marcospereirampj / python-keycloak

MIT License
692 stars 296 forks source link

Authentication error when calling get_client_id #571

Closed ryan-lake closed 1 month ago

ryan-lake commented 1 month ago

This started with 4.1.0.

The code

keycloak_master_admin = KeycloakAdmin(server_url="https://auth.*****/auth",realm_name="master",client_id="admin-cli",        client_secret_key="***",    )
keycloak_master_admin.change_current_realm("internal_admin_realm")
client_id = keycloak_master_admin.get_client_id("admin-cli")

The call to get_client_id fails to authenticate with keycloak, getting a 401. The calls before this (the creation of the admin client and the realm change succeed without error).

In 4.0.1 and before this code runs fine. Keycloak only shows an unknown user failed authentication.

[ERROR] KeycloakAuthenticationError: 401: b'
{
    "error": "unauthorized_client",
    "error_description": "Invalid client or Invalid client credentials"
}
'
Traceback (most recent call last):
  File "/var/task/tenant_authorizer.py", line 36, in handler
    realm, principal_id, user_name, roles = validateToken(token, tenant_row)
  File "/var/task/tenant_authorizer.py", line 126, in validateToken
    client_id = keycloak_master_admin.get_client_id("admin-cli")
  File "/opt/python/keycloak/keycloak_admin.py", line 1319, in get_client_id
    data_raw = self.connection.raw_get(
  File "/opt/python/keycloak/openid_connection.py", line 358, in raw_get
    self._refresh_if_required()
  File "/opt/python/keycloak/openid_connection.py", line 343, in _refresh_if_required
    self.refresh_token()
  File "/opt/python/keycloak/openid_connection.py", line 326, in refresh_token
    self.get_token()
  File "/opt/python/keycloak/openid_connection.py", line 313, in get_token
    self.token = self.keycloak_openid.token(
  File "/opt/python/keycloak/keycloak_openid.py", line 326, in token
    return raise_error_from_response(data_raw, KeycloakPostError)
  File "/opt/python/keycloak/exceptions.py", line 192, in raise_error_from_response
    raise error(
ryshoooo commented 1 month ago

Hi @ryan-lake

Keycloak 4.1.0 comes with a behavioral change in KeycloakAdmin. Upon KeyclokAdmin's initialization, we no longer fetch the access + refresh token, that is something that happens upon the first API request (get_client_id in your case). Unfortunately in your case, you change the realm before that call happens, meaning the credentials are going to be fetched from internal_admin_realm instead of master realm, so you get a 401.

A quick fix for you is to add keycloak_master_admin.connection.get_token() call before the change_current_realm.

However, I overall just do not like this behavior (that changing the realm gets you into 401/403 state). It does mean that refresh token won't work either as the realm is changed, so you'll after some time reach 401 later anyway unless changed back to the master realm.

We overall need a better handling of changing realms, such that it keeps the same realm for credentials fetch and refresh.

ryan-lake commented 1 month ago

Thank you for the reply, that makes sense.