From 1c4c48a490366749a593b879edd788579a6b20d9 Mon Sep 17 00:00:00 2001 From: Shirkanesi Date: Thu, 1 Aug 2024 12:58:52 +0200 Subject: [PATCH 1/5] Allow specification of attribute for domain in KeycloakClient --- apricot/oauth/keycloak_client.py | 3 +++ run.py | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/apricot/oauth/keycloak_client.py b/apricot/oauth/keycloak_client.py index 3555610..3e00cfa 100644 --- a/apricot/oauth/keycloak_client.py +++ b/apricot/oauth/keycloak_client.py @@ -17,6 +17,7 @@ def __init__( self: Self, keycloak_base_url: str, keycloak_realm: str, + keycloak_domain_attribute: str, **kwargs: Any, ) -> None: """Initialise a KeycloakClient. @@ -26,6 +27,7 @@ def __init__( """ self.base_url = keycloak_base_url self.realm = keycloak_realm + self.domain_attribute = keycloak_domain_attribute redirect_uri = "urn:ietf:wg:oauth:2.0:oob" # this is the "no redirect" URL scopes: list[str] = [] # this is the default scope @@ -162,6 +164,7 @@ def users(self: Self) -> list[JSONDict]: attributes["oauth_id"] = user_dict.get("id", None) attributes["sn"] = last_name or "" attributes["uidNumber"] = user_dict["attributes"]["uid"][0] + attributes["domain"] = user_dict["attributes"].get(self.domain_attribute, [None])[0] output.append(attributes) except KeyError: pass diff --git a/run.py b/run.py index cd1b1a5..9df97e4 100644 --- a/run.py +++ b/run.py @@ -82,6 +82,12 @@ type=str, help="Keycloak Realm.", ) + keycloak_group.add_argument( + "--keycloak-domain-attribute", + type=str, + default="domain", + help="The attribute in Keycloak that contains the users' domain.", + ) # Options for Redis cache redis_group = parser.add_argument_group("Redis") redis_group.add_argument( From 5bad298adc50eff5261e1421dfdd00324c4e2c0f Mon Sep 17 00:00:00 2001 From: Shirkanesi Date: Thu, 1 Aug 2024 13:28:59 +0200 Subject: [PATCH 2/5] ADD documentation for --keycloak-domain-attribute --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8911e95..aab244e 100644 --- a/README.md +++ b/README.md @@ -200,12 +200,27 @@ Do this as follows: You will need to use the following command line arguments: ```bash ---backend Keycloak --keycloak-base-url "/" --keycloak-realm "" +--backend Keycloak --keycloak-base-url "/" --keycloak-realm "" --keycloak-domain-attribute "" ``` You will need to register an application to interact with `Keycloak`. Do this as follows: +- Under the realm option `Client scopes` create a new scope, e.g. `domainScope` with: + - Type: `Default` + - Include in token scope: `true` + - Save +- In the created scope click `Mappers` > `Configure new mapper` and now create either + - `Hardcoded claim` + - => Every user gets the same domain + - name: `domain` + - token claim name: `domain` + - claim value: `` + - `User attribute` + - => Every user has an attribute for the domain + - name: `domain` + - user attribute: `` + - token claim name: `domain` - Create a new `Client` in your `Keycloak` instance. - Set the name to whatever you choose (e.g. `apricot`) - Enable `Client authentication` @@ -220,3 +235,5 @@ Do this as follows: - `realm-management` > `manage-users` - `realm-management` > `query-groups` - `realm-management` > `query-users` +- Under `Client scopes` click `Add client scope` > `domainScope`. Make sure to select type `Default` + From 64dbbc7959f73d69acd65bbedcbbbe622bc74b5c Mon Sep 17 00:00:00 2001 From: James Robinson Date: Wed, 23 Oct 2024 13:47:18 +0100 Subject: [PATCH 3/5] :memo: Reformat Keycloak docs --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aab244e..3ed3bab 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,8 @@ Instructions for specific OpenID Connect backends below. You will need to use the following command line arguments: ```bash ---backend MicrosoftEntra --entra-tenant-id "" +--backend MicrosoftEntra \ +--entra-tenant-id "" ``` You will need to register an application to interact with `Microsoft Entra`. @@ -200,7 +201,10 @@ Do this as follows: You will need to use the following command line arguments: ```bash ---backend Keycloak --keycloak-base-url "/" --keycloak-realm "" --keycloak-domain-attribute "" +--backend Keycloak \ +--keycloak-base-url "/" \ +--keycloak-domain-attribute "" \ +--keycloak-realm "" ``` You will need to register an application to interact with `Keycloak`. @@ -219,7 +223,7 @@ Do this as follows: - `User attribute` - => Every user has an attribute for the domain - name: `domain` - - user attribute: `` + - user attribute: `` - token claim name: `domain` - Create a new `Client` in your `Keycloak` instance. - Set the name to whatever you choose (e.g. `apricot`) @@ -236,4 +240,3 @@ Do this as follows: - `realm-management` > `query-groups` - `realm-management` > `query-users` - Under `Client scopes` click `Add client scope` > `domainScope`. Make sure to select type `Default` - From 15c764187283fd6a599d8c163523d06dfa1886fa Mon Sep 17 00:00:00 2001 From: James Robinson Date: Wed, 23 Oct 2024 13:49:55 +0100 Subject: [PATCH 4/5] :recycle: Alphabetise Keycloak attributes --- apricot/oauth/keycloak_client.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apricot/oauth/keycloak_client.py b/apricot/oauth/keycloak_client.py index 3e00cfa..ed94923 100644 --- a/apricot/oauth/keycloak_client.py +++ b/apricot/oauth/keycloak_client.py @@ -16,18 +16,19 @@ class KeycloakClient(OAuthClient): def __init__( self: Self, keycloak_base_url: str, - keycloak_realm: str, keycloak_domain_attribute: str, + keycloak_realm: str, **kwargs: Any, ) -> None: """Initialise a KeycloakClient. @param keycloak_base_url: Base URL for Keycloak server + @param keycloak_domain_attribute: Keycloak attribute used to define your domain @param keycloak_realm: Realm for Keycloak server """ self.base_url = keycloak_base_url - self.realm = keycloak_realm self.domain_attribute = keycloak_domain_attribute + self.realm = keycloak_realm redirect_uri = "urn:ietf:wg:oauth:2.0:oob" # this is the "no redirect" URL scopes: list[str] = [] # this is the default scope @@ -153,18 +154,18 @@ def users(self: Self) -> list[JSONDict]: username = user_dict.get("username") attributes: JSONDict = {} attributes["cn"] = username - attributes["uid"] = username - attributes["oauth_username"] = username - attributes["displayName"] = full_name - attributes["mail"] = user_dict.get("email") attributes["description"] = "" + attributes["displayName"] = full_name + attributes["domain"] = user_dict["attributes"].get(self.domain_attribute, [None])[0] attributes["gidNumber"] = user_dict["attributes"]["uid"][0] attributes["givenName"] = first_name or "" attributes["homeDirectory"] = f"/home/{username}" if username else None + attributes["mail"] = user_dict.get("email") attributes["oauth_id"] = user_dict.get("id", None) + attributes["oauth_username"] = username attributes["sn"] = last_name or "" + attributes["uid"] = username attributes["uidNumber"] = user_dict["attributes"]["uid"][0] - attributes["domain"] = user_dict["attributes"].get(self.domain_attribute, [None])[0] output.append(attributes) except KeyError: pass From 62d8b6f5b6017a2bec52a2fd2b803a9cacf53756 Mon Sep 17 00:00:00 2001 From: James Robinson Date: Wed, 23 Oct 2024 14:00:17 +0100 Subject: [PATCH 5/5] :rotating_light: Fix linting issues --- apricot/oauth/keycloak_client.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apricot/oauth/keycloak_client.py b/apricot/oauth/keycloak_client.py index ed94923..54ddaaa 100644 --- a/apricot/oauth/keycloak_client.py +++ b/apricot/oauth/keycloak_client.py @@ -156,7 +156,10 @@ def users(self: Self) -> list[JSONDict]: attributes["cn"] = username attributes["description"] = "" attributes["displayName"] = full_name - attributes["domain"] = user_dict["attributes"].get(self.domain_attribute, [None])[0] + attributes["domain"] = user_dict["attributes"].get( + self.domain_attribute, + [None], + )[0] attributes["gidNumber"] = user_dict["attributes"]["uid"][0] attributes["givenName"] = first_name or "" attributes["homeDirectory"] = f"/home/{username}" if username else None