From 670521fd3ef17aa6e095d797c2d021ff2ebf070f Mon Sep 17 00:00:00 2001 From: Harry Smith <38967972+OxyOCE@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:26:18 +1300 Subject: [PATCH] Add option to always use UPN --- auth/oidc/classes/loginflow/authcode.php | 28 ++++++++++++++++++++---- auth/oidc/classes/loginflow/base.php | 28 ++++++++++++++++++++---- auth/oidc/lang/en/auth_oidc.php | 2 ++ auth/oidc/settings.php | 4 ++++ 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/auth/oidc/classes/loginflow/authcode.php b/auth/oidc/classes/loginflow/authcode.php index 52f492cb5..16d4ee1c8 100644 --- a/auth/oidc/classes/loginflow/authcode.php +++ b/auth/oidc/classes/loginflow/authcode.php @@ -340,7 +340,12 @@ protected function handleauthresponse(array $authparams) { // If user is already logged in and trying to link Microsoft 365 account or use it for OIDC. // Check if that Microsoft 365 account already exists in moodle. if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $upn = $idtoken->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $upn = $idtoken->claim('upn'); + } + if (empty($upn)) { + $upn = $idtoken->claim('preferred_username'); + } if (empty($upn)) { $upn = $idtoken->claim('email'); } @@ -540,7 +545,12 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok // Find the latest real Microsoft username. // Determine remote username depending on IdP type, or fall back to standard 'sub'. if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $oidcusername = $idtoken->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $oidcusername = $idtoken->claim('upn'); + } + if (empty($oidcusername)) { + $oidcusername = $idtoken->claim('preferred_username'); + } if (empty($oidcusername)) { $oidcusername = $idtoken->claim('email'); } @@ -672,7 +682,12 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok $existinguser = core_user::get_user($existingmatching->moodleid); if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $username = $idtoken->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $username = $idtoken->claim('upn'); + } + if (empty($username)) { + $username = $idtoken->claim('preferred_username'); + } if (empty($username)) { $username = $idtoken->claim('email'); } @@ -742,7 +757,12 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok // Generate a Moodle username. // Use 'upn' if available for username (Azure-specific), or fall back to lower-case oidcuniqid. if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $username = $idtoken->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $username = $idtoken->claim('upn'); + } + if (empty($username)) { + $username = $idtoken->claim('preferred_username'); + } if (empty($username)) { $username = $idtoken->claim('email'); } diff --git a/auth/oidc/classes/loginflow/base.php b/auth/oidc/classes/loginflow/base.php index 98b7ee4c4..154307a00 100644 --- a/auth/oidc/classes/loginflow/base.php +++ b/auth/oidc/classes/loginflow/base.php @@ -156,7 +156,12 @@ public function get_userinfo($username) { if (!isset($userdata['userPrincipalName'])) { if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $upn = $token->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $upn = $idtoken->claim('upn'); + } + if (empty($upn)) { + $upn = $idtoken->claim('preferred_username'); + } if (empty($upn)) { $upn = $token->claim('email'); } @@ -235,7 +240,12 @@ public function get_userinfo($username) { if (!isset($userdata['userPrincipalName'])) { if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $upn = $token->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $upn = $idtoken->claim('upn'); + } + if (empty($upn)) { + $upn = $idtoken->claim('preferred_username'); + } if (empty($upn)) { $upn = $token->claim('email'); } @@ -566,7 +576,12 @@ protected function checkrestrictions(jwt $idtoken) { $restrictions = explode("\n", $restrictions); // Check main user identifier claim based on IdP type, and falls back to oidc-standard "sub" if still empty. if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $tomatch = $idtoken->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $tomatch = $idtoken->claim('upn'); + } + if (empty($tomatch)) { + $tomatch = $idtoken->claim('preferred_username'); + } if (empty($tomatch)) { $tomatch = $idtoken->claim('email'); } @@ -640,7 +655,12 @@ protected function createtoken($oidcuniqid, $username, $authparams, $tokenparams } else { // Determine remote username depending on IdP type, or fall back to standard 'sub'. if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT) { - $oidcusername = $idtoken->claim('preferred_username'); + if (isset($this->config->useupn) && $this->config->useupn) { + $oidcusername = $idtoken->claim('upn'); + } + if (empty($oidcusername)) { + $oidcusername = $idtoken->claim('preferred_username'); + } if (empty($oidcusername)) { $oidcusername = $idtoken->claim('email'); } diff --git a/auth/oidc/lang/en/auth_oidc.php b/auth/oidc/lang/en/auth_oidc.php index d43fd3a9c..46bd6a951 100644 --- a/auth/oidc/lang/en/auth_oidc.php +++ b/auth/oidc/lang/en/auth_oidc.php @@ -89,6 +89,8 @@ $string['cfg_err_invalidclientsecret'] = 'Invalid client secret'; $string['cfg_forceredirect_key'] = 'Force redirect'; $string['cfg_forceredirect_desc'] = 'If enabled, will skip the login index page and redirect to the OpenID Connect page. Can be bypassed with ?noredirect=1 URL param'; +$string['cfg_useupn_key'] = 'Always use UPN'; +$string['cfg_useupn_desc'] = 'If enabled and IdP type is Microsoft, UPN will be used for login flow instead of preferred name.'; $string['cfg_icon_key'] = 'Icon'; $string['cfg_icon_desc'] = 'An icon to display next to the provider name on the login page.'; $string['cfg_iconalt_o365'] = 'Microsoft 365 icon'; diff --git a/auth/oidc/settings.php b/auth/oidc/settings.php index d4e85cd42..d724556fe 100644 --- a/auth/oidc/settings.php +++ b/auth/oidc/settings.php @@ -67,6 +67,10 @@ $settings->add(new admin_setting_configcheckbox('auth_oidc/forceredirect', get_string('cfg_forceredirect_key', 'auth_oidc'), get_string('cfg_forceredirect_desc', 'auth_oidc'), 0)); + // Use UPN. + $settings->add(new admin_setting_configcheckbox('auth_oidc/useupn', + get_string('cfg_useupn_key', 'auth_oidc'), get_string('cfg_useupn_desc', 'auth_oidc'), 0)); + // Auto-append. $settings->add(new admin_setting_configtext('auth_oidc/autoappend', get_string('cfg_autoappend_key', 'auth_oidc'), get_string('cfg_autoappend_desc', 'auth_oidc'), '', PARAM_TEXT));