Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log auth_oidc user out from all sessions when Front-channel logout URL is triggered #2712

Open
wants to merge 1 commit into
base: MOODLE_401_STABLE
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions auth/oidc/classes/loginflow/authcode.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use moodle_exception;
use moodle_url;
use pix_icon;
use stdClass;

defined('MOODLE_INTERNAL') || die();

Expand Down Expand Up @@ -395,7 +396,11 @@ protected function handleauthresponse(array $authparams) {
// Otherwise it's a user logging in normally with OIDC.
$this->handlelogin($oidcuniqid, $authparams, $tokenparams, $idtoken);
if ($USER->id && $DB->record_exists('auth_oidc_token', ['userid' => $USER->id])) {
$DB->set_field('auth_oidc_token', 'sid', $sid, ['userid' => $USER->id]);
$authoidsidrecord = new stdClass();
$authoidsidrecord->userid = $USER->id;
$authoidsidrecord->sid = $sid;
$authoidsidrecord->timecreated = time();
$DB->insert_record('auth_oidc_sid', $authoidsidrecord);
}
redirect(core_login_get_return_url());
}
Expand Down Expand Up @@ -792,7 +797,7 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok
$tokenrec = $DB->get_record('auth_oidc_token', ['id' => $tokenrec->id]);
// This should be already done in auth_plugin_oidc::user_authenticated_hook, but just in case...
if (!empty($tokenrec) && empty($tokenrec->userid)) {
$updatedtokenrec = new \stdClass;
$updatedtokenrec = new stdClass;
$updatedtokenrec->id = $tokenrec->id;
$updatedtokenrec->userid = $user->id;
$DB->update_record('auth_oidc_token', $updatedtokenrec);
Expand Down
20 changes: 18 additions & 2 deletions auth/oidc/classes/observers.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@

namespace auth_oidc;

use core\event\user_deleted;
use core\event\user_loggedout;

defined('MOODLE_INTERNAL') || die();

require_once($CFG->dirroot.'/lib/filelib.php');
Expand All @@ -36,13 +39,26 @@ class observers {
/**
* Handle user_deleted event - clean up calendar subscriptions.
*
* @param \core\event\user_deleted $event The triggered event.
* @param user_deleted $event The triggered event.
* @return bool Success/Failure.
*/
public static function handle_user_deleted(\core\event\user_deleted $event) {
public static function handle_user_deleted(user_deleted $event) {
global $DB;
$userid = $event->objectid;
$DB->delete_records('auth_oidc_token', ['userid' => $userid]);
return true;
}

/**
* Handle user_loggedout event - clean up sid records.
*
* @param user_loggedout $event The triggered event.
* @return bool Success/Failure.
*/
public static function handle_user_loggedout(user_loggedout $event) {
global $DB;
$userid = $event->objectid;
$DB->delete_records('auth_oidc_sid', ['userid' => $userid]);
return true;
}
}
49 changes: 49 additions & 0 deletions auth/oidc/classes/task/cleanup_oidc_sid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* A scheduled task to clean up oidc sid records.
*
* @package auth_oidc
* @author Lai Wei <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright (C) 2021 onwards Microsoft, Inc. (http://microsoft.com/)
*/

namespace auth_oidc\task;

use core\task\scheduled_task;

/**
* A scheduled task that cleans up OIDC SID records.
*/
class cleanup_oidc_sid extends scheduled_task {
/**
* Get a descriptive name for the task.
*/
public function get_name() {
return get_string('task_cleanup_oidc_sid', 'auth_oidc');
}

/**
* Clean up OIDC SID records.
*/
public function execute() {
global $DB;

$DB->delete_records_select('auth_oidc_sid', 'timecreated < ?', [strtotime('-1 day')]);
}
}
6 changes: 6 additions & 0 deletions auth/oidc/db/events.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@
'priority' => 200,
'internal' => false,
],
[
'eventname' => '\core\event\user_loggedout',
'callback' => '\auth_oidc\observers::handle_user_loggedout',
'priority' => 200,
'internal' => false,
],
];
14 changes: 12 additions & 2 deletions auth/oidc/db/install.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="auth/oidc/db" VERSION="20231221" COMMENT="XMLDB file for Moodle auth/oidc plugin"
<XMLDB PATH="auth/oidc/db" VERSION="20241127" COMMENT="XMLDB file for Moodle auth/oidc plugin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
Expand Down Expand Up @@ -50,7 +50,6 @@
<FIELD NAME="expiry" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="token expiry"/>
<FIELD NAME="refreshtoken" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="refresh token"/>
<FIELD NAME="idtoken" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="id token"/>
<FIELD NAME="sid" TYPE="char" LENGTH="36" NOTNULL="false" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand All @@ -61,5 +60,16 @@
<INDEX NAME="username" UNIQUE="false" FIELDS="username"/>
</INDEXES>
</TABLE>
<TABLE NAME="auth_oidc_sid" COMMENT="Stores sid from IdP, to be used to find connected Moodle users when SLO is triggered from IdP.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="userid" TYPE="int" LENGTH="20" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="sid" TYPE="char" LENGTH="36" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
9 changes: 9 additions & 0 deletions auth/oidc/db/tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,13 @@
'dayofweek' => '*',
'month' => '*',
],
[
'classname' => 'auth_oidc\task\cleanup_oidc_sid',
'blocking' => 0,
'minute' => '51',
'hour' => '*',
'day' => '*',
'dayofweek' => '*',
'month' => '*',
],
];
53 changes: 48 additions & 5 deletions auth/oidc/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function xmldb_auth_oidc_upgrade($oldversion) {

// Populate token oidcusername.
if (empty($user->oidcusername)) {
$updatedtoken = new \stdClass;
$updatedtoken = new stdClass;
$updatedtoken->id = $user->tokenid;
$updatedtoken->oidcusername = $oidcusername;
$DB->update_record('auth_oidc_token', $updatedtoken);
Expand All @@ -105,12 +105,12 @@ function xmldb_auth_oidc_upgrade($oldversion) {
// Old username, update to upn/sub.
if ($oidcusername != $user->username) {
// Update username.
$updateduser = new \stdClass;
$updateduser = new stdClass;
$updateduser->id = $user->userid;
$updateduser->username = $oidcusername;
$DB->update_record('user', $updateduser);

$updatedtoken = new \stdClass;
$updatedtoken = new stdClass;
$updatedtoken->id = $user->tokenid;
$updatedtoken->username = $oidcusername;
$DB->update_record('auth_oidc_token', $updatedtoken);
Expand Down Expand Up @@ -144,7 +144,7 @@ function xmldb_auth_oidc_upgrade($oldversion) {
foreach ($authtokensrs as $authtokenrec) {
$newusername = trim(\core_text::strtolower($authtokenrec->username));
if ($newusername !== $authtokenrec->username) {
$updatedrec = new \stdClass;
$updatedrec = new stdClass;
$updatedrec->id = $authtokenrec->id;
$updatedrec->username = $newusername;
$DB->update_record('auth_oidc_token', $updatedrec);
Expand Down Expand Up @@ -181,7 +181,7 @@ function xmldb_auth_oidc_upgrade($oldversion) {
JOIN {user} u ON u.username = tok.username';
$records = $DB->get_recordset_sql($sql);
foreach ($records as $record) {
$newrec = new \stdClass;
$newrec = new stdClass;
$newrec->id = $record->id;
$newrec->userid = $record->userid;
$DB->update_record('auth_oidc_token', $newrec);
Expand Down Expand Up @@ -504,5 +504,48 @@ function xmldb_auth_oidc_upgrade($oldversion) {
upgrade_plugin_savepoint(true, 2022112836, 'auth', 'oidc');
}

if ($oldversion < 2022112842) {
// Define table auth_oidc_sid to be created.
$table = new xmldb_table('auth_oidc_sid');

// Adding fields to table auth_oidc_sid.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('userid', XMLDB_TYPE_INTEGER, '20', null, XMLDB_NOTNULL, null, null);
$table->add_field('sid', XMLDB_TYPE_CHAR, '36', null, XMLDB_NOTNULL, null, null);
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);

// Adding keys to table auth_oidc_sid.
$table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);

// Conditionally launch create table for auth_oidc_sid.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}

// Migrate existing sid values from auth_oidc_tokens to auth_oidc_sid.
$tokenrecords = $DB->get_records('auth_oidc_token');
foreach ($tokenrecords as $tokenrecord) {
if ($tokenrecord->sid) {
$sidrecord = new stdClass();
$sidrecord->userid = $tokenrecord->userid;
$sidrecord->sid = $tokenrecord->sid;
$sidrecord->timecreated = time();
$DB->insert_record('auth_oidc_sid', $sidrecord);
}
}

// Define field sid to be dropped from auth_oidc_token.
$table = new xmldb_table('auth_oidc_token');
$field = new xmldb_field('sid');

// Conditionally launch drop field sid.
if ($dbman->field_exists($table, $field)) {
$dbman->drop_field($table, $field);
}

// Oidc savepoint reached.
upgrade_plugin_savepoint(true, 2022112842, 'auth', 'oidc');
}

return true;
}
1 change: 1 addition & 0 deletions auth/oidc/lang/en/auth_oidc.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
$string['event_debug'] = 'Debug message';

$string['task_cleanup_oidc_state_and_token'] = 'Clean up OIDC state and invalid token';
$string['task_cleanup_oidc_sid'] = 'Clean up OIDC SID records';

$string['errorauthdisconnectemptypassword'] = 'Password cannot be empty';
$string['errorauthdisconnectemptyusername'] = 'Username cannot be empty';
Expand Down
9 changes: 7 additions & 2 deletions auth/oidc/logout.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* @copyright (C) 2014 onwards Microsoft, Inc. (http://microsoft.com/)
*/

use core\session\manager;

// phpcs:ignore moodle.Files.RequireLogin.Missing
require_once(__DIR__ . '/../../config.php');

Expand All @@ -32,15 +34,18 @@
$sid = optional_param('sid', '', PARAM_TEXT);

if ($sid) {
if ($authoidctokenrecord = $DB->get_record('auth_oidc_token', ['sid' => $sid])) {
if ($authoidctokenrecord->userid == $USER->id) {
if ($authoidcsidrecord = $DB->get_record('auth_oidc_sid', ['sid' => $sid])) {
if ($authoidcsidrecord->userid == $USER->id) {
$authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
foreach ($authsequence as $authname) {
$authplugin = get_auth_plugin($authname);
$authplugin->logoutpage_hook();
}

require_logout();

// Log the user out from all sessions.
manager::destroy_user_sessions($authoidcsidrecord->userid);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion auth/oidc/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

defined('MOODLE_INTERNAL') || die();

$plugin->version = 2022112840;
$plugin->version = 2022112842;
$plugin->requires = 2022112800;
$plugin->release = '4.1.9';
$plugin->component = 'auth_oidc';
Expand Down