From 6bc5808c53b820fa0f2684941e67dc3ee250909a Mon Sep 17 00:00:00 2001 From: Leon Maraite <42477021+lmaraite@users.noreply.github.com> Date: Mon, 7 Nov 2022 09:28:23 +0100 Subject: [PATCH] Add the possibility to configure the OAuth2 claim which is used for the pgAdmin username. #5468 This feature provides the possibility to configure the Oauth2 claim which should be used as a username. The key in the config.py is called 'OAUTH2_USERNAME_CLAIM'. If you don't provide a custom key, the email is used as the username, like before. So it is completely backward compatible. --- docs/en_US/oauth2.rst | 2 ++ docs/en_US/release_notes_6_16.rst | 3 ++- web/config.py | 6 +++++- web/pgadmin/authenticate/oauth2.py | 29 +++++++++++++++++++++++------ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/docs/en_US/oauth2.rst b/docs/en_US/oauth2.rst index 4cc2628f5..9579fdc3c 100644 --- a/docs/en_US/oauth2.rst +++ b/docs/en_US/oauth2.rst @@ -33,6 +33,8 @@ and modify the values for the following parameters: "OAUTH2_SCOPE", "Oauth scope, ex: 'openid email profile'. Note that an 'email' claim is required in the resulting profile." "OAUTH2_ICON", "The Font-awesome icon to be placed on the oauth2 button, ex: fa-github" "OAUTH2_BUTTON_COLOR", "Oauth2 button color" + "OAUTH2_USERNAME_CLAIM", "The claim which is used for the username. If the value is empty + the email is used as username, but if a value is provided, the claim has to exist. Ex: *oid* (for AzureAD)" "OAUTH2_AUTO_CREATE_USER", "Set the value to *True* if you want to automatically create a pgAdmin user corresponding to a successfully authenticated Oauth2 user. Please note that password is not stored in the pgAdmin database." diff --git a/docs/en_US/release_notes_6_16.rst b/docs/en_US/release_notes_6_16.rst index 1ae5baa74..1b6f9c2ef 100644 --- a/docs/en_US/release_notes_6_16.rst +++ b/docs/en_US/release_notes_6_16.rst @@ -16,7 +16,8 @@ New features ************ | `Issue #1832 `_ - Added support for storing configurations of pgAdmin in an external database. - + | `Issue #5468 `_ - Add the possibility to configure the Oauth2 claim which is used for the pgAdmin username. + Housekeeping ************ diff --git a/web/config.py b/web/config.py index 9de292882..9e3efd3c9 100644 --- a/web/config.py +++ b/web/config.py @@ -11,6 +11,7 @@ # ########################################################################## +from pgadmin.utils import env, IS_WIN, fs_short_path import builtins import logging import os @@ -22,7 +23,6 @@ root = os.path.dirname(os.path.realpath(__file__)) if sys.path[0] != root: sys.path.insert(0, root) -from pgadmin.utils import env, IS_WIN, fs_short_path ########################################################################## # Application settings @@ -754,6 +754,10 @@ OAUTH2_CONFIG = [ # Oauth scope, ex: 'openid email profile' # Note that an 'email' claim is required in the resulting profile 'OAUTH2_SCOPE': None, + # The claim which is used for the username. If the value is empty the + # email is used as username, but if a value is provided, + # the claim has to exist. + 'OAUTH2_USERNAME_CLAIM': None, # Font-awesome icon, ex: fa-github 'OAUTH2_ICON': None, # UI button colour, ex: #0000ff diff --git a/web/pgadmin/authenticate/oauth2.py b/web/pgadmin/authenticate/oauth2.py index ea9a16c6b..be1c43c39 100644 --- a/web/pgadmin/authenticate/oauth2.py +++ b/web/pgadmin/authenticate/oauth2.py @@ -123,6 +123,23 @@ class OAuth2Authentication(BaseAuthentication): [value for value in self.email_keys if value in profile.keys()] email = profile[email_key[0]] if (len(email_key) > 0) else None + username = email + username_claim = None + if 'OAUTH2_USERNAME_CLAIM' in self.oauth2_config[ + self.oauth2_current_client]: + username_claim = self.oauth2_config[ + self.oauth2_current_client + ]['OAUTH2_USERNAME_CLAIM'] + if username_claim is not None: + if username_claim in profile: + username = profile[username_claim] + else: + error_msg = "The claim '%s' is required to login into " \ + "pgAdmin. Please update your Oauth2 profile." % ( + username_claim) + current_app.logger.exception(error_msg) + return False, gettext(error_msg) + if not email or email == '': current_app.logger.exception( "An email id is required to login into pgAdmin. " @@ -132,10 +149,10 @@ class OAuth2Authentication(BaseAuthentication): "An email id is required to login into pgAdmin. " "Please update your Oauth2 profile.") - user, msg = self.__auto_create_user(email) + user, msg = self.__auto_create_user(username, email) if user: user = db.session.query(User).filter_by( - username=email, auth_source=OAUTH2).first() + username=username, auth_source=OAUTH2).first() current_app.login_manager.logout_view = \ OAuth2Authentication.LOGOUT_VIEW return login_user(user), None @@ -165,17 +182,17 @@ class OAuth2Authentication(BaseAuthentication): return False, self.oauth2_clients[ self.oauth2_current_client].authorize_redirect(redirect_url) - def __auto_create_user(self, email): + def __auto_create_user(self, username, email): if config.OAUTH2_AUTO_CREATE_USER: - user = User.query.filter_by(username=email, + user = User.query.filter_by(username=username, auth_source=OAUTH2).first() if not user: return create_user({ - 'username': email, + 'username': username, 'email': email, 'role': 2, 'active': True, 'auth_source': OAUTH2 }) - return True, {'username': email} + return True, {'username': username}