From fb6a0f6444dcb69862ea084bf9854eaeb9c12d51 Mon Sep 17 00:00:00 2001 From: Niko Hoogeveen Date: Wed, 10 Dec 2025 14:18:19 -0500 Subject: [PATCH] MDL-73396 auth_oauth2: link non-suspended account on oauth login Added checks to link non-suspended user accounts to OAuth2, when logging in. Also added an additional check to prevent users from using OAuth2 to login if their account is suspended in Moodle. --- auth/oauth2/classes/auth.php | 56 +++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/auth/oauth2/classes/auth.php b/auth/oauth2/classes/auth.php index d93e976b9c0..f2637e5aca6 100644 --- a/auth/oauth2/classes/auth.php +++ b/auth/oauth2/classes/auth.php @@ -467,18 +467,31 @@ class auth extends \auth_plugin_base { $mappeduser = get_complete_user_data('id', $linkedlogin->get('userid')); if ($mappeduser && $mappeduser->suspended) { - $failurereason = AUTH_LOGIN_SUSPENDED; - $event = \core\event\user_login_failed::create([ - 'userid' => $mappeduser->id, - 'other' => [ - 'username' => $userinfo['username'], - 'reason' => $failurereason - ] - ]); - $event->trigger(); - $SESSION->loginerrormsg = get_string('invalidlogin'); - $client->log_out(); - redirect(new moodle_url('/login/index.php')); + // Check if there's another user with the same email that is not suspended. + $moodleuser = \core_user::get_user_by_email($userinfo['email'], '*', null, IGNORE_MULTIPLE); + if ($moodleuser->id == $mappeduser->id) { + $failurereason = AUTH_LOGIN_SUSPENDED; + $event = \core\event\user_login_failed::create([ + 'userid' => $mappeduser->id, + 'other' => [ + 'username' => $userinfo['username'], + 'reason' => $failurereason, + ], + ]); + $event->trigger(); + $SESSION->loginerrormsg = get_string('invalidlogin'); + $client->log_out(); + redirect(new moodle_url('/login/index.php')); + } else if ($moodleuser && !$moodleuser->suspended) { + // Update the OAuth2 linked login to point to the active user account. + $linkedlogin->set('userid', $moodleuser->id); + $linkedlogin->set('timemodified', time()); + $linkedlogin->update(); + + // Update user fields and continue with login. + $userinfo = $this->update_user($userinfo, $moodleuser); + $userwasmapped = true; + } } else if ($mappeduser && ($mappeduser->confirmed || !$issuer->get('requireconfirmation'))) { // Update user fields. $userinfo = $this->update_user($userinfo, $mappeduser); @@ -508,7 +521,6 @@ class auth extends \auth_plugin_base { redirect(new moodle_url('/login/index.php')); } - if (!$issuer->is_valid_login_domain($oauthemail)) { // Trigger login failed event. $failurereason = AUTH_LOGIN_UNAUTHORISED; @@ -524,8 +536,24 @@ class auth extends \auth_plugin_base { if (!$userwasmapped) { // No defined mapping - we need to see if there is an existing account with the same email. + $moodleuser = \core_user::get_user_by_email($userinfo['email'], '*', null, IGNORE_MULTIPLE); + + // Ensure we don't link a login for a suspended user. + if (!empty($moodleuser) && $moodleuser->suspended) { + $failurereason = AUTH_LOGIN_SUSPENDED; + $event = \core\event\user_login_failed::create([ + 'userid' => $moodleuser->id, + 'other' => [ + 'username' => $userinfo['email'], + 'reason' => $failurereason, + ], + ]); + $event->trigger(); + $SESSION->loginerrormsg = get_string('invalidlogin'); + $client->log_out(); + redirect(new moodle_url('/login/index.php')); + } - $moodleuser = \core_user::get_user_by_email($userinfo['email']); if (!empty($moodleuser)) { if ($issuer->get('requireconfirmation')) { $PAGE->set_url('/auth/oauth2/confirm-link-login.php');