From cd51c6a4f001aefcf30b9da26c7986893fc35851 Mon Sep 17 00:00:00 2001 From: psrok1 Date: Mon, 19 Aug 2024 16:56:25 +0200 Subject: [PATCH] OIDC: Fetch userinfo claims from userinfo endpoint --- docker-compose-oidc-dev.yml | 1 + mwdb/resources/oauth.py | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docker-compose-oidc-dev.yml b/docker-compose-oidc-dev.yml index 21e2145f7..0e8a046d0 100644 --- a/docker-compose-oidc-dev.yml +++ b/docker-compose-oidc-dev.yml @@ -85,5 +85,6 @@ services: environment: KEYCLOAK_DATABASE_HOST: keycloak_postgres KEYCLOAK_DATABASE_PASSWORD: bn_keycloak_password + KEYCLOAK_HOSTNAME: "http://127.0.0.1:8080" ports: - "127.0.0.1:8080:8080" diff --git a/mwdb/resources/oauth.py b/mwdb/resources/oauth.py index 1dcbac103..e6fa8c0e4 100644 --- a/mwdb/resources/oauth.py +++ b/mwdb/resources/oauth.py @@ -372,14 +372,14 @@ def post(self, provider_name): obj = loads_schema(request.get_data(as_text=True), schema) redirect_uri = f"{app_config.mwdb.base_url}/oauth/callback" oidc_client = provider.get_oidc_client() - userinfo = oidc_client.fetch_id_token( + id_token_claims = oidc_client.fetch_id_token( obj["code"], obj["state"], obj["nonce"], redirect_uri ) # 'sub' bind should be used instead of 'name' identity = ( db.session.query(OpenIDUserIdentity) .filter( - OpenIDUserIdentity.sub_id == userinfo["sub"], + OpenIDUserIdentity.sub_id == id_token_claims["sub"], OpenIDUserIdentity.provider_id == provider.id, ) .first() @@ -435,7 +435,7 @@ def post(self, provider_name): obj = loads_schema(request.get_data(as_text=True), schema) redirect_uri = f"{app_config.mwdb.base_url}/oauth/callback" oidc_client = provider.get_oidc_client() - userinfo = oidc_client.fetch_id_token( + id_token_claims = oidc_client.fetch_id_token( obj["code"], obj["state"], obj["nonce"], redirect_uri ) # register user with information from provider @@ -443,12 +443,13 @@ def post(self, provider_name): exists().where( and_( OpenIDUserIdentity.provider_id == provider.id, - OpenIDUserIdentity.sub_id == userinfo["sub"], + OpenIDUserIdentity.sub_id == id_token_claims["sub"], ) ) ).scalar(): raise Conflict("User is already bound with selected provider.") + userinfo = oidc_client.userinfo() login_claims = ["preferred_username", "nickname", "name"] for claim in login_claims: @@ -468,13 +469,15 @@ def post(self, provider_name): # If no candidates in claims: try fallback login else: # If no candidates in claims: try fallback login - sub_md5 = hashlib.md5(userinfo["sub"].encode("utf-8")).hexdigest()[:8] + sub_md5 = hashlib.md5(id_token_claims["sub"].encode("utf-8")).hexdigest()[ + :8 + ] username = f"{provider_name}-{sub_md5}" if "email" in userinfo.keys(): user_email = userinfo["email"] else: - user_email = f'{userinfo["sub"]}@mwdb.local' + user_email = f'{id_token_claims["sub"]}@mwdb.local' user = User.create( username, @@ -483,7 +486,7 @@ def post(self, provider_name): ) identity = OpenIDUserIdentity( - sub_id=userinfo["sub"], provider_id=provider.id, user_id=user.id + sub_id=id_token_claims["sub"], provider_id=provider.id, user_id=user.id ) if not group.add_member(user): @@ -567,7 +570,7 @@ def post(self, provider_name): obj = loads_schema(request.get_data(as_text=True), schema) redirect_uri = f"{app_config.mwdb.base_url}/oauth/callback" oidc_client = provider.get_oidc_client() - userinfo = oidc_client.fetch_id_token( + id_token_claims = oidc_client.fetch_id_token( obj["code"], obj["state"], obj["nonce"], redirect_uri ) if db.session.query( @@ -576,7 +579,7 @@ def post(self, provider_name): OpenIDUserIdentity.provider_id == provider.id, or_( OpenIDUserIdentity.user_id == g.auth_user.id, - OpenIDUserIdentity.sub_id == userinfo["sub"], + OpenIDUserIdentity.sub_id == id_token_claims["sub"], ), ) ) @@ -584,7 +587,9 @@ def post(self, provider_name): raise Conflict("Provider identity is already bound with mwdb account.") identity = OpenIDUserIdentity( - sub_id=userinfo["sub"], provider_id=provider.id, user_id=g.auth_user.id + sub_id=id_token_claims["sub"], + provider_id=provider.id, + user_id=g.auth_user.id, ) if not group.add_member(g.auth_user):