How to make a dockerized keycloak communicate with the flask project on localhost (With CIBA Poll Mode Enabled)

81 views Asked by At

What I want to do:

What I am trying to do is, a user registers via my flask endpoint lets call it /register, which works on localhost:5000, a dokerized keycloak is being used to handle everything related to authentication and autherization via port 9090, I then generate a link, that includes elements from CIBA so that the user authenticates himself after he recieves the link via email my presumed code to generate the email to send

auth_req_id = response["auth_req_id"] if "auth_req_id" in response else "None"
verification_link = config.decrypted_login_ciba_url + "?token=" + auth_req_id + "&email=" + user_email

The CIBA part is not working at all, when I attempt to get the auth_req_id via this code

ciba_request_url = "{}realms/{}/protocols/openid-connect/ext/ciba/auth".format(decrypted_keycloak_server_url, decrypted_keycloak_master_realm)

        payload = {
            "client_id": decrypted_keycloak_client_id,
            "client_secret": decrypted_keycloak_client_secret_key,
            "login_hint": login_hint,
            "scope": "profile",
            "binding_message": "this is a binding message"
        }


        headers = {"Content-Type": "application/x-www-form-urlencoded"}

        response = requests.request(method="POST", url=ciba_request_url, headers=headers, data=payload)

Its failing and returning an error without any logs in the keycloak server. After attempting to call the keycloak endpoint directly from postman I got the following error:

{
    "error": "server_error",
    "error_description": "Failed to send authentication request"
}

Do note that if I supply the login_hint of a user that does not exist, I get the following expected error, which means the keycloak server is functioning correctly:

{
    "error": "invalid_request",
    "error_description": "invalid user"
}

How I configured stuff:

I have set up my keycloak using this docker compose:

version: '3'

services:
  dev-keycloak:
    image: quay.io/keycloak/keycloak:18.0.2
    command:
      - start-dev
    # env_file:
    #    - basekeycloakenviroment.env
    environment:
        - KEYCLOAK_ADMIN=admin
        - KEYCLOAK_ADMIN_PASSWORD=admin
        - KC_HTTP_ENABLED=true
        - KC_FEATURES="preview, account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, authorization, ciba, client-policies, client-secret-rotation, declarative-user-profile, device-flow, docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, linkedin-oauth, map-storage, multi-site, par, preview, recovery-codes, scripts, step-up-authentication, token-exchange, transient-users, update-email, web-authn"
        - KC_SPI_CIBA_AUTH_CHANNEL_CIBA_HTTP_AUTH_CHANNEL_HTTP_AUTHENTICATION_CHANNEL_URI=http://host.docker.internal:5000/login-callback
        - JAVA_OPTS_APPEND=-Dkeycloak.profile.feature.admin_fine_grained_authz=enabled
    ports:
      - "9090:8080"
    volumes:
        - keycloak_data:/opt/keycloak/data
    networks:
      - keycloaknetwork

networks:
  keycloaknetwork:
    driver: bridge

volumes:
   keycloak_data:
    name: keycloak_data_volume

I have also set up my CIBA configurations in the keylcloak UI as follows: Authentication tab Client realm options

I set up the endpoint login-callback in my flask app as follows(its a simple testing endpoint):

class CIBAResource2(Resource):
    def post(self):
        # Here, you would handle the notification from Keycloak.
        # For now, let's just print the received data to the console.
        data = request.json
        print("Received notification from Keycloak:", data)
        return "Notification received", 201

api.add_resource(CIBAResource2, '/login-callback')

my flask app can communicate with the dockerized keycloak normally without any problem, I can authenticate a user and everything without using CIBA, via basic username/password that generates a token.

The issue:

Now the opposite is not true especially when testing CIBA:

First attempt, I tested via the flask application, and it returned an error, no logs showed on keycloak.

Second attempt, I checked via postman directly using the keycloak pre-built endpoints, this is the curl I tested via postman:

curl --location --request POST 'http://localhost:9090/realms/realm-1/protocol/openid-
connect/ext/ciba/auth' \
--header 'User-Agent: Apidog/1.0.0 (https://apidog.com)' \
--data-urlencode 'client_id=realm-1-client-1' \
--data-urlencode 'client_secret=yQ7IJglc3WZ3M3PBkt9CHp1gYP0freUC' \
--data-urlencode 'login_hint=employee1' \
--data-urlencode 'scope=profile email' \
--data-urlencode 'binding_message=callback'

it also did not work, but returned this error with status code= 503 and no logs were showing on keycloak:

{
    "error": "server_error",
    "error_description": "Failed to send authentication request"
}

After doing some digging, I discovered this stackoverflow question: Keycloak CIBA Authentication fails with "Failed to send authentication request" for the same error, but it did not help at all

Third attempt, I had the idea to test the curl for localhost:5000/login-callback directly from dockerized keycloak terminal, at first it did not work, the reason why it did not work is I discovered that docker quarantines the container inside, while I exposed port 8080 and mapped it to 9090 for communicting into the docker container, localhost does not work when communicating from the container to the outside, this is where I discovered host.docker.internal. When I called via curl http://host.docker.internal:5000/login-callback I managed to get a result back, and it worked at least in curl in the docker container terminal.

After the third solution, I thought perhaps I need to change KC_SPI_CIBA_AUTH_CHANNEL_CIBA_HTTP_AUTH_CHANNEL_HTTP_AUTHENTICATION_CHANNEL_URI = localhost:5000/login-callback to host.docker.internal:5000/login-callback and I repeated the same attempted, but still it does not work, when I attempt to apply the keycloak endpoint I still get the same error, so, what am I doing wrong here, I think the issue is related to Docker or something, or perhaps its related to CIBA configurations, or even both, but I cant put my finger on what it is, this has been the 5th day attempting to figure it out.

0

There are 0 answers