diff --git a/auth.php b/auth.php index cd65c379..75eb901f 100644 --- a/auth.php +++ b/auth.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/authlib.php'); -require_once($CFG->dirroot.'/login/lib.php'); +require_once($CFG->libdir . '/authlib.php'); +require_once($CFG->dirroot . '/login/lib.php'); /** * OpenID Connect Authentication Plugin. @@ -51,8 +51,10 @@ public function __construct($forceloginflow = null) { global $SESSION; $loginflow = 'authcode'; - if (isset($SESSION->stateadditionaldata) && !empty($SESSION->stateadditionaldata) && - isset($SESSION->stateadditoinaldata['forceflow'])) { + if ( + isset($SESSION->stateadditionaldata) && !empty($SESSION->stateadditionaldata) && + isset($SESSION->stateadditoinaldata['forceflow']) + ) { $loginflow = $SESSION->stateadditoinaldata['forceflow']; } else { if (!empty($forceloginflow) && is_string($forceloginflow)) { @@ -64,7 +66,7 @@ public function __construct($forceloginflow = null) { } } } - $loginflowclass = '\auth_oidc\loginflow\\'.$loginflow; + $loginflowclass = '\auth_oidc\loginflow\\' . $loginflow; if (class_exists($loginflowclass)) { $this->loginflow = new $loginflowclass($this->config); } else { @@ -150,8 +152,10 @@ public function should_login_redirect() { $silentloginmodesetting = get_config('auth_oidc', 'silentloginmode'); $forceredirectsetting = get_config('auth_oidc', 'forceredirect'); $forceloginsetting = get_config('core', 'forcelogin'); - if ($silentloginmodesetting && $forceredirectsetting && $forceloginsetting && isset($_SERVER['HTTP_REFERER']) && - strpos($_SERVER['HTTP_REFERER'], $CFG->wwwroot) !== false) { + if ( + $silentloginmodesetting && $forceredirectsetting && $forceloginsetting && isset($_SERVER['HTTP_REFERER']) && + strpos($_SERVER['HTTP_REFERER'], $CFG->wwwroot) !== false + ) { return false; } @@ -197,8 +201,13 @@ public function handleredirect() { * @param null $userid * @return mixed */ - public function disconnect($justremovetokens = false, $donotremovetokens = false, ?\moodle_url $redirect = null, - ?\moodle_url $selfurl = null, $userid = null) { + public function disconnect( + $justremovetokens = false, + $donotremovetokens = false, + ?\moodle_url $redirect = null, + ?\moodle_url $selfurl = null, + $userid = null + ) { return $this->loginflow->disconnect($justremovetokens, $donotremovetokens, $redirect, $selfurl, $userid); } @@ -264,7 +273,7 @@ public function user_authenticated_hook(&$user, $username, $password) { if (!empty($tokenrec)) { // If the token record username is out of sync (ie username changes), update it. if ($tokenrec->username != $user->username) { - $updatedtokenrec = new \stdClass; + $updatedtokenrec = new \stdClass(); $updatedtokenrec->id = $tokenrec->id; $updatedtokenrec->username = $user->username; $DB->update_record('auth_oidc_token', $updatedtokenrec); @@ -276,7 +285,7 @@ public function user_authenticated_hook(&$user, $username, $password) { $tokenrec = $DB->get_record('auth_oidc_token', ['username' => $username]); if (!empty($tokenrec)) { $tokenrec->userid = $user->id; - $updatedtokenrec = new \stdClass; + $updatedtokenrec = new \stdClass(); $updatedtokenrec->id = $tokenrec->id; $updatedtokenrec->userid = $user->id; $DB->update_record('auth_oidc_token', $updatedtokenrec); @@ -323,8 +332,10 @@ public function postlogout_hook($user) { $logouturl = 'https://login.microsoftonline.com/organizations/oauth2/logout?post_logout_redirect_uri=' . urlencode($CFG->wwwroot); } else { - if (preg_match("/^https:\/\/login.microsoftonline.com\//", $logouturl) && - preg_match("/\/oauth2\/logout$/", $logouturl)) { + if ( + preg_match("/^https:\/\/login.microsoftonline.com\//", $logouturl) && + preg_match("/\/oauth2\/logout$/", $logouturl) + ) { $logouturl .= '?post_logout_redirect_uri=' . urlencode($CFG->wwwroot); } } diff --git a/binding_username_claim.php b/binding_username_claim.php index 50f70639..d4aa22d3 100644 --- a/binding_username_claim.php +++ b/binding_username_claim.php @@ -100,8 +100,14 @@ $bindingusernametoolurl = new moodle_url('/auth/oidc/change_binding_username_claim_tool.php'); echo html_writer::tag('p', get_string('binding_username_claim_description', 'auth_oidc', $bindingusernametoolurl->out())); if ($existingclaims) { - echo html_writer::tag('p', get_string('binding_username_claim_description_existing_claims', 'auth_oidc', - implode(' / ', $existingclaims))); + echo html_writer::tag( + 'p', + get_string( + 'binding_username_claim_description_existing_claims', + 'auth_oidc', + implode(' / ', $existingclaims) + ) + ); } $form->display(); diff --git a/change_binding_username_claim_tool.php b/change_binding_username_claim_tool.php index 491f7520..11a7349d 100644 --- a/change_binding_username_claim_tool.php +++ b/change_binding_username_claim_tool.php @@ -71,8 +71,14 @@ echo $OUTPUT->heading(get_string('change_binding_username_claim_tool', 'auth_oidc')); $bindingusernameclaimurl = new moodle_url('/auth/oidc/binding_username_claim.php'); - echo html_writer::tag('p', get_string('change_binding_username_claim_tool_description', 'auth_oidc', - $bindingusernameclaimurl->out())); + echo html_writer::tag( + 'p', + get_string( + 'change_binding_username_claim_tool_description', + 'auth_oidc', + $bindingusernameclaimurl->out() + ) + ); $form1->display(); @@ -87,8 +93,10 @@ $process = new process($cir); $filecolumns = $process->get_file_columns(); -$mform2 = new change_binding_username_claim_tool_form2(null, - ['columns' => $filecolumns, 'data' => ['iid' => $iid, 'previewrows' => $previewrows]]); +$mform2 = new change_binding_username_claim_tool_form2( + null, + ['columns' => $filecolumns, 'data' => ['iid' => $iid, 'previewrows' => $previewrows]] +); // If a file has been uploaded, then process it. if ($mform2->is_cancelled()) { diff --git a/classes/adminsetting/auth_oidc_admin_setting_loginflow.php b/classes/adminsetting/auth_oidc_admin_setting_loginflow.php index 7a7dcb49..80cb3c17 100644 --- a/classes/adminsetting/auth_oidc_admin_setting_loginflow.php +++ b/classes/adminsetting/auth_oidc_admin_setting_loginflow.php @@ -72,7 +72,7 @@ public function output_html($data, $query = '') { foreach ($this->flowtypes as $flowtype) { $html .= \html_writer::start_div(); - $flowtypeid = $baseid.'_'.$flowtype; + $flowtypeid = $baseid . '_' . $flowtype; $radioattrs = [ 'type' => 'radio', 'name' => $inputname, @@ -82,8 +82,8 @@ public function output_html($data, $query = '') { if ($data === $flowtype || (empty($data) && $flowtype === $this->get_defaultsetting())) { $radioattrs['checked'] = 'checked'; } - $typename = get_string('cfg_loginflow_'.$flowtype, 'auth_oidc'); - $typedesc = get_string('cfg_loginflow_'.$flowtype.'_desc', 'auth_oidc'); + $typename = get_string('cfg_loginflow_' . $flowtype, 'auth_oidc'); + $typedesc = get_string('cfg_loginflow_' . $flowtype . '_desc', 'auth_oidc'); $html .= \html_writer::empty_tag('input', $radioattrs); $html .= \html_writer::label($typename, $flowtypeid, false); $html .= '
'; diff --git a/classes/form/application.php b/classes/form/application.php index a3769cf9..b1ffe24b 100644 --- a/classes/form/application.php +++ b/classes/form/application.php @@ -69,8 +69,10 @@ protected function definition() { $authmethodoptions = [ AUTH_OIDC_AUTH_METHOD_SECRET => get_string('auth_method_secret', 'auth_oidc'), ]; - if (isset($this->_customdata['oidcconfig']->idptype) && - $this->_customdata['oidcconfig']->idptype == AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM) { + if ( + isset($this->_customdata['oidcconfig']->idptype) && + $this->_customdata['oidcconfig']->idptype == AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM + ) { $authmethodoptions[AUTH_OIDC_AUTH_METHOD_CERTIFICATE] = get_string('auth_method_certificate', 'auth_oidc'); } $mform->addElement('select', 'clientauthmethod', auth_oidc_config_name_in_form('clientauthmethod'), $authmethodoptions); @@ -93,16 +95,24 @@ protected function definition() { $mform->addElement('static', 'clientcertsource_help', '', get_string('clientcertsource_help', 'auth_oidc')); // Certificate private key. - $mform->addElement('textarea', 'clientprivatekey', auth_oidc_config_name_in_form('clientprivatekey'), - ['rows' => 10, 'cols' => 80, 'class' => 'cert_textarea']); + $mform->addElement( + 'textarea', + 'clientprivatekey', + auth_oidc_config_name_in_form('clientprivatekey'), + ['rows' => 10, 'cols' => 80, 'class' => 'cert_textarea'] + ); $mform->setType('clientprivatekey', PARAM_TEXT); $mform->disabledIf('clientprivatekey', 'clientauthmethod', 'neq', AUTH_OIDC_AUTH_METHOD_CERTIFICATE); $mform->disabledIf('clientprivatekey', 'clientcertsource', 'neq', AUTH_OIDC_AUTH_CERT_SOURCE_TEXT); $mform->addElement('static', 'clientprivatekey_help', '', get_string('clientprivatekey_help', 'auth_oidc')); // Certificate certificate. - $mform->addElement('textarea', 'clientcert', auth_oidc_config_name_in_form('clientcert'), - ['rows' => 10, 'cols' => 80, 'class' => 'cert_textarea']); + $mform->addElement( + 'textarea', + 'clientcert', + auth_oidc_config_name_in_form('clientcert'), + ['rows' => 10, 'cols' => 80, 'class' => 'cert_textarea'] + ); $mform->setType('clientcert', PARAM_TEXT); $mform->disabledIf('clientcert', 'clientauthmethod', 'neq', AUTH_OIDC_AUTH_METHOD_CERTIFICATE); $mform->disabledIf('clientcert', 'clientcertsource', 'neq', AUTH_OIDC_AUTH_CERT_SOURCE_TEXT); @@ -164,12 +174,19 @@ protected function definition() { // Secret expiry notifications recipients. if (auth_oidc_is_local_365_installed()) { - $mform->addElement('header', 'secretexpirynotification', - get_string('settings_section_secret_expiry_notification', 'auth_oidc')); + $mform->addElement( + 'header', + 'secretexpirynotification', + get_string('settings_section_secret_expiry_notification', 'auth_oidc') + ); $mform->setExpanded('secretexpirynotification'); - $mform->addElement('text', 'secretexpiryrecipients', auth_oidc_config_name_in_form('secretexpiryrecipients'), - ['size' => 256]); + $mform->addElement( + 'text', + 'secretexpiryrecipients', + auth_oidc_config_name_in_form('secretexpiryrecipients'), + ['size' => 256] + ); $mform->setType('secretexpiryrecipients', PARAM_TEXT); $mform->disabledIf('secretexpiryrecipients', 'clientauthmethod', 'neq', AUTH_OIDC_AUTH_METHOD_SECRET); $mform->disabledIf('secretexpiryrecipients', 'idptype', 'eq', AUTH_OIDC_IDP_TYPE_OTHER); @@ -254,16 +271,22 @@ public function validation($data, $files) { } // If "certificate" authentication method is used, ensure tenant specific endpoints are used. - if ($data['idptype'] == AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM && - $data['clientauthmethod'] == AUTH_OIDC_AUTH_METHOD_CERTIFICATE) { - if (strpos($data['authendpoint'], '/common/') !== false || + if ( + $data['idptype'] == AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM && + $data['clientauthmethod'] == AUTH_OIDC_AUTH_METHOD_CERTIFICATE + ) { + if ( + strpos($data['authendpoint'], '/common/') !== false || strpos($data['authendpoint'], '/organizations/') !== false || - strpos($data['authendpoint'], '/consumers/') !== false) { + strpos($data['authendpoint'], '/consumers/') !== false + ) { $errors['authendpoint'] = get_string('error_tenant_specific_endpoint_required', 'auth_oidc'); } - if (strpos($data['tokenendpoint'], '/common/') !== false || + if ( + strpos($data['tokenendpoint'], '/common/') !== false || strpos($data['tokenendpoint'], '/organizations/') !== false || - strpos($data['tokenendpoint'], '/consumers/') !== false) { + strpos($data['tokenendpoint'], '/consumers/') !== false + ) { $errors['tokenendpoint'] = get_string('error_tenant_specific_endpoint_required', 'auth_oidc'); } } diff --git a/classes/form/binding_username_claim.php b/classes/form/binding_username_claim.php index 9852d69d..e3ffaf2c 100644 --- a/classes/form/binding_username_claim.php +++ b/classes/form/binding_username_claim.php @@ -114,10 +114,10 @@ protected function definition() { } $mform->addElement( - 'select', - 'bindingusernameclaim', - auth_oidc_config_name_in_form('bindingusernameclaim'), - $bindingusernameoptions + 'select', + 'bindingusernameclaim', + auth_oidc_config_name_in_form('bindingusernameclaim'), + $bindingusernameoptions ); $mform->setDefault('bindingusernameclaim', 'auto'); $mform->addElement('static', 'bindingusernameclaim_description', '', get_string($descriptionidentifier, 'auth_oidc')); diff --git a/classes/form/disconnect.php b/classes/form/disconnect.php index 8bddab4b..cc02c7e8 100644 --- a/classes/form/disconnect.php +++ b/classes/form/disconnect.php @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot.'/lib/formslib.php'); +require_once($CFG->dirroot . '/lib/formslib.php'); /** * OIDC Disconnect Form. diff --git a/classes/httpclient.php b/classes/httpclient.php index a8d5f2f7..95725e20 100644 --- a/classes/httpclient.php +++ b/classes/httpclient.php @@ -51,8 +51,8 @@ protected function get_clienttag_headers() { $params = "lang=PHP; os={$ostype}; os_version={$osver}; arch={$arch}; version={$ver}; MoodleInstallId={$iid}"; $clienttag = "Moodle/{$mdlver} ({$params})"; return [ - 'User-Agent: '.$clienttag, - 'X-ClientService-ClientTag: '.$clienttag, + 'User-Agent: ' . $clienttag, + 'X-ClientService-ClientTag: ' . $clienttag, ]; } @@ -63,8 +63,8 @@ protected function get_clienttag_headers() { */ protected function get_plugin_version() { global $CFG; - $plugin = new \stdClass; - require_once($CFG->dirroot.'/auth/oidc/version.php'); + $plugin = new \stdClass(); + require_once($CFG->dirroot . '/auth/oidc/version.php'); return (isset($plugin->release)) ? $plugin->release : 'unknown'; } diff --git a/classes/jwt.php b/classes/jwt.php index d66de9e5..46c020b2 100644 --- a/classes/jwt.php +++ b/classes/jwt.php @@ -106,7 +106,7 @@ public static function decode_jws(string $jwtpayload) { */ public static function instance_from_encoded($encoded) { [$header, $body] = static::decode($encoded); - $jwt = new static; + $jwt = new static(); $jwt->set_header($header); $jwt->set_claims($body); return $jwt; diff --git a/classes/loginflow/authcode.php b/classes/loginflow/authcode.php index 41aba701..db3474a3 100644 --- a/classes/loginflow/authcode.php +++ b/classes/loginflow/authcode.php @@ -210,8 +210,12 @@ public function user_login($username, $password = null) { * @param array $extraparams Additional parameters to send with the OIDC request. * @param bool $selectaccount Whether to prompt the user to select an account. */ - public function initiateauthrequest($promptlogin = false, array $stateparams = [], array $extraparams = [], - bool $selectaccount = false) { + public function initiateauthrequest( + $promptlogin = false, + array $stateparams = [], + array $extraparams = [], + bool $selectaccount = false + ) { $client = $this->get_oidcclient(); $client->authrequest($promptlogin, $stateparams, $extraparams, $selectaccount); } @@ -367,17 +371,19 @@ protected function handleauthresponse(array $authparams) { // Check if that Microsoft 365 account already exists in moodle. $oidcusername = $this->get_oidc_username_from_token_claim($idtoken); - $userrec = $DB->count_records_sql('SELECT COUNT(*) + $userrec = $DB->count_records_sql( + 'SELECT COUNT(*) FROM {user} WHERE username = ? AND id != ?', - [$oidcusername, $USER->id]); + [$oidcusername, $USER->id] + ); if (!empty($userrec)) { if (empty($additionaldata['redirect'])) { $redirect = '/auth/oidc/ucp.php?o365accountconnected=true'; } else if ($additionaldata['redirect'] == '/local/o365/ucp.php') { - $redirect = $additionaldata['redirect'].'?action=connection&o365accountconnected=true'; + $redirect = $additionaldata['redirect'] . '?action=connection&o365accountconnected=true'; } else { throw new moodle_exception('errorinvalidredirect_message', 'auth_oidc'); } @@ -570,8 +576,10 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok if (auth_oidc_is_local_365_installed()) { if ($existingmatching = $DB->get_record('local_o365_objects', ['type' => 'user', 'objectid' => $oidcuniqid])) { $existinguser = core_user::get_user($existingmatching->moodleid); - if ($existinguser && strtolower($existingmatching->o365name) != strtolower($oidcusername) && - $existinguser->username != strtolower($oidcusername)) { + if ( + $existinguser && strtolower($existingmatching->o365name) != strtolower($oidcusername) && + $existinguser->username != strtolower($oidcusername) + ) { $usernamechanged = true; } } @@ -652,8 +660,12 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok // Update local_o365_objects table. if (auth_oidc_is_local_365_installed()) { - if ($o365objectrecord = $DB->get_record('local_o365_objects', - ['moodleid' => $user->id, 'type' => 'user'])) { + if ( + $o365objectrecord = $DB->get_record( + 'local_o365_objects', + ['moodleid' => $user->id, 'type' => 'user'] + ) + ) { $o365objectrecord->o365name = $oidcusername; $DB->update_record('local_o365_objects', $o365objectrecord); } @@ -694,8 +706,10 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok if (auth_oidc_is_local_365_installed()) { $apiclient = \local_o365\utils::get_api(); $userdetails = $apiclient->get_user($oidcuniqid); - if (!is_null($userdetails) && isset($userdetails['userPrincipalName']) && - stripos($userdetails['userPrincipalName'], '#EXT#') !== false && $idtoken->claim('unique_name')) { + if ( + !is_null($userdetails) && isset($userdetails['userPrincipalName']) && + stripos($userdetails['userPrincipalName'], '#EXT#') !== false && $idtoken->claim('unique_name') + ) { $originalupn = $userdetails['userPrincipalName']; $username = $idtoken->claim('unique_name'); } @@ -754,8 +768,10 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok if (auth_oidc_is_local_365_installed()) { $apiclient = \local_o365\utils::get_api(); $userdetails = $apiclient->get_user($oidcuniqid, true); - if (!is_null($userdetails) && isset($userdetails['userPrincipalName']) && - stripos($userdetails['userPrincipalName'], '#EXT#') !== false && $idtoken->claim('unique_name')) { + if ( + !is_null($userdetails) && isset($userdetails['userPrincipalName']) && + stripos($userdetails['userPrincipalName'], '#EXT#') !== false && $idtoken->claim('unique_name') + ) { $originalupn = $userdetails['userPrincipalName']; $username = $idtoken->claim('unique_name'); } @@ -801,7 +817,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); @@ -815,7 +831,6 @@ protected function handlelogin(string $oidcuniqid, array $authparams, array $tok redirect($CFG->wwwroot, get_string('errorauthgeneral', 'auth_oidc'), null, notification::NOTIFY_ERROR); } - } return true; } diff --git a/classes/loginflow/base.php b/classes/loginflow/base.php index 219c6d43..7ea031ce 100644 --- a/classes/loginflow/base.php +++ b/classes/loginflow/base.php @@ -357,8 +357,13 @@ public function set_httpclient(\auth_oidc\httpclientinterface $httpclient) { * @param \moodle_url|null $selfurl The page this is accessed from, used for some redirects. * @param int|null $userid ID of the user to disconnect; uses the current user if not provided. */ - public function disconnect($justremovetokens = false, $donotremovetokens = false, ?\moodle_url $redirect = null, - ?\moodle_url $selfurl = null, $userid = null) { + public function disconnect( + $justremovetokens = false, + $donotremovetokens = false, + ?\moodle_url $redirect = null, + ?\moodle_url $selfurl = null, + $userid = null + ) { global $USER, $DB, $CFG; if ($redirect === null) { $redirect = new \moodle_url('/auth/oidc/ucp.php'); @@ -386,7 +391,7 @@ public function disconnect($justremovetokens = false, $donotremovetokens = false redirect($redirect); } else { global $OUTPUT, $PAGE; - require_once($CFG->dirroot.'/user/lib.php'); + require_once($CFG->dirroot . '/user/lib.php'); $PAGE->set_url($selfurl->out()); $PAGE->set_context(\context_system::instance()); $PAGE->set_pagelayout('standard'); @@ -430,12 +435,14 @@ public function disconnect($justremovetokens = false, $donotremovetokens = false if ($mform->is_cancelled()) { redirect($redirect); } else if ($fromform = $mform->get_data()) { - if (empty($fromform->newmethod) || ($fromform->newmethod !== $prevauthmethod && - $fromform->newmethod !== 'manual')) { + if ( + empty($fromform->newmethod) || ($fromform->newmethod !== $prevauthmethod && + $fromform->newmethod !== 'manual') + ) { throw new moodle_exception('errorauthdisconnectinvalidmethod', 'auth_oidc'); } - $updateduser = new stdClass; + $updateduser = new stdClass(); if ($fromform->newmethod === 'manual') { if (empty($fromform->password)) { @@ -462,7 +469,7 @@ public function disconnect($justremovetokens = false, $donotremovetokens = false $updateduser->auth = $prevauthmethod; // We can't use user_update_user as it will rehash the value. if (!empty($prevmethodrec->password)) { - $manualuserupdate = new stdClass; + $manualuserupdate = new stdClass(); $manualuserupdate->id = $userrec->id; $manualuserupdate->password = $prevmethodrec->password; $DB->update_record('user', $manualuserupdate); @@ -510,7 +517,6 @@ public function disconnect($justremovetokens = false, $donotremovetokens = false * @return mixed Determined by loginflow. */ public function handleredirect() { - } /** @@ -595,7 +601,7 @@ protected function checkrestrictions(jwt $idtoken) { $hasrestrictions = true; ob_start(); try { - $pattern = '/'.$restriction.'/'; + $pattern = '/' . $restriction . '/'; if (isset($this->config->userrestrictionscasesensitive) && !$this->config->userrestrictionscasesensitive) { $pattern .= 'i'; } @@ -640,8 +646,15 @@ protected function checkrestrictions(jwt $idtoken) { * @param null|string $originalupn * @return stdClass The created token database record. */ - protected function createtoken($oidcuniqid, $username, $authparams, $tokenparams, jwt $idtoken, $userid = 0, - $originalupn = null) { + protected function createtoken( + $oidcuniqid, + $username, + $authparams, + $tokenparams, + jwt $idtoken, + $userid = 0, + $originalupn = null + ) { global $DB; if (!is_null($originalupn)) { @@ -669,7 +682,7 @@ protected function createtoken($oidcuniqid, $username, $authparams, $tokenparams } } - $tokenrec = new stdClass; + $tokenrec = new stdClass(); $tokenrec->oidcuniqid = $oidcuniqid; $tokenrec->username = $username; $tokenrec->userid = $userid; @@ -701,7 +714,7 @@ protected function createtoken($oidcuniqid, $username, $authparams, $tokenparams */ protected function updatetoken($tokenid, $authparams, $tokenparams) { global $DB; - $tokenrec = new stdClass; + $tokenrec = new stdClass(); $tokenrec->id = $tokenid; $tokenrec->authcode = $authparams['code']; $tokenrec->token = $tokenparams['access_token']; @@ -740,6 +753,7 @@ protected function get_oidc_username_from_token_claim(jwt $idtoken, string $bind switch ($bindingusernameclaim) { case 'custom': $bindingusernameclaim = get_config('auth_oidc', 'custombindingclaim'); + // No break. case 'preferred_username': case 'email': case 'upn': diff --git a/classes/loginflow/rocreds.php b/classes/loginflow/rocreds.php index 8eb1226b..c71786a4 100644 --- a/classes/loginflow/rocreds.php +++ b/classes/loginflow/rocreds.php @@ -122,11 +122,15 @@ public function loginpage_hook(&$frm, &$user) { $failurereason = AUTH_LOGIN_UNAUTHORISED; // Trigger login failed event. - $event = \core\event\user_login_failed::create(['other' => ['username' => $username, - 'reason' => $failurereason]]); + $event = \core\event\user_login_failed::create([ + 'other' => [ + 'username' => $username, + 'reason' => $failurereason, + ], + ]); $event->trigger(); - debugging('[client '.getremoteaddr()."] $CFG->wwwroot Unknown user, can not create new accounts: $username ". + debugging('[client ' . getremoteaddr() . "] $CFG->wwwroot Unknown user, can not create new accounts: $username " . $_SERVER['HTTP_USER_AGENT']); return false; @@ -179,8 +183,10 @@ public function user_login($username, $password = null) { if (auth_oidc_is_local_365_installed()) { $apiclient = \local_o365\utils::get_api(); $userdetails = $apiclient->get_user($oidcuniqid); - if (!is_null($userdetails) && isset($userdetails['userPrincipalName']) && - stripos($userdetails['userPrincipalName'], '#EXT#') !== false) { + if ( + !is_null($userdetails) && isset($userdetails['userPrincipalName']) && + stripos($userdetails['userPrincipalName'], '#EXT#') !== false + ) { $originalupn = $userdetails['userPrincipalName']; } } diff --git a/classes/observers.php b/classes/observers.php index a51781fc..645acec7 100644 --- a/classes/observers.php +++ b/classes/observers.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot.'/lib/filelib.php'); +require_once($CFG->dirroot . '/lib/filelib.php'); /** * Handles events. diff --git a/classes/oidcclient.php b/classes/oidcclient.php index 54a57f5f..7961da7d 100644 --- a/classes/oidcclient.php +++ b/classes/oidcclient.php @@ -91,7 +91,6 @@ public function setcreds($id, $secret, $redirecturi, $tokenresource = '', $scope } else { $this->tokenresource = 'https://graph.microsoft.com'; } - } $this->scope = (!empty($scope)) ? $scope : 'openid profile email'; } @@ -174,11 +173,15 @@ public function get_endpoint($endpoint) { * @param bool $selectaccount Whether to prompt the user to select an account. * @return array Array of request parameters. */ - protected function getauthrequestparams($promptlogin = false, array $stateparams = [], array $extraparams = [], - bool $selectaccount = false) { + protected function getauthrequestparams( + $promptlogin = false, + array $stateparams = [], + array $extraparams = [], + bool $selectaccount = false + ) { global $SESSION; - $nonce = 'N'.uniqid(); + $nonce = 'N' . uniqid(); $params = [ 'response_type' => 'code', @@ -224,7 +227,7 @@ protected function getauthrequestparams($promptlogin = false, array $stateparams * @return array */ protected function getadminconsentrequestparams(array $stateparams = [], array $extraparams = []) { - $nonce = 'N'.uniqid(); + $nonce = 'N' . uniqid(); $params = [ 'client_id' => $this->clientid, @@ -247,7 +250,7 @@ protected function getadminconsentrequestparams(array $stateparams = [], array $ */ protected function getnewstate($nonce, array $stateparams = []) { global $DB; - $staterec = new \stdClass; + $staterec = new \stdClass(); $staterec->sesskey = sesskey(); $staterec->state = random_string(15); $staterec->nonce = $nonce; @@ -265,8 +268,12 @@ protected function getnewstate($nonce, array $stateparams = []) { * @param array $extraparams Additional parameters to send with the OIDC request. * @param bool $selectaccount Whether to prompt the user to select an account. */ - public function authrequest($promptlogin = false, array $stateparams = [], array $extraparams = [], - bool $selectaccount = false) { + public function authrequest( + $promptlogin = false, + array $stateparams = [], + array $extraparams = [], + bool $selectaccount = false + ) { if (empty($this->clientid)) { throw new moodle_exception('erroroidcclientnocreds', 'auth_oidc'); } diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 6522dbf2..79ac092c 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -25,29 +25,21 @@ namespace auth_oidc\privacy; -defined('MOODLE_INTERNAL') || die(); - use core_privacy\local\metadata\collection; -use core_privacy\local\request\contextlist; +use core_privacy\local\metadata\provider as metadata_provider; use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\contextlist; +use core_privacy\local\request\core_userlist_provider; +use core_privacy\local\request\plugin\provider as plugin_provider; use core_privacy\local\request\writer; -/** - * Interface for handling user lists in the OIDC authentication plugin. - * - * @package auth_oidc - */ -interface auth_oidc_userlist extends \core_privacy\local\request\core_userlist_provider { -}; - /** * Privacy provider for auth_oidc. */ class provider implements - \core_privacy\local\request\plugin\provider, - \core_privacy\local\metadata\provider, - auth_oidc_userlist { - + core_userlist_provider, + metadata_provider, + plugin_provider { /** * Returns meta data about this system. * @@ -86,12 +78,12 @@ public static function get_metadata(collection $collection): collection { foreach ($tables as $table => $fields) { $fielddata = []; foreach ($fields as $field) { - $fielddata[$field] = 'privacy:metadata:'.$table.':'.$field; + $fielddata[$field] = 'privacy:metadata:' . $table . ':' . $field; } $collection->add_database_table( $table, $fielddata, - 'privacy:metadata:'.$table + 'privacy:metadata:' . $table ); } @@ -105,7 +97,7 @@ public static function get_metadata(collection $collection): collection { * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. */ public static function get_contexts_for_userid(int $userid): contextlist { - $contextlist = new \core_privacy\local\request\contextlist(); + $contextlist = new contextlist(); $sql = "SELECT ctx.id FROM {auth_oidc_token} tk @@ -134,7 +126,8 @@ public static function get_contexts_for_userid(int $userid): contextlist { /** * Get the list of users who have data within a context. * - * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. + * @param \core_privacy\local\request\userlist $userlist The userlist containing the list of + * users who have data in this context/plugin combination. */ public static function get_users_in_context(\core_privacy\local\request\userlist $userlist) { $context = $userlist->get_context(); @@ -188,7 +181,7 @@ public static function export_user_data(approved_contextlist $contextlist) { foreach ($records as $record) { writer::with_context($context)->export_data([ get_string('privacy:metadata:auth_oidc', 'auth_oidc'), - get_string('privacy:metadata:'.$table, 'auth_oidc'), + get_string('privacy:metadata:' . $table, 'auth_oidc'), ], $record); } } @@ -212,7 +205,7 @@ protected static function get_table_user_map(\stdClass $user): array { /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { if ($context->contextlevel == CONTEXT_USER) { diff --git a/classes/tests/mockoidcclient.php b/classes/tests/mockoidcclient.php index 20980616..cf1ac3f5 100644 --- a/classes/tests/mockoidcclient.php +++ b/classes/tests/mockoidcclient.php @@ -45,10 +45,10 @@ class mockoidcclient extends \auth_oidc\oidcclient { * @return array Array of request parameters. */ public function getauthrequestparams( - $promptlogin = false, - array $stateparams = [], - array $extraparams = [], - bool $selectaccount = false + $promptlogin = false, + array $stateparams = [], + array $extraparams = [], + bool $selectaccount = false ) { return parent::getauthrequestparams($promptlogin, $stateparams); } diff --git a/classes/upload_process_tracker.php b/classes/upload_process_tracker.php index 7935c9be..f744bb48 100644 --- a/classes/upload_process_tracker.php +++ b/classes/upload_process_tracker.php @@ -32,7 +32,7 @@ */ class upload_process_tracker { /** @var array */ - protected $_row; + protected $row; /** @var array */ public $columns = []; /** @var array */ @@ -66,7 +66,7 @@ public function start() { echo html_writer::tag('th', $header, ['class' => 'header c' . $ci++, 'scope' => 'col']); } echo html_writer::end_tag('tr'); - $this->_row = null; + $this->row = null; } /** @@ -75,11 +75,11 @@ public function start() { * @return void */ public function flush() { - if (empty($this->_row) || empty($this->_row['line']['normal'])) { + if (empty($this->row) || empty($this->row['line']['normal'])) { // Nothing to print - each line has to have at least number. - $this->_row = []; + $this->row = []; foreach ($this->columns as $col) { - $this->_row[$col] = ['normal' => '', 'info' => '', 'warning' => '', 'error' => '']; + $this->row[$col] = ['normal' => '', 'info' => '', 'warning' => '', 'error' => '']; } return; @@ -87,7 +87,7 @@ public function flush() { $ci = 0; $ri = 1; echo ''; - foreach ($this->_row as $key => $field) { + foreach ($this->row as $key => $field) { foreach ($field as $type => $content) { if ($field[$type] !== '') { $field[$type] = '' . $field[$type] . ''; @@ -105,7 +105,7 @@ public function flush() { } echo ''; foreach ($this->columns as $col) { - $this->_row[$col] = ['normal' => '', 'info' => '', 'warning' => '', 'error' => '']; + $this->row[$col] = ['normal' => '', 'info' => '', 'warning' => '', 'error' => '']; } } @@ -119,7 +119,7 @@ public function flush() { * @return void */ public function track($col, $msg, $level = 'normal', $merge = true) { - if (empty($this->_row)) { + if (empty($this->row)) { $this->flush(); } if (!in_array($col, $this->columns)) { @@ -128,12 +128,12 @@ public function track($col, $msg, $level = 'normal', $merge = true) { return; } if ($merge) { - if ($this->_row[$col][$level] != '') { - $this->_row[$col][$level] .= '
'; + if ($this->row[$col][$level] != '') { + $this->row[$col][$level] .= '
'; } - $this->_row[$col][$level] .= $msg; + $this->row[$col][$level] .= $msg; } else { - $this->_row[$col][$level] = $msg; + $this->row[$col][$level] = $msg; } } diff --git a/classes/utils.php b/classes/utils.php index 93dfcfc5..8766c46a 100644 --- a/classes/utils.php +++ b/classes/utils.php @@ -55,14 +55,21 @@ public static function process_json_response($response, array $expectedstructure if (isset($result['error_description'])) { $isadminconsent = optional_param('admin_consent', false, PARAM_BOOL); if ($isadminconsent) { - if (get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM && + if ( + get_config('auth_oidc', 'idptype') == AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM && auth_oidc_is_local_365_installed() && $result['error'] === 'invalid_grant' && isset($result['error_codes']) && count($result['error_codes']) == 1 && - $result['error_codes'][0] == 53003) { + $result['error_codes'][0] == 53003 + ) { $localo365configurationpageurl = new moodle_url('/admin/settings.php', ['section' => 'local_o365']); - throw new moodle_exception('settings_adminconsent_error_53003', 'local_o365', - $localo365configurationpageurl, '', $result['error_description']); + throw new moodle_exception( + 'settings_adminconsent_error_53003', + 'local_o365', + $localo365configurationpageurl, + '', + $result['error_description'] + ); } } throw new moodle_exception('erroroidccall_message', 'auth_oidc', '', $result['error_description']); @@ -73,7 +80,7 @@ public static function process_json_response($response, array $expectedstructure foreach ($expectedstructure as $key => $val) { if (!isset($result[$key])) { - $errmsg = 'Invalid structure received. No "'.$key.'"'; + $errmsg = 'Invalid structure received. No "' . $key . '"'; self::debug($errmsg, __METHOD__, $result); throw new moodle_exception('erroroidccall', 'auth_oidc'); } @@ -81,7 +88,8 @@ public static function process_json_response($response, array $expectedstructure if ($val !== null && $result[$key] !== $val) { $strreceivedval = self::tostring($result[$key]); $strval = self::tostring($val); - $errmsg = 'Invalid structure received. Invalid "'.$key.'". Received "'.$strreceivedval.'", expected "'.$strval.'"'; + $errmsg = 'Invalid structure received. Invalid "' . $key . '". Received "' . $strreceivedval . + '", expected "' . $strval . '"'; self::debug($errmsg, __METHOD__, $result); throw new moodle_exception('erroroidccall', 'auth_oidc'); } @@ -98,9 +106,9 @@ public static function process_json_response($response, array $expectedstructure public static function tostring($val) { if (is_scalar($val)) { if (is_bool($val)) { - return '(bool)'.(string)(int)$val; + return '(bool)' . (string)(int)$val; } else { - return '('.gettype($val).')'.(string)$val; + return '(' . gettype($val) . ')' . (string)$val; } } else if (is_null($val)) { return '(null)'; diff --git a/cleanupoidctokens.php b/cleanupoidctokens.php index 3d1a2845..5e401afe 100644 --- a/cleanupoidctokens.php +++ b/cleanupoidctokens.php @@ -47,7 +47,7 @@ $tokenstoclean = $emptyuseridtokens + $mismatchedtokens; -uasort($tokenstoclean, function($a, $b) { +uasort($tokenstoclean, function ($a, $b) { return strcmp($a->oidcusername, $b->oidcusername); }); diff --git a/db/upgrade.php b/db/upgrade.php index 346db562..a7facf0c 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); @@ -125,7 +125,7 @@ function xmldb_auth_oidc_upgrade($oldversion) { if ($oldversion < 2015012707) { if (!$dbman->table_exists('auth_oidc_prevlogin')) { - $dbman->install_one_table_from_xmldb_file(__DIR__.'/install.xml', 'auth_oidc_prevlogin'); + $dbman->install_one_table_from_xmldb_file(__DIR__ . '/install.xml', 'auth_oidc_prevlogin'); } upgrade_plugin_savepoint(true, 2015012707, 'auth', 'oidc'); } @@ -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); @@ -157,14 +157,22 @@ function xmldb_auth_oidc_upgrade($oldversion) { // Update old endpoints. $config = get_config('auth_oidc'); if ($config->authendpoint === 'https://login.windows.net/common/oauth2/authorize') { - add_to_config_log('authendpoint', $config->authendpoint, 'https://login.microsoftonline.com/common/oauth2/authorize', - 'auth_oidc'); + add_to_config_log( + 'authendpoint', + $config->authendpoint, + 'https://login.microsoftonline.com/common/oauth2/authorize', + 'auth_oidc' + ); set_config('authendpoint', 'https://login.microsoftonline.com/common/oauth2/authorize', 'auth_oidc'); } if ($config->tokenendpoint === 'https://login.windows.net/common/oauth2/token') { - add_to_config_log('tokenendpoint', $config->tokenendpoint, 'https://login.microsoftonline.com/common/oauth2/token', - 'auth_oidc'); + add_to_config_log( + 'tokenendpoint', + $config->tokenendpoint, + 'https://login.microsoftonline.com/common/oauth2/token', + 'auth_oidc' + ); set_config('tokenendpoint', 'https://login.microsoftonline.com/common/oauth2/token', 'auth_oidc'); } @@ -181,7 +189,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); @@ -399,10 +407,10 @@ function xmldb_auth_oidc_upgrade($oldversion) { $existingidptype = get_config('auth_oidc', 'idptype'); if ($existinglocksetting != AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM) { add_to_config_log( - 'idptype', - $existingidptype, - AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM, - 'auth_oidc' + 'idptype', + $existingidptype, + AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM, + 'auth_oidc' ); } set_config('idptype', AUTH_OIDC_IDP_TYPE_MICROSOFT_IDENTITY_PLATFORM, 'auth_oidc'); @@ -426,8 +434,12 @@ function xmldb_auth_oidc_upgrade($oldversion) { if (empty($clientsecretconfig) && !empty($clientcertificateconfig) && !empty($clientprivatekeyconfig)) { $existingclientauthmethod = get_config('auth_oidc', 'clientauthmethod'); if ($existingclientauthmethod != AUTH_OIDC_AUTH_METHOD_CERTIFICATE) { - add_to_config_log('clientauthmethod', $existingclientauthmethod, AUTH_OIDC_AUTH_METHOD_CERTIFICATE, - 'auth_oidc'); + add_to_config_log( + 'clientauthmethod', + $existingclientauthmethod, + AUTH_OIDC_AUTH_METHOD_CERTIFICATE, + 'auth_oidc' + ); } set_config('clientauthmethod', AUTH_OIDC_AUTH_METHOD_CERTIFICATE, 'auth_oidc'); } else { diff --git a/index.php b/index.php index 1abea2e8..20082e92 100644 --- a/index.php +++ b/index.php @@ -24,8 +24,8 @@ */ // phpcs:ignore moodle.Files.RequireLogin.Missing -require_once(__DIR__.'/../../config.php'); -require_once(__DIR__.'/auth.php'); +require_once(__DIR__ . '/../../config.php'); +require_once(__DIR__ . '/auth.php'); $auth = new \auth_plugin_oidc('authcode'); $auth->set_httpclient(new \auth_oidc\httpclient()); diff --git a/lib.php b/lib.php index 482060da..3589e861 100644 --- a/lib.php +++ b/lib.php @@ -232,8 +232,11 @@ function auth_oidc_get_tokens_with_mismatched_usernames() { $item->userid = $record->muserid; $item->oidcuniqueid = $record->oidcuniqid; $item->matchingstatus = get_string('mismatched', 'auth_oidc'); - $item->details = get_string('mismatched_details', 'auth_oidc', - ['tokenusername' => $record->tokenusername, 'moodleusername' => $record->musername]); + $item->details = get_string( + 'mismatched_details', + 'auth_oidc', + ['tokenusername' => $record->tokenusername, 'moodleusername' => $record->musername] + ); $deletetokenurl = new moodle_url('/auth/oidc/cleanupoidctokens.php', ['id' => $record->id]); $item->action = html_writer::link($deletetokenurl, get_string('delete_token_and_reference', 'auth_oidc')); @@ -257,7 +260,13 @@ function auth_oidc_delete_token(int $tokenid): void { JOIN {auth_oidc_token} tok ON obj.o365name = tok.username JOIN {user} u ON obj.moodleid = u.id WHERE obj.type = :type AND tok.id = :tokenid'; - if ($objectrecord = $DB->get_record_sql($sql, ['type' => 'user', 'tokenid' => $tokenid], IGNORE_MULTIPLE)) { + if ( + $objectrecord = $DB->get_record_sql( + $sql, + ['type' => 'user', 'tokenid' => $tokenid], + IGNORE_MULTIPLE + ) + ) { // Delete record from local_o365_objects. $DB->delete_records('local_o365_objects', ['id' => $objectrecord->id]); @@ -265,8 +274,11 @@ function auth_oidc_delete_token(int $tokenid): void { $DB->delete_records('local_o365_token', ['user_id' => $objectrecord->userid]); // Delete record from local_o365_connections. - $DB->delete_records_select('local_o365_connections', 'muserid = :userid OR LOWER(entraidupn) = :email', - ['userid' => $objectrecord->userid, 'email' => $objectrecord->email]); + $DB->delete_records_select( + 'local_o365_connections', + 'muserid = :userid OR LOWER(entraidupn) = :email', + ['userid' => $objectrecord->userid, 'email' => $objectrecord->email] + ); } } @@ -314,28 +326,45 @@ function auth_oidc_get_remote_fields() { $order = 0; while ($order++ < 15) { - $remotefields['extensionAttribute' . $order] = get_string('settings_fieldmap_field_extensionattribute', 'auth_oidc', - $order); + $remotefields['extensionAttribute' . $order] = get_string( + 'settings_fieldmap_field_extensionattribute', + 'auth_oidc', + $order + ); } // SDS profile sync. - [$sdsprofilesyncenabled, $schoolid, $schoolname] = local_o365\feature\sds\utils::get_profile_sync_status_with_id_name(); + [$sdsprofilesyncenabled, $schoolid, $schoolname] = + local_o365\feature\sds\utils::get_profile_sync_status_with_id_name(); if ($sdsprofilesyncenabled) { - $remotefields['sds_school_id'] = get_string('settings_fieldmap_field_sds_school_id', 'auth_oidc', - get_config('local_o365', 'sdsprofilesync', $schoolid)); - $remotefields['sds_school_name'] = get_string('settings_fieldmap_field_sds_school_name', 'auth_oidc', $schoolname); + $remotefields['sds_school_id'] = get_string( + 'settings_fieldmap_field_sds_school_id', + 'auth_oidc', + get_config('local_o365', 'sdsprofilesync', $schoolid) + ); + $remotefields['sds_school_name'] = get_string( + 'settings_fieldmap_field_sds_school_name', + 'auth_oidc', + $schoolname + ); $remotefields['sds_school_role'] = get_string('settings_fieldmap_field_sds_school_role', 'auth_oidc'); $remotefields['sds_student_externalId'] = get_string('settings_fieldmap_field_sds_student_externalId', 'auth_oidc'); $remotefields['sds_student_birthDate'] = get_string('settings_fieldmap_field_sds_student_birthDate', 'auth_oidc'); $remotefields['sds_student_grade'] = get_string('settings_fieldmap_field_sds_student_grade', 'auth_oidc'); - $remotefields['sds_student_graduationYear'] = get_string('settings_fieldmap_field_sds_student_graduationYear', - 'auth_oidc'); - $remotefields['sds_student_studentNumber'] = get_string('settings_fieldmap_field_sds_student_studentNumber', - 'auth_oidc'); + $remotefields['sds_student_graduationYear'] = get_string( + 'settings_fieldmap_field_sds_student_graduationYear', + 'auth_oidc' + ); + $remotefields['sds_student_studentNumber'] = get_string( + 'settings_fieldmap_field_sds_student_studentNumber', + 'auth_oidc' + ); $remotefields['sds_teacher_externalId'] = get_string('settings_fieldmap_field_sds_teacher_externalId', 'auth_oidc'); - $remotefields['sds_teacher_teacherNumber'] = get_string('settings_fieldmap_field_sds_teacher_teacherNumber', - 'auth_oidc'); + $remotefields['sds_teacher_teacherNumber'] = get_string( + 'settings_fieldmap_field_sds_teacher_teacherNumber', + 'auth_oidc' + ); } } else { $remotefields = [ @@ -452,15 +481,26 @@ function auth_oidc_apply_default_email_mapping() { * @param boolean $updateremotefields Allow remote updates * @param array $customfields list of custom profile fields */ -function auth_oidc_display_auth_lock_options($settings, $auth, $userfields, $helptext, $mapremotefields, $updateremotefields, - $customfields = []) { +function auth_oidc_display_auth_lock_options( + $settings, + $auth, + $userfields, + $helptext, + $mapremotefields, + $updateremotefields, + $customfields = [] +) { global $DB; // Introductory explanation and help text. if ($mapremotefields) { - $settings->add(new admin_setting_heading($auth.'/data_mapping', new lang_string('auth_data_mapping', 'auth'), $helptext)); + $settings->add( + new admin_setting_heading($auth . '/data_mapping', new lang_string('auth_data_mapping', 'auth'), $helptext) + ); } else { - $settings->add(new admin_setting_heading($auth.'/auth_fieldlocks', new lang_string('auth_fieldlocks', 'auth'), $helptext)); + $settings->add( + new admin_setting_heading($auth . '/auth_fieldlocks', new lang_string('auth_fieldlocks', 'auth'), $helptext) + ); } // Generate the list of options. @@ -525,36 +565,69 @@ function auth_oidc_display_auth_lock_options($settings, $auth, $userfields, $hel // Display a message that the field can not be mapped because it's too long. $url = new moodle_url('/user/profile/index.php'); $a = (object)['fieldname' => s($fieldname), 'shortname' => s($field), 'charlimit' => 67, 'link' => $url->out()]; - $settings->add(new admin_setting_heading($auth.'/field_not_mapped_'.sha1($field), '', - get_string('cannotmapfield', 'auth', $a))); + $settings->add(new admin_setting_heading( + $auth . '/field_not_mapped_' . sha1($field), + '', + get_string('cannotmapfield', 'auth', $a) + )); } else if ($mapremotefields) { // We are mapping to a remote field here. // Mapping. if ($field == 'email') { - $settings->add(new admin_setting_configselect("auth_oidc/field_map_{$field}", - get_string('auth_fieldmapping', 'auth', $fieldname), '', null, $emailremotefields)); + $settings->add(new admin_setting_configselect( + "auth_oidc/field_map_{$field}", + get_string('auth_fieldmapping', 'auth', $fieldname), + '', + null, + $emailremotefields + )); } else { - $settings->add(new admin_setting_configselect("auth_oidc/field_map_{$field}", - get_string('auth_fieldmapping', 'auth', $fieldname), '', null, $remotefields)); + $settings->add(new admin_setting_configselect( + "auth_oidc/field_map_{$field}", + get_string('auth_fieldmapping', 'auth', $fieldname), + '', + null, + $remotefields + )); } // Update local. - $settings->add(new admin_setting_configselect("auth_{$auth}/field_updatelocal_{$field}", - get_string('auth_updatelocalfield', 'auth', $fieldname), '', 'always', $updatelocaloptions)); + $settings->add(new admin_setting_configselect( + "auth_{$auth}/field_updatelocal_{$field}", + get_string('auth_updatelocalfield', 'auth', $fieldname), + '', + 'always', + $updatelocaloptions + )); // Update remote. if ($updateremotefields) { - $settings->add(new admin_setting_configselect("auth_{$auth}/field_updateremote_{$field}", - get_string('auth_updateremotefield', 'auth', $fieldname), '', 0, $updateextoptions)); + $settings->add(new admin_setting_configselect( + "auth_{$auth}/field_updateremote_{$field}", + get_string('auth_updateremotefield', 'auth', $fieldname), + '', + 0, + $updateextoptions + )); } // Lock fields. - $settings->add(new admin_setting_configselect("auth_{$auth}/field_lock_{$field}", - get_string('auth_fieldlockfield', 'auth', $fieldname), '', 'unlocked', $lockoptions)); + $settings->add(new admin_setting_configselect( + "auth_{$auth}/field_lock_{$field}", + get_string('auth_fieldlockfield', 'auth', $fieldname), + '', + 'unlocked', + $lockoptions + )); } else { // Lock fields Only. - $settings->add(new admin_setting_configselect("auth_{$auth}/field_lock_{$field}", - get_string('auth_fieldlockfield', 'auth', $fieldname), '', 'unlocked', $lockoptions)); + $settings->add(new admin_setting_configselect( + "auth_{$auth}/field_lock_{$field}", + get_string('auth_fieldlockfield', 'auth', $fieldname), + '', + 'unlocked', + $lockoptions + )); } } } @@ -708,8 +781,12 @@ function auth_oidc_get_binding_username_claim(): string { $bindingusernameclaim = 'auto'; } else if ($bindingusernameclaim === 'custom') { $bindingusernameclaim = get_config('auth_oidc', 'customclaimname'); - } else if (!in_array($bindingusernameclaim, ['auto', 'preferred_username', 'email', 'upn', 'unique_name', 'sub', 'oid', - 'samaccountname'])) { + } else if ( + !in_array( + $bindingusernameclaim, + ['auto', 'preferred_username', 'email', 'upn', 'unique_name', 'sub', 'oid', 'samaccountname'] + ) + ) { $bindingusernameclaim = 'auto'; } @@ -741,8 +818,10 @@ function auth_oidc_get_existing_claims(): array { $decodedtoken = jwt::decode($tokenrecord->$tokenkey); if (is_array($decodedtoken) && count($decodedtoken) > 1) { foreach ($decodedtoken[1] as $claim => $value) { - if (!in_array($claim, $excludedclaims) && (is_string($value) || is_numeric($value)) && - !in_array($claim, $tokenclaims)) { + if ( + !in_array($claim, $excludedclaims) && (is_string($value) || is_numeric($value)) && + !in_array($claim, $tokenclaims) + ) { $tokenclaims[] = $claim; } } diff --git a/manageapplication.php b/manageapplication.php index 401b8881..79ce389e 100644 --- a/manageapplication.php +++ b/manageapplication.php @@ -55,10 +55,14 @@ $form = new application(null, ['oidcconfig' => $oidcconfig]); $formdata = []; -foreach (['idptype', 'clientid', 'clientauthmethod', 'clientsecret', 'clientprivatekey', 'clientcert', - 'clientcertsource', 'clientprivatekeyfile', 'clientcertfile', 'clientcertpassphrase', - 'authendpoint', 'tokenendpoint', 'oidcresource', 'oidcscope', 'secretexpiryrecipients', - 'bindingusernameclaim', 'customclaimname'] as $field) { +foreach ( + [ + 'idptype', 'clientid', 'clientauthmethod', 'clientsecret', 'clientprivatekey', 'clientcert', + 'clientcertsource', 'clientprivatekeyfile', 'clientcertfile', 'clientcertpassphrase', + 'authendpoint', 'tokenendpoint', 'oidcresource', 'oidcscope', 'secretexpiryrecipients', + 'bindingusernameclaim', 'customclaimname', + ] as $field +) { if (isset($oidcconfig->$field)) { $formdata[$field] = $oidcconfig->$field; } diff --git a/settings.php b/settings.php index 121db834..dd4255ad 100644 --- a/settings.php +++ b/settings.php @@ -39,107 +39,176 @@ $ADMIN->add('authsettings', $oidcfolder); // Application configuration page. - $ADMIN->add('oidcfolder', new admin_externalpage('auth_oidc_application', get_string('settings_page_application', 'auth_oidc'), - new moodle_url('/auth/oidc/manageapplication.php'))); - + $ADMIN->add('oidcfolder', new admin_externalpage( + 'auth_oidc_application', + get_string('settings_page_application', 'auth_oidc'), + new moodle_url('/auth/oidc/manageapplication.php') + )); $idptype = get_config('auth_oidc', 'idptype'); if ($idptype) { // Binding username claim page. - $ADMIN->add('oidcfolder', new admin_externalpage('auth_oidc_binding_username_claim', + $ADMIN->add('oidcfolder', new admin_externalpage( + 'auth_oidc_binding_username_claim', get_string('settings_page_binding_username_claim', 'auth_oidc'), - new moodle_url('/auth/oidc/binding_username_claim.php'))); + new moodle_url('/auth/oidc/binding_username_claim.php') + )); // Change binding username claim tool page. - $ADMIN->add('oidcfolder', new admin_externalpage('auth_oidc_change_binding_username_claim_tool', + $ADMIN->add('oidcfolder', new admin_externalpage( + 'auth_oidc_change_binding_username_claim_tool', get_string('settings_page_change_binding_username_claim_tool', 'auth_oidc'), - new moodle_url('/auth/oidc/change_binding_username_claim_tool.php'))); + new moodle_url('/auth/oidc/change_binding_username_claim_tool.php') + )); } - // Other settings page and its settings. $settings = new admin_settingpage($section, get_string('settings_page_other_settings', 'auth_oidc')); // Basic heading. - $settings->add(new admin_setting_heading('auth_oidc/basic_heading', get_string('heading_basic', 'auth_oidc'), - get_string('heading_basic_desc', 'auth_oidc'))); + $settings->add(new admin_setting_heading( + 'auth_oidc/basic_heading', + get_string('heading_basic', 'auth_oidc'), + get_string('heading_basic_desc', 'auth_oidc') + )); // Redirect URI. - $settings->add(new auth_oidc_admin_setting_redirecturi('auth_oidc/redirecturi', - get_string('cfg_redirecturi_key', 'auth_oidc'), get_string('cfg_redirecturi_desc', 'auth_oidc'), utils::get_redirecturl())); + $settings->add(new auth_oidc_admin_setting_redirecturi( + 'auth_oidc/redirecturi', + get_string('cfg_redirecturi_key', 'auth_oidc'), + get_string('cfg_redirecturi_desc', 'auth_oidc'), + utils::get_redirecturl() + )); // Link to authentication options. $authenticationconfigurationurl = new moodle_url('/auth/oidc/manageapplication.php'); - $settings->add(new admin_setting_description('auth_oidc/authenticationlink', + $settings->add(new admin_setting_description( + 'auth_oidc/authenticationlink', get_string('settings_page_application', 'auth_oidc'), - get_string('cfg_authenticationlink_desc', 'auth_oidc', $authenticationconfigurationurl->out()))); + get_string('cfg_authenticationlink_desc', 'auth_oidc', $authenticationconfigurationurl->out()) + )); // Additional options heading. - $settings->add(new admin_setting_heading('auth_oidc/additional_options_heading', - get_string('heading_additional_options', 'auth_oidc'), get_string('heading_additional_options_desc', 'auth_oidc'))); + $settings->add(new admin_setting_heading( + 'auth_oidc/additional_options_heading', + get_string('heading_additional_options', 'auth_oidc'), + get_string('heading_additional_options_desc', 'auth_oidc') + )); // Force redirect. - $settings->add(new admin_setting_configcheckbox('auth_oidc/forceredirect', - get_string('cfg_forceredirect_key', 'auth_oidc'), get_string('cfg_forceredirect_desc', 'auth_oidc'), 0)); + $settings->add(new admin_setting_configcheckbox( + 'auth_oidc/forceredirect', + get_string('cfg_forceredirect_key', 'auth_oidc'), + get_string('cfg_forceredirect_desc', 'auth_oidc'), + 0 + )); // Silent login mode. $forceloginconfigurl = new moodle_url('/admin/settings.php', ['section' => 'sitepolicies']); - $settings->add(new admin_setting_configcheckbox('auth_oidc/silentloginmode', + $settings->add(new admin_setting_configcheckbox( + 'auth_oidc/silentloginmode', get_string('cfg_silentloginmode_key', 'auth_oidc'), - get_string('cfg_silentloginmode_desc', 'auth_oidc', $forceloginconfigurl->out(false)), 0)); + get_string('cfg_silentloginmode_desc', 'auth_oidc', $forceloginconfigurl->out(false)), + 0 + )); // Auto-append. - $settings->add(new admin_setting_configtext('auth_oidc/autoappend', - get_string('cfg_autoappend_key', 'auth_oidc'), get_string('cfg_autoappend_desc', 'auth_oidc'), '', PARAM_TEXT)); + $settings->add(new admin_setting_configtext( + 'auth_oidc/autoappend', + get_string('cfg_autoappend_key', 'auth_oidc'), + get_string('cfg_autoappend_desc', 'auth_oidc'), + '', + PARAM_TEXT + )); // Domain hint. - $settings->add(new admin_setting_configtext('auth_oidc/domainhint', - get_string('cfg_domainhint_key', 'auth_oidc'), get_string('cfg_domainhint_desc', 'auth_oidc'), '' , PARAM_TEXT)); + $settings->add(new admin_setting_configtext( + 'auth_oidc/domainhint', + get_string('cfg_domainhint_key', 'auth_oidc'), + get_string('cfg_domainhint_desc', 'auth_oidc'), + '', + PARAM_TEXT + )); // Login flow. - $settings->add(new auth_oidc_admin_setting_loginflow('auth_oidc/loginflow', - get_string('cfg_loginflow_key', 'auth_oidc'), '', 'authcode')); + $settings->add(new auth_oidc_admin_setting_loginflow( + 'auth_oidc/loginflow', + get_string('cfg_loginflow_key', 'auth_oidc'), + '', + 'authcode' + )); // User restrictions heading. - $settings->add(new admin_setting_heading('auth_oidc/user_restrictions_heading', - get_string('heading_user_restrictions', 'auth_oidc'), get_string('heading_user_restrictions_desc', 'auth_oidc'))); + $settings->add(new admin_setting_heading( + 'auth_oidc/user_restrictions_heading', + get_string('heading_user_restrictions', 'auth_oidc'), + get_string('heading_user_restrictions_desc', 'auth_oidc') + )); // User restrictions. - $settings->add(new admin_setting_configtextarea('auth_oidc/userrestrictions', - get_string('cfg_userrestrictions_key', 'auth_oidc'), get_string('cfg_userrestrictions_desc', 'auth_oidc'), '', PARAM_TEXT)); + $settings->add(new admin_setting_configtextarea( + 'auth_oidc/userrestrictions', + get_string('cfg_userrestrictions_key', 'auth_oidc'), + get_string('cfg_userrestrictions_desc', 'auth_oidc'), + '', + PARAM_TEXT + )); // User restrictions case sensitivity. - $settings->add(new admin_setting_configcheckbox('auth_oidc/userrestrictionscasesensitive', + $settings->add(new admin_setting_configcheckbox( + 'auth_oidc/userrestrictionscasesensitive', get_string('cfg_userrestrictionscasesensitive_key', 'auth_oidc'), - get_string('cfg_userrestrictionscasesensitive_desc', 'auth_oidc'), '1')); + get_string('cfg_userrestrictionscasesensitive_desc', 'auth_oidc'), + '1' + )); // Sign out integration heading. - $settings->add(new admin_setting_heading('auth_oidc/sign_out_heading', - get_string('heading_sign_out', 'auth_oidc'), get_string('heading_sign_out_desc', 'auth_oidc'))); + $settings->add(new admin_setting_heading( + 'auth_oidc/sign_out_heading', + get_string('heading_sign_out', 'auth_oidc'), + get_string('heading_sign_out_desc', 'auth_oidc') + )); // Single sign out from Moodle to IdP. - $settings->add(new admin_setting_configcheckbox('auth_oidc/single_sign_off', + $settings->add(new admin_setting_configcheckbox( + 'auth_oidc/single_sign_off', get_string('cfg_signoffintegration_key', 'auth_oidc'), - get_string('cfg_signoffintegration_desc', 'auth_oidc', $CFG->wwwroot), '0')); + get_string('cfg_signoffintegration_desc', 'auth_oidc', $CFG->wwwroot), + '0' + )); // IdP logout endpoint. - $settings->add(new admin_setting_configtext('auth_oidc/logouturi', - get_string('cfg_logoutendpoint_key', 'auth_oidc'), get_string('cfg_logoutendpoint_desc', 'auth_oidc'), - 'https://login.microsoftonline.com/organizations/oauth2/logout', PARAM_URL)); + $settings->add(new admin_setting_configtext( + 'auth_oidc/logouturi', + get_string('cfg_logoutendpoint_key', 'auth_oidc'), + get_string('cfg_logoutendpoint_desc', 'auth_oidc'), + 'https://login.microsoftonline.com/organizations/oauth2/logout', + PARAM_URL + )); // Front channel logout URL. - $settings->add(new auth_oidc_admin_setting_redirecturi('auth_oidc/logoutendpoint', - get_string('cfg_frontchannellogouturl_key', 'auth_oidc'), get_string('cfg_frontchannellogouturl_desc', 'auth_oidc'), - utils::get_frontchannellogouturl())); + $settings->add(new auth_oidc_admin_setting_redirecturi( + 'auth_oidc/logoutendpoint', + get_string('cfg_frontchannellogouturl_key', 'auth_oidc'), + get_string('cfg_frontchannellogouturl_desc', 'auth_oidc'), + utils::get_frontchannellogouturl() + )); // Display heading. - $settings->add(new admin_setting_heading('auth_oidc/display_heading', - get_string('heading_display', 'auth_oidc'), get_string('heading_display_desc', 'auth_oidc'))); + $settings->add(new admin_setting_heading( + 'auth_oidc/display_heading', + get_string('heading_display', 'auth_oidc'), + get_string('heading_display_desc', 'auth_oidc') + )); // Provider Name (opname). - $settings->add(new admin_setting_configtext('auth_oidc/opname', - get_string('cfg_opname_key', 'auth_oidc'), get_string('cfg_opname_desc', 'auth_oidc'), - get_string('pluginname', 'auth_oidc'), PARAM_TEXT)); + $settings->add(new admin_setting_configtext( + 'auth_oidc/opname', + get_string('cfg_opname_key', 'auth_oidc'), + get_string('cfg_opname_desc', 'auth_oidc'), + get_string('pluginname', 'auth_oidc'), + PARAM_TEXT + )); // Icon. $icons = [ @@ -219,31 +288,51 @@ 'component' => 'moodle', ], ]; - $settings->add(new auth_oidc_admin_setting_iconselect('auth_oidc/icon', - get_string('cfg_icon_key', 'auth_oidc'), get_string('cfg_icon_desc', 'auth_oidc'), 'auth_oidc:o365', $icons)); + $settings->add(new auth_oidc_admin_setting_iconselect( + 'auth_oidc/icon', + get_string('cfg_icon_key', 'auth_oidc'), + get_string('cfg_icon_desc', 'auth_oidc'), + 'auth_oidc:o365', + $icons + )); // Custom icon. $configkey = new lang_string('cfg_customicon_key', 'auth_oidc'); $configdesc = new lang_string('cfg_customicon_desc', 'auth_oidc'); - $customiconsetting = new admin_setting_configstoredfile('auth_oidc/customicon', - get_string('cfg_customicon_key', 'auth_oidc'), get_string('cfg_customicon_desc', 'auth_oidc'), 'customicon', 0, - ['accepted_types' => ['.png', '.jpg', '.ico'], 'maxbytes' => get_max_upload_file_size()]); + $customiconsetting = new admin_setting_configstoredfile( + 'auth_oidc/customicon', + get_string('cfg_customicon_key', 'auth_oidc'), + get_string('cfg_customicon_desc', 'auth_oidc'), + 'customicon', + 0, + ['accepted_types' => ['.png', '.jpg', '.ico'], 'maxbytes' => get_max_upload_file_size()] + ); $customiconsetting->set_updatedcallback('auth_oidc_initialize_customicon'); $settings->add($customiconsetting); // Debugging heading. - $settings->add(new admin_setting_heading('auth_oidc/debugging_heading', - get_string('heading_debugging', 'auth_oidc'), get_string('heading_debugging_desc', 'auth_oidc'))); + $settings->add(new admin_setting_heading( + 'auth_oidc/debugging_heading', + get_string('heading_debugging', 'auth_oidc'), + get_string('heading_debugging_desc', 'auth_oidc') + )); // Record debugging messages. - $settings->add(new admin_setting_configcheckbox('auth_oidc/debugmode', - get_string('cfg_debugmode_key', 'auth_oidc'), get_string('cfg_debugmode_desc', 'auth_oidc'), '0')); + $settings->add(new admin_setting_configcheckbox( + 'auth_oidc/debugmode', + get_string('cfg_debugmode_key', 'auth_oidc'), + get_string('cfg_debugmode_desc', 'auth_oidc'), + '0' + )); $ADMIN->add('oidcfolder', $settings); // Cleanup OIDC tokens page. - $ADMIN->add('oidcfolder', new admin_externalpage('auth_oidc_cleanup_oidc_tokens', - get_string('settings_page_cleanup_oidc_tokens', 'auth_oidc'), new moodle_url('/auth/oidc/cleanupoidctokens.php'))); + $ADMIN->add('oidcfolder', new admin_externalpage( + 'auth_oidc_cleanup_oidc_tokens', + get_string('settings_page_cleanup_oidc_tokens', 'auth_oidc'), + new moodle_url('/auth/oidc/cleanupoidctokens.php') + )); // Other settings page and its settings. $fieldmappingspage = new admin_settingpage('auth_oidc_field_mapping', get_string('settings_page_field_mapping', 'auth_oidc')); @@ -251,8 +340,15 @@ // Display locking / mapping of profile fields. $authplugin = get_auth_plugin('oidc'); - auth_oidc_display_auth_lock_options($fieldmappingspage, $authplugin->authtype, $authplugin->userfields, - get_string('cfg_field_mapping_desc', 'auth_oidc'), true, false, $authplugin->get_custom_user_profile_fields()); + auth_oidc_display_auth_lock_options( + $fieldmappingspage, + $authplugin->authtype, + $authplugin->userfields, + get_string('cfg_field_mapping_desc', 'auth_oidc'), + true, + false, + $authplugin->get_custom_user_profile_fields() + ); } $settings = null; diff --git a/tests/privacy_provider_test.php b/tests/privacy_provider_test.php index 6a3989c2..8e3d56b1 100644 --- a/tests/privacy_provider_test.php +++ b/tests/privacy_provider_test.php @@ -36,7 +36,6 @@ * @group office365_privacy */ final class privacy_provider_test extends \core_privacy\tests\provider_testcase { - /** * Tests set up. */ @@ -310,5 +309,4 @@ private static function create_prevlogin(int $userid): \stdClass { $record->id = $DB->insert_record('auth_oidc_prevlogin', $record); return $record; } - } diff --git a/ucp.php b/ucp.php index 5d5d701e..b049e865 100644 --- a/ucp.php +++ b/ucp.php @@ -23,9 +23,9 @@ * @copyright (C) 2014 onwards Microsoft, Inc. (http://microsoft.com/) */ -require_once(__DIR__.'/../../config.php'); -require_once(__DIR__.'/auth.php'); -require_once(__DIR__.'/lib.php'); +require_once(__DIR__ . '/../../config.php'); +require_once(__DIR__ . '/auth.php'); +require_once(__DIR__ . '/lib.php'); require_login(); @@ -44,13 +44,13 @@ if ($action === 'connectlogin' && $oidcloginconnected === false) { // Use authorization request login flow to connect existing users. auth_oidc_connectioncapability($USER->id, 'connect', true); - $auth = new \auth_oidc\loginflow\authcode; + $auth = new \auth_oidc\loginflow\authcode(); $auth->set_httpclient(new \auth_oidc\httpclient()); $auth->initiateauthrequest(); } else if ($action === 'disconnectlogin' && $oidcloginconnected === true) { if (is_enabled_auth('manual') === true) { auth_oidc_connectioncapability($USER->id, 'disconnect', true); - $auth = new \auth_plugin_oidc; + $auth = new \auth_plugin_oidc(); $auth->set_httpclient(new \auth_oidc\httpclient()); $auth->disconnect(); } diff --git a/version.php b/version.php index 0d41472c..92cd5759 100644 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2025040810; +$plugin->version = 2025040815; $plugin->requires = 2025040800; -$plugin->release = '5.0.2'; +$plugin->release = '5.0.4'; $plugin->component = 'auth_oidc'; $plugin->maturity = MATURITY_STABLE;