From 0ccc9d3575e02153571d71f26834b96cb8f6dd54 Mon Sep 17 00:00:00 2001 From: kaiyou <pierre@jaury.eu> Date: Tue, 17 Mar 2020 12:26:17 +0100 Subject: [PATCH] Add the ability to configure special OIDC mappings --- hiboo/sso/forms.py | 6 ++++++ hiboo/sso/oidc.py | 36 +++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/hiboo/sso/forms.py b/hiboo/sso/forms.py index 9f76b3b3..98a7994a 100644 --- a/hiboo/sso/forms.py +++ b/hiboo/sso/forms.py @@ -39,4 +39,10 @@ class OIDCForm(flask_wtf.FlaskForm): ("id_token token", _("Id token and token")) ] ) + special_mappings = fields.SelectMultipleField( + _('Enabled special claim mappings'), choices=[ + ("mask_sub_uuid", _("Mask the profile uuid")), + ("original_email", _("Return the actual user email")) + ] + ) submit = fields.SubmitField(_('Submit')) diff --git a/hiboo/sso/oidc.py b/hiboo/sso/oidc.py index 7019dce1..dd9a77f1 100644 --- a/hiboo/sso/oidc.py +++ b/hiboo/sso/oidc.py @@ -14,6 +14,7 @@ from hiboo import models, utils, profile import flask import time +import inspect class Config(object): @@ -36,7 +37,8 @@ class Config(object): "token_endpoint_auth_method": form.token_endpoint_auth_method.data, "redirect_uris": [form.redirect_uri.data], "grant_types": form.grant_types.data, - "response_types": form.response_types.data + "response_types": form.response_types.data, + "special_mappings": form.special_mappings.data }) cls.update_client(service) @@ -47,7 +49,8 @@ class Config(object): token_endpoint_auth_method=service.config.get("token_endpoint_auth_method"), redirect_uri=service.config.get("redirect_uris", [""])[0], grant_types=service.config.get("grant_types", ["authorization_code"]), - response_types=service.config.get("response_types", ["code"]) + response_types=service.config.get("response_types", ["code"]), + special_mappings=service.config.get("special_mappings", []) ) @classmethod @@ -70,11 +73,11 @@ class AuthorizationCodeMixin(object): # Authorization code object for redis storage AuthorizationCode = type("AuthorizationCode", (utils.SerializableObj, sqla_oauth2.OAuth2AuthorizationCodeMixin), {}) - def create_authorization_code(self, client, grant_user, request): + def create_authorization_code(self, client, profile, request): obj = AuthorizationCodeMixin.AuthorizationCode( code=security.generate_token(48), nonce=request.data.get("nonce") or "", client_id=client.client_id, redirect_uri=request.redirect_uri, - scope=request.scope, user_id=grant_user.uuid, + scope=request.scope, user_id=profile.uuid, auth_time=int(time.time()) ) utils.redis.hmset("code:{}".format(obj.code), obj.serialize()) @@ -112,8 +115,8 @@ class OpenIDMixin(object): def get_jwt_config(self, grant=None): return self.get_client().get_jwt_config() - def generate_user_info(self, user, scope): - return self.get_client().generate_user_info(user, scope) + def generate_user_info(self, profile, scope): + return self.get_client().generate_user_info(profile, scope) class Client(sqla_oauth2.OAuth2ClientMixin): @@ -160,13 +163,24 @@ class Client(sqla_oauth2.OAuth2ClientMixin): 'exp': 3600, } - def generate_user_info(self, user, scope): + def generate_user_info(self, profile, scope): """ User info generation function used by the oidc code mixin and the userinfo endpoint """ - return oidc.UserInfo( - sub=user.uuid, name=user.username, prefered_username=user.username, - login=user.username, email=user.email - ) + special_mappings = self.service.config.get("special_mappings", []) + claims = dict() + if "openid" in scope: + claims.update( + sub=profile.username if "mask_sub_uuid" in special_mappings else profile.uuid, + name=profile.username, + preferred_username=profile.username, + login=profile.username + ) + if "email" in scope: + user_email = profile.user.contact.get("email") + claims.update( + email=user_email if "original_email" in special_mappings else profile.email + ) + return oidc.UserInfo(**claims) def generate_token(self, client, grant_type, user=None, scope=None, expires_in=None, include_refresh_token=False): """ Specific token generation function to help keep track of the profile associated with a token -- GitLab