From 11e4a12c83754bf6a7ffe95f6bcc80266113b0a9 Mon Sep 17 00:00:00 2001 From: Adrian_Cin Date: Mon, 14 Jun 2021 16:17:47 +0700 Subject: [PATCH 01/10] Correct public key format Keycloak returns public key in PEM format --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63abe49..28b218d 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ token_rpt_info = keycloak_openid.introspect(keycloak_openid.introspect(token['ac token_info = keycloak_openid.introspect(token['access_token']) # Decode Token -KEYCLOAK_PUBLIC_KEY = keycloak_openid.public_key() +KEYCLOAK_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" + keycloak_openid.public_key() + "\n-----END PUBLIC KEY-----" options = {"verify_signature": True, "verify_aud": True, "verify_exp": True} token_info = keycloak_openid.decode_token(token['access_token'], key=KEYCLOAK_PUBLIC_KEY, options=options) From 31b4efd7ab903354bb844d9eec1671dbdaa9dbf0 Mon Sep 17 00:00:00 2001 From: bostonkenne Date: Thu, 17 Jun 2021 15:51:11 +0100 Subject: [PATCH 02/10] add remove user realm role --- keycloak/keycloak_admin.py | 15 ++++++++++++++- keycloak/urls_patterns.py | 4 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index ffb5968..4272482 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -47,7 +47,8 @@ from .urls_patterns import URL_ADMIN_SERVER_INFO, URL_ADMIN_CLIENT_AUTHZ_RESOURC URL_ADMIN_REALM_ROLES_MEMBERS, URL_ADMIN_CLIENT_PROTOCOL_MAPPER, URL_ADMIN_CLIENT_SCOPES_MAPPERS, \ URL_ADMIN_FLOWS_EXECUTIONS_EXEUCUTION, URL_ADMIN_FLOWS_EXECUTIONS_FLOW, URL_ADMIN_FLOWS_COPY, \ URL_ADMIN_FLOWS_ALIAS, URL_ADMIN_CLIENT_SERVICE_ACCOUNT_USER, URL_ADMIN_AUTHENTICATOR_CONFIG, \ - URL_ADMIN_CLIENT_ROLES_COMPOSITE_CLIENT_ROLE, URL_ADMIN_CLIENT_ALL_SESSIONS, URL_ADMIN_EVENTS + URL_ADMIN_CLIENT_ROLES_COMPOSITE_CLIENT_ROLE, URL_ADMIN_CLIENT_ALL_SESSIONS, URL_ADMIN_EVENTS,\ + URL_ADMIN_DELETE_USER_ROLE class KeycloakAdmin: @@ -1878,3 +1879,15 @@ class KeycloakAdmin: params_path = {"realm-name": self.realm_name, "id": client_id} data_raw = self.connection.raw_get(URL_ADMIN_CLIENT_ALL_SESSIONS.format(**params_path)) return raise_error_from_response(data_raw, KeycloakGetError) + + + def delete_user_realm_role(self, user_id, payload): + """ + Delete realm-level role mappings + DELETE admin/realms/{realm-name}/users/{id}/role-mappings/realm + + """ + params_path = {"realm-name": self.realm_name, "id": str(user_id) } + data_raw = self.connection.raw_delete(URL_ADMIN_DELETE_USER_ROLE.format(**params_path), + data=json.dumps(payload)) + return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204) \ No newline at end of file diff --git a/keycloak/urls_patterns.py b/keycloak/urls_patterns.py index 8dfbadb..460ae8b 100644 --- a/keycloak/urls_patterns.py +++ b/keycloak/urls_patterns.py @@ -105,4 +105,6 @@ URL_ADMIN_KEYS = "admin/realms/{realm-name}/keys" URL_ADMIN_USER_FEDERATED_IDENTITIES = "admin/realms/{realm-name}/users/{id}/federated-identity" URL_ADMIN_USER_FEDERATED_IDENTITY = "admin/realms/{realm-name}/users/{id}/federated-identity/{provider}" -URL_ADMIN_EVENTS = 'admin/realms/{realm-name}/events' \ No newline at end of file +URL_ADMIN_EVENTS = 'admin/realms/{realm-name}/events' + +URL_ADMIN_DELETE_USER_ROLE = "admin/realms/{realm-name}/users/{id}/role-mappings/realm" \ No newline at end of file From d7d661a38c7a6bf5daaea513616f4f9936460bef Mon Sep 17 00:00:00 2001 From: bostonkenne Date: Thu, 17 Jun 2021 15:53:16 +0100 Subject: [PATCH 03/10] fix json response --- keycloak/keycloak_admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index 4272482..15ee759 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -1890,4 +1890,4 @@ class KeycloakAdmin: params_path = {"realm-name": self.realm_name, "id": str(user_id) } data_raw = self.connection.raw_delete(URL_ADMIN_DELETE_USER_ROLE.format(**params_path), data=json.dumps(payload)) - return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204) \ No newline at end of file + return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204]) \ No newline at end of file From 8f6de6c3c84faaf354484811160c8d95c33ee3c8 Mon Sep 17 00:00:00 2001 From: Yannick Chabbert Date: Mon, 28 Jun 2021 15:42:54 +0200 Subject: [PATCH 04/10] openid - minor typo fix, change nothing yet --- keycloak/keycloak_openid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keycloak/keycloak_openid.py b/keycloak/keycloak_openid.py index 0f801ea..197dd26 100644 --- a/keycloak/keycloak_openid.py +++ b/keycloak/keycloak_openid.py @@ -189,7 +189,7 @@ class KeycloakOpenID: payload = {"username": username, "password": password, "client_id": self.client_id, "grant_type": grant_type, "code": code, "redirect_uri": redirect_uri} - if payload: + if extra: payload.update(extra) if totp: From 44fe7b714aa08743fc95a8de5d9ea469dabb2799 Mon Sep 17 00:00:00 2001 From: Manjeetsinh Alonja Date: Fri, 9 Jul 2021 11:33:35 +0530 Subject: [PATCH 05/10] Added realm partial export feature --- keycloak/keycloak_admin.py | 13 ++++++++++++- keycloak/urls_patterns.py | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index ffb5968..41f71eb 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -47,7 +47,8 @@ from .urls_patterns import URL_ADMIN_SERVER_INFO, URL_ADMIN_CLIENT_AUTHZ_RESOURC URL_ADMIN_REALM_ROLES_MEMBERS, URL_ADMIN_CLIENT_PROTOCOL_MAPPER, URL_ADMIN_CLIENT_SCOPES_MAPPERS, \ URL_ADMIN_FLOWS_EXECUTIONS_EXEUCUTION, URL_ADMIN_FLOWS_EXECUTIONS_FLOW, URL_ADMIN_FLOWS_COPY, \ URL_ADMIN_FLOWS_ALIAS, URL_ADMIN_CLIENT_SERVICE_ACCOUNT_USER, URL_ADMIN_AUTHENTICATOR_CONFIG, \ - URL_ADMIN_CLIENT_ROLES_COMPOSITE_CLIENT_ROLE, URL_ADMIN_CLIENT_ALL_SESSIONS, URL_ADMIN_EVENTS + URL_ADMIN_CLIENT_ROLES_COMPOSITE_CLIENT_ROLE, URL_ADMIN_CLIENT_ALL_SESSIONS, URL_ADMIN_EVENTS, \ + URL_ADMIN_REALM_EXPORT class KeycloakAdmin: @@ -242,6 +243,16 @@ class KeycloakAdmin: data=json.dumps(payload)) return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[201]) + def export_realm(self, export_clients=False, export_groups_and_role=False): + """ + Export the realm configurations in the json format + + :return: realm configurations JSON + """ + params_path = {"realm-name": self.realm_name, "export-clients": export_clients, "export-groups-and-roles": export_groups_and_role } + data_raw = self.raw_post(URL_ADMIN_REALM_EXPORT.format(**params_path), data="") + return raise_error_from_response(data_raw, KeycloakGetError) + def get_realms(self): """ Lists all realms in Keycloak deployment diff --git a/keycloak/urls_patterns.py b/keycloak/urls_patterns.py index 8dfbadb..65ffbeb 100644 --- a/keycloak/urls_patterns.py +++ b/keycloak/urls_patterns.py @@ -89,6 +89,7 @@ URL_ADMIN_IDP_MAPPERS = "admin/realms/{realm-name}/identity-provider/instances/{ URL_ADMIN_IDP = "admin/realms//{realm-name}/identity-provider/instances/{alias}" URL_ADMIN_REALM_ROLES_ROLE_BY_NAME = "admin/realms/{realm-name}/roles/{role-name}" URL_ADMIN_REALM_ROLES_COMPOSITE_REALM_ROLE = "admin/realms/{realm-name}/roles/{role-name}/composites" +URL_ADMIN_REALM_EXPORT = "admin/realms/{realm-name}/partial-export?exportClients={export-clients}&exportGroupsAndRoles={export-groups-and-roles}" URL_ADMIN_FLOWS = "admin/realms/{realm-name}/authentication/flows" URL_ADMIN_FLOWS_ALIAS = "admin/realms/{realm-name}/authentication/flows/{flow-id}" From 71a92f8b4911edfc0f7c26b6829ce519a44e9979 Mon Sep 17 00:00:00 2001 From: Manjeetsinh Alonja Date: Fri, 9 Jul 2021 12:05:58 +0530 Subject: [PATCH 06/10] Fix feature function documents --- keycloak/keycloak_admin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index 41f71eb..3abf55b 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -247,6 +247,12 @@ class KeycloakAdmin: """ Export the realm configurations in the json format + RealmRepresentation + https://www.keycloak.org/docs-api/5.0/rest-api/index.html#_partialexport + + :param export-clients: Skip if not want to export realm clients + :param export-groups-and-roles: Skip if not want to export realm groups and roles + :return: realm configurations JSON """ params_path = {"realm-name": self.realm_name, "export-clients": export_clients, "export-groups-and-roles": export_groups_and_role } From 227b698b3fd1552fbac9d0e619d2ff3640ddcf8a Mon Sep 17 00:00:00 2001 From: Michael Kao Date: Tue, 20 Jul 2021 17:23:44 +0200 Subject: [PATCH 07/10] Stopping pagination requests if response count is lower than page size. --- keycloak/keycloak_admin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index ffb5968..e018dbc 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -223,6 +223,8 @@ class KeycloakAdmin: if not partial_results: break results.extend(partial_results) + if len(partial_results) < query['max']: + break page += 1 return results From a9b39248543b521fe2a5936fe09b3d8509d681c0 Mon Sep 17 00:00:00 2001 From: Jacky Boen Date: Mon, 2 Aug 2021 10:27:17 +0800 Subject: [PATCH 08/10] Fix KeycloakAdmin using wrong realm when authenticating with a service account Signed-off-by: Jacky Boen --- keycloak/keycloak_admin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index ffb5968..5feceaf 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -1827,14 +1827,17 @@ class KeycloakAdmin: return r def get_token(self): + token_realm_name = 'master' if self.client_secret_key else self.user_realm_name or self.realm_name self.keycloak_openid = KeycloakOpenID(server_url=self.server_url, client_id=self.client_id, - realm_name=self.user_realm_name or self.realm_name, verify=self.verify, + realm_name=token_realm_name, verify=self.verify, client_secret_key=self.client_secret_key, custom_headers=self.custom_headers) grant_type = ["password"] if self.client_secret_key: grant_type = ["client_credentials"] + if self.user_realm_name: + self.realm_name = self.user_realm_name self._token = self.keycloak_openid.token(self.username, self.password, grant_type=grant_type) From bd8af2924e8b479428a4f2ee3000cbf9bba0e7bf Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Wed, 18 Aug 2021 00:45:53 +0200 Subject: [PATCH 09/10] feat: add KeycloakAdmin.set_events --- keycloak/keycloak_admin.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index ffb5968..0344721 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -1774,6 +1774,20 @@ class KeycloakAdmin: data=None, **query) return raise_error_from_response(data_raw, KeycloakGetError) + def set_events(self, payload): + """ + Set realm events configuration + + RealmEventsConfigRepresentation + https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_realmeventsconfigrepresentation + + :return: Http response + """ + params_path = {"realm-name": self.realm_name} + data_raw = self.raw_put(URL_ADMIN_EVENTS.format(**params_path), + data=json.dumps(payload)) + return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204]) + def raw_get(self, *args, **kwargs): """ Calls connection.raw_get. From 81b12d2d556883f5770e81818b9e3f5eb666a10b Mon Sep 17 00:00:00 2001 From: Bas van der Linden <33874522+BvdLind@users.noreply.github.com> Date: Thu, 19 Aug 2021 19:50:37 +0200 Subject: [PATCH 10/10] Update README example create_client_role syntax In the README the `create_client_role` function has a `client_id` argument, but in [keycloak_admin.py](https://github.com/marcospereirampj/python-keycloak/blob/0ebcf990941f600e6ff562091a81cbeafbd21f3e/keycloak/keycloak_admin.py#L1001) `client_role_id` seems to be used instead. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63abe49..d076555 100644 --- a/README.md +++ b/README.md @@ -215,7 +215,7 @@ role = keycloak_admin.get_client_role(client_id="client_id", role_name="role_nam role_id = keycloak_admin.get_client_role_id(client_id="client_id", role_name="test") # Create client role -keycloak_admin.create_client_role(client_id='client_id', {'name': 'roleName', 'clientRole': True}) +keycloak_admin.create_client_role(client_role_id='client_id', {'name': 'roleName', 'clientRole': True}) # Assign client role to user. Note that BOTH role_name and role_id appear to be required. keycloak_admin.assign_client_role(client_id="client_id", user_id="user_id", role_id="role_id", role_name="test")