From aed28401be355e9b3d487c170f7bf77de4cca220 Mon Sep 17 00:00:00 2001 From: David Woloszyn Date: Thu, 7 Aug 2025 16:53:48 +1000 Subject: [PATCH] MDL-86004 core: Modify upgrade step for Microsoft endpoints The upgrade step for Microsoft OAuth2 issuers has been modified to address an oversight in MDL-84432. The upgrade now only updates service base urls for multi-tenant issuers. Co-authored-by: Raju Tummoji --- lib/db/upgrade.php | 204 +++++++++++++++++++++++---------------------- version.php | 2 +- 2 files changed, 107 insertions(+), 99 deletions(-) diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 81daa665b77..e1b257c50d4 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1684,104 +1684,6 @@ function xmldb_main_upgrade($oldversion) { // Automatically generated Moodle v5.0.0 release upgrade line. // Put any upgrade step following this. - if ($oldversion < 2025041400.08) { - // A [name => url] map of new OIDC endpoints to be updated/created. - $endpointuris = [ - 'discovery_endpoint' => 'https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration', - 'token_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token', - 'userinfo_endpoint' => 'https://graph.microsoft.com/oidc/userinfo', - 'authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', - 'device_authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/devicecode', - 'end_session_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/logout', - 'kerberos_endpoint' => 'https://login.microsoftonline.com/common/kerberos', - ]; - - // A [name] map of endpoints to be deleted. - $deletedendpointuris = [ - 'userpicture_endpoint', - ]; - - // A [internalfield => externalfield] map of new OIDC-based user field mappings to be updated/created. - $userfieldmappings = [ - 'idnumber' => 'sub', - 'firstname' => 'givenname', - 'lastname' => 'familyname', - 'email' => 'email', - 'lang' => 'locale', - ]; - - $admin = get_admin(); - $adminid = $admin ? $admin->id : '0'; - - $microsoftservices = $DB->get_records('oauth2_issuer', ['servicetype' => 'microsoft']); - foreach ($microsoftservices as $microsoftservice) { - $time = time(); - - // Insert/update the new endpoints. - foreach ($endpointuris as $endpointname => $endpointuri) { - $endpoint = ['issuerid' => $microsoftservice->id, 'name' => $endpointname]; - $endpointid = $DB->get_field('oauth2_endpoint', 'id', $endpoint); - - if ($endpointid) { - $endpoint = array_merge($endpoint, [ - 'id' => $endpointid, - 'url' => $endpointuri, - 'timemodified' => $time, - 'usermodified' => $adminid, - ]); - $DB->update_record('oauth2_endpoint', $endpoint); - } else { - $endpoint = array_merge($endpoint, [ - 'url' => $endpointuri, - 'timecreated' => $time, - 'timemodified' => $time, - 'usermodified' => $adminid, - ]); - $DB->insert_record('oauth2_endpoint', $endpoint); - } - } - - // Delete the old endpoints. - foreach ($deletedendpointuris as $endpointname) { - $endpoint = ['issuerid' => $microsoftservice->id, 'name' => $endpointname]; - $DB->delete_records('oauth2_endpoint', $endpoint); - } - - // Insert/update new user field mappings. - foreach ($userfieldmappings as $internalfieldname => $externalfieldname) { - $fieldmap = ['issuerid' => $microsoftservice->id, 'internalfield' => $internalfieldname]; - $fieldmapid = $DB->get_field('oauth2_user_field_mapping', 'id', $fieldmap); - - if ($fieldmapid) { - $fieldmap = array_merge($fieldmap, [ - 'id' => $fieldmapid, - 'externalfield' => $externalfieldname, - 'timemodified' => $time, - 'usermodified' => $adminid, - ]); - $DB->update_record('oauth2_user_field_mapping', $fieldmap); - } else { - $fieldmap = array_merge($fieldmap, [ - 'externalfield' => $externalfieldname, - 'timecreated' => $time, - 'timemodified' => $time, - 'usermodified' => $adminid, - ]); - $DB->insert_record('oauth2_user_field_mapping', $fieldmap); - } - } - - // Update the baseurl for the issuer. - $microsoftservice->baseurl = 'https://login.microsoftonline.com/common/v2.0'; - $microsoftservice->timemodified = $time; - $microsoftservice->usermodified = $adminid; - $DB->update_record('oauth2_issuer', $microsoftservice); - } - - // Main savepoint reached. - upgrade_main_savepoint(true, 2025041400.08); - } - if ($oldversion < 2025041400.09) { // Define field systememail to be added to oauth2_issuer. @@ -1854,5 +1756,111 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2025041401.08); } + if ($oldversion < 2025041401.10) { + // A [name => url] map of new OIDC endpoints to be updated/created. + $endpointuris = [ + 'discovery_endpoint' => 'https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration', + 'token_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token', + 'userinfo_endpoint' => 'https://graph.microsoft.com/oidc/userinfo', + 'authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize', + 'device_authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/devicecode', + 'end_session_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/logout', + 'kerberos_endpoint' => 'https://login.microsoftonline.com/common/kerberos', + ]; + // A [name] map of endpoints to be deleted. + $deletedendpointuris = [ + 'userpicture_endpoint', + ]; + // A [internalfield => externalfield] map of new OIDC-based user field mappings to be updated/created. + $userfieldmappings = [ + 'idnumber' => 'sub', + 'firstname' => 'givenname', + 'lastname' => 'familyname', + 'email' => 'email', + 'lang' => 'locale', + ]; + $admin = get_admin(); + $adminid = $admin ? $admin->id : '0'; + $microsoftservices = $DB->get_records('oauth2_issuer', ['servicetype' => 'microsoft']); + foreach ($microsoftservices as $microsoftservice) { + $time = time(); + if (strpos($microsoftservice->baseurl, 'common') !== false) { + // Multi-tenant endpoint, proceed with upgrade. + // Insert/update the new endpoints. + foreach ($endpointuris as $endpointname => $endpointuri) { + $endpoint = ['issuerid' => $microsoftservice->id, 'name' => $endpointname]; + $endpointid = $DB->get_field('oauth2_endpoint', 'id', $endpoint); + if ($endpointid) { + $endpoint = array_merge($endpoint, [ + 'id' => $endpointid, + 'url' => $endpointuri, + 'timemodified' => $time, + 'usermodified' => $adminid, + ]); + $DB->update_record('oauth2_endpoint', $endpoint); + } else { + $endpoint = array_merge($endpoint, [ + 'url' => $endpointuri, + 'timecreated' => $time, + 'timemodified' => $time, + 'usermodified' => $adminid, + ]); + $DB->insert_record('oauth2_endpoint', $endpoint); + } + } + // Delete the old endpoints. + foreach ($deletedendpointuris as $endpointname) { + $endpoint = ['issuerid' => $microsoftservice->id, 'name' => $endpointname]; + $DB->delete_records('oauth2_endpoint', $endpoint); + } + // Insert/update new user field mappings. + foreach ($userfieldmappings as $internalfieldname => $externalfieldname) { + $fieldmap = ['issuerid' => $microsoftservice->id, 'internalfield' => $internalfieldname]; + $fieldmapid = $DB->get_field('oauth2_user_field_mapping', 'id', $fieldmap); + if ($fieldmapid) { + $fieldmap = array_merge($fieldmap, [ + 'id' => $fieldmapid, + 'externalfield' => $externalfieldname, + 'timemodified' => $time, + 'usermodified' => $adminid, + ]); + $DB->update_record('oauth2_user_field_mapping', $fieldmap); + } else { + $fieldmap = array_merge($fieldmap, [ + 'externalfield' => $externalfieldname, + 'timecreated' => $time, + 'timemodified' => $time, + 'usermodified' => $adminid, + ]); + $DB->insert_record('oauth2_user_field_mapping', $fieldmap); + } + } + // Update the baseurl for the issuer. + $microsoftservice->baseurl = 'https://login.microsoftonline.com/common/v2.0'; + $microsoftservice->timemodified = $time; + $microsoftservice->usermodified = $adminid; + $DB->update_record('oauth2_issuer', $microsoftservice); + } else { + // Single-tenant endpoint, add discovery_endpoint if it doesn't exist. + $url = $microsoftservice->baseurl; + $url .= (substr($url, -1) === '/') ? '' : '/'; + $url .= '.well-known/openid-configuration'; + $endpoint = ['issuerid' => $microsoftservice->id, 'name' => 'discovery_endpoint']; + $endpointid = $DB->get_field('oauth2_endpoint', 'id', $endpoint); + if (!$endpointid) { + $endpoint = array_merge($endpoint, [ + 'url' => $url, + 'timecreated' => $time, + 'timemodified' => $time, + 'usermodified' => $adminid, + ]); + $DB->insert_record('oauth2_endpoint', $endpoint); + } + } + } + // Main savepoint reached. + upgrade_main_savepoint(true, 2025041401.10); + } + return true; } diff --git a/version.php b/version.php index f58e45c1478..4a9498ceadc 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2025041401.09; // 20250414 = branching date YYYYMMDD - do not modify! +$version = 2025041401.10; // 20250414 = branching date YYYYMMDD - do not modify! // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '5.0.1+ (Build: 20250731)'; // Human-friendly version name