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.
This commit is contained in:
Andrew Nicols 2017-05-12 06:44:43 +08:00
parent e84fefdb09
commit 95dd5e3bd6
2 changed files with 26 additions and 3 deletions

View File

@ -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');
}

View File

@ -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;
}
}