From 95dd5e3bd6898f5cf2bfd5a83754473aba99f97c Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 12 May 2017 06:44:43 +0800 Subject: [PATCH] MDL-58774 auth_oauth2: Only check unexpired accounts for same issuer It shoudl be possible to link multiple OAuth2 sources which have the same e-mail address to an account. This patch makes the check for an existing linked account stricter so that it only checks for linked account records which match the same issuer, and which do not have expired confirmation tokens. --- auth/oauth2/classes/api.php | 6 +++--- auth/oauth2/classes/linked_login.php | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/auth/oauth2/classes/api.php b/auth/oauth2/classes/api.php index ffcb79c47fb..a96ebc64709 100644 --- a/auth/oauth2/classes/api.php +++ b/auth/oauth2/classes/api.php @@ -105,7 +105,7 @@ class api { $userid = $USER->id; } - if (linked_login::count_records(['username' => $userinfo['username']]) > 0) { + if (linked_login::has_existing_issuer_match($issuer, $userinfo['username'])) { throw new moodle_exception('alreadylinked', 'auth_oauth2'); } @@ -148,7 +148,7 @@ class api { $record->issuerid = $issuer->get('id'); $record->username = $userinfo['username']; $record->userid = $userid; - if (linked_login::count_records(['username' => $userinfo['username']]) > 0) { + if (linked_login::has_existing_issuer_match($issuer, $userinfo['username'])) { throw new moodle_exception('alreadylinked', 'auth_oauth2'); } $record->email = $userinfo['email']; @@ -242,7 +242,7 @@ class api { require_once($CFG->dirroot.'/user/profile/lib.php'); require_once($CFG->dirroot.'/user/lib.php'); - if (linked_login::count_records(['username' => $userinfo['username']]) > 0) { + if (linked_login::has_existing_issuer_match($issuer, $userinfo['username'])) { throw new moodle_exception('alreadylinked', 'auth_oauth2'); } diff --git a/auth/oauth2/classes/linked_login.php b/auth/oauth2/classes/linked_login.php index e4a56ca600b..a3fa2b92fb8 100644 --- a/auth/oauth2/classes/linked_login.php +++ b/auth/oauth2/classes/linked_login.php @@ -65,4 +65,27 @@ class linked_login extends persistent { ); } + /** + * Check whether there are any valid linked accounts for this issuer + * and username combination. + * + * @param \core\oauth2\issuer $issuer The issuer + * @param string $username The username to check + */ + public static function has_existing_issuer_match(\core\oauth2\issuer $issuer, $username) { + global $DB; + + $where = "issuerid = :issuerid + AND username = :username + AND (confirmtokenexpires = 0 OR confirmtokenexpires > :maxexpiry)"; + + $count = $DB->count_records_select(static::TABLE, $where, [ + 'issuerid' => $issuer->get('id'), + 'username' => $username, + 'maxexpiry' => (new \DateTime('NOW'))->getTimestamp(), + ]); + + return $count > 0; + } + }