diff --git a/apps/authentication/backends/oidc/backends.py b/apps/authentication/backends/oidc/backends.py index daa614ec8..ec5765510 100644 --- a/apps/authentication/backends/oidc/backends.py +++ b/apps/authentication/backends/oidc/backends.py @@ -18,6 +18,7 @@ from django.urls import reverse from django.conf import settings from common.utils import get_logger +from users.utils import construct_user_email from ..base import JMSBaseAuthBackend from .utils import validate_and_return_id_token, build_absolute_uri @@ -39,17 +40,22 @@ class UserMixin: logger.debug(log_prompt.format('start')) sub = claims['sub'] - name = claims.get('name', sub) - username = claims.get('preferred_username', sub) - email = claims.get('email', "{}@{}".format(username, 'jumpserver.openid')) - logger.debug( - log_prompt.format( - "sub: {}|name: {}|username: {}|email: {}".format(sub, name, username, email) - ) - ) + + # Construct user attrs value + user_attrs = {} + for field, attr in settings.AUTH_OPENID_USER_ATTR_MAP.items(): + user_attrs[field] = claims.get(attr, sub) + email = user_attrs.get('email', '') + email = construct_user_email(user_attrs.get('username'), email, 'jumpserver.openid') + user_attrs.update({'email': email}) + + logger.debug(log_prompt.format(user_attrs)) + + username = user_attrs.get('username') + name = user_attrs.get('name') user, created = get_user_model().objects.get_or_create( - username=username, defaults={"name": name, "email": email} + username=username, defaults=user_attrs ) logger.debug(log_prompt.format("user: {}|created: {}".format(user, created))) logger.debug(log_prompt.format("Send signal => openid create or update user")) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 6f84397ac..85c3b4598 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -191,6 +191,9 @@ class Config(dict): 'AUTH_OPENID_CLIENT_AUTH_METHOD': 'client_secret_basic', 'AUTH_OPENID_SHARE_SESSION': True, 'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True, + 'AUTH_OPENID_USER_ATTR_MAP': { + 'name': 'name', 'username': 'preferred_username', 'email': 'email' + }, # OpenID 新配置参数 (version >= 1.5.9) 'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://oidc.example.com/', diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index fb067078f..010e92f31 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -73,6 +73,7 @@ AUTH_OPENID_USE_NONCE = CONFIG.AUTH_OPENID_USE_NONCE AUTH_OPENID_SHARE_SESSION = CONFIG.AUTH_OPENID_SHARE_SESSION AUTH_OPENID_IGNORE_SSL_VERIFICATION = CONFIG.AUTH_OPENID_IGNORE_SSL_VERIFICATION AUTH_OPENID_ALWAYS_UPDATE_USER = CONFIG.AUTH_OPENID_ALWAYS_UPDATE_USER +AUTH_OPENID_USER_ATTR_MAP = CONFIG.AUTH_OPENID_USER_ATTR_MAP AUTH_OPENID_AUTH_LOGIN_URL_NAME = 'authentication:openid:login' AUTH_OPENID_AUTH_LOGIN_CALLBACK_URL_NAME = 'authentication:openid:login-callback' AUTH_OPENID_AUTH_LOGOUT_URL_NAME = 'authentication:openid:logout' diff --git a/apps/settings/serializers/auth/oidc.py b/apps/settings/serializers/auth/oidc.py index 5ab73ea04..ad30729a0 100644 --- a/apps/settings/serializers/auth/oidc.py +++ b/apps/settings/serializers/auth/oidc.py @@ -31,6 +31,11 @@ class CommonSettingSerializer(serializers.Serializer): AUTH_OPENID_IGNORE_SSL_VERIFICATION = serializers.BooleanField( required=False, label=_('Ignore ssl verification') ) + AUTH_OPENID_USER_ATTR_MAP = serializers.DictField( + required=True, label=_('User attr map'), + help_text=_('User attr map present how to map OpenID user attr to ' + 'jumpserver, username,name,email is jumpserver attr') + ) class KeycloakSettingSerializer(CommonSettingSerializer):