diff --git a/classes/loginflow/authcode.php b/classes/loginflow/authcode.php index c81cc7d..09bb857 100644 --- a/classes/loginflow/authcode.php +++ b/classes/loginflow/authcode.php @@ -36,6 +36,7 @@ use moodle_exception; use moodle_url; use pix_icon; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -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()); } @@ -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); diff --git a/classes/observers.php b/classes/observers.php index a92cec8..a51781f 100644 --- a/classes/observers.php +++ b/classes/observers.php @@ -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'); @@ -36,10 +39,10 @@ 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]); diff --git a/classes/task/cleanup_oidc_sid.php b/classes/task/cleanup_oidc_sid.php new file mode 100644 index 0000000..b6ed866 --- /dev/null +++ b/classes/task/cleanup_oidc_sid.php @@ -0,0 +1,49 @@ +. + +/** + * A scheduled task to clean up oidc sid records. + * + * @package auth_oidc + * @author Lai Wei + * @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')]); + } +} diff --git a/db/install.xml b/db/install.xml index a5c581b..93029ea 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -50,7 +50,6 @@ - @@ -61,5 +60,16 @@ + + + + + + + + + + +
diff --git a/db/tasks.php b/db/tasks.php index 8ab8904..a254fce 100644 --- a/db/tasks.php +++ b/db/tasks.php @@ -35,4 +35,13 @@ 'dayofweek' => '*', 'month' => '*', ], + [ + 'classname' => 'auth_oidc\task\cleanup_oidc_sid', + 'blocking' => 0, + 'minute' => '51', + 'hour' => '*', + 'day' => '*', + 'dayofweek' => '*', + 'month' => '*', + ], ]; diff --git a/db/upgrade.php b/db/upgrade.php index 3276e64..b1a7436 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -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); @@ -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); @@ -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); @@ -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); @@ -504,5 +504,48 @@ function xmldb_auth_oidc_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2024042201, 'auth', 'oidc'); } + if ($oldversion < 2024100702) { + // 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 (isset($tokenrecord->sid) && $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, 2024100702, 'auth', 'oidc'); + } + return true; } diff --git a/lang/en/auth_oidc.php b/lang/en/auth_oidc.php index 123bbf8..1539773 100644 --- a/lang/en/auth_oidc.php +++ b/lang/en/auth_oidc.php @@ -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'; diff --git a/logout.php b/logout.php index be5dc71..a652f78 100644 --- a/logout.php +++ b/logout.php @@ -32,14 +32,15 @@ $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(); } + $DB->delete_records('auth_oidc_sid', ['sid' => $sid]); require_logout(); } } diff --git a/version.php b/version.php index ff2197a..93b3be4 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024100700; +$plugin->version = 2024100703; $plugin->requires = 2024100700; $plugin->release = '4.5.0'; $plugin->component = 'auth_oidc';