Differences Between: [Versions 402 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core\oauth2\service; 18 19 use core\http_client; 20 use core\oauth2\discovery\auth_server_config_reader; 21 use core\oauth2\endpoint; 22 use core\oauth2\issuer; 23 use GuzzleHttp\Psr7\Request; 24 25 /** 26 * MoodleNet OAuth 2 configuration. 27 * 28 * @package core 29 * @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com> 30 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 */ 32 class moodlenet implements issuer_interface { 33 34 /** 35 * Get the issuer template to display in the form. 36 * 37 * @return issuer the issuer. 38 */ 39 public static function init(): ?issuer { 40 $record = (object) [ 41 'name' => 'MoodleNet', 42 'image' => 'https://moodle.net/favicon.ico', 43 'baseurl' => 'https://moodle.net', 44 'loginscopes' => '', 45 'loginscopesoffline' => '', 46 'loginparamsoffline' => '', 47 'showonloginpage' => issuer::SERVICEONLY, 48 'servicetype' => 'moodlenet', 49 ]; 50 $issuer = new issuer(0, $record); 51 52 return $issuer; 53 } 54 55 /** 56 * Create the endpoints for the issuer. 57 * 58 * @param issuer $issuer the issuer instance. 59 * @return issuer the issuer instance. 60 */ 61 public static function create_endpoints(issuer $issuer): issuer { 62 self::discover_endpoints($issuer); 63 return $issuer; 64 } 65 66 /** 67 * Read the OAuth 2 Auth Server Metadata. 68 * 69 * @param issuer $issuer the issuer instance. 70 * @return int the number of endpoints created. 71 */ 72 public static function discover_endpoints($issuer): int { 73 $baseurl = $issuer->get('baseurl'); 74 if (empty($baseurl)) { 75 return 0; 76 } 77 78 $endpointscreated = 0; 79 $config = []; 80 if (defined('BEHAT_SITE_RUNNING')) { 81 $config['verify'] = false; 82 } 83 $configreader = new auth_server_config_reader(new http_client($config)); 84 try { 85 $config = $configreader->read_configuration(new \moodle_url($baseurl)); 86 87 foreach ($config as $key => $value) { 88 if (substr_compare($key, '_endpoint', -strlen('_endpoint')) === 0) { 89 $record = new \stdClass(); 90 $record->issuerid = $issuer->get('id'); 91 $record->name = $key; 92 $record->url = $value; 93 94 $endpoint = new endpoint(0, $record); 95 $endpoint->create(); 96 $endpointscreated++; 97 } 98 99 if ($key == 'scopes_supported') { 100 $issuer->set('scopessupported', implode(' ', $value)); 101 $issuer->update(); 102 } 103 } 104 } catch (\Exception $e) { 105 throw new \moodle_exception('Could not read service configuration for issuer: ' . $issuer->get('name')); 106 } 107 108 try { 109 self::client_registration($issuer); 110 } catch (\Exception $e) { 111 throw new \moodle_exception('Could not register client for issuer: ' . $issuer->get('name')); 112 } 113 114 return $endpointscreated; 115 } 116 117 /** 118 * Perform (open) OAuth 2 Dynamic Client Registration with the MoodleNet application. 119 * 120 * @param issuer $issuer the issuer instance containing the service baseurl. 121 * @return void 122 */ 123 protected static function client_registration(issuer $issuer): void { 124 global $CFG, $SITE; 125 126 $clientid = $issuer->get('clientid'); 127 $clientsecret = $issuer->get('clientsecret'); 128 129 if (empty($clientid) && empty($clientsecret)) { 130 $url = $issuer->get_endpoint_url('registration'); 131 if ($url) { 132 $scopes = str_replace("\r", " ", $issuer->get('scopessupported')); 133 $hosturl = $CFG->wwwroot; 134 135 $request = [ 136 'client_name' => $SITE->fullname, 137 'client_uri' => $hosturl, 138 'logo_uri' => $hosturl . '/pix/f/moodle-256.png', 139 'tos_uri' => $hosturl, 140 'policy_uri' => $hosturl, 141 'software_id' => 'moodle', 142 'software_version' => $CFG->version, 143 'redirect_uris' => [ 144 $hosturl . '/admin/oauth2callback.php' 145 ], 146 'token_endpoint_auth_method' => 'client_secret_basic', 147 'grant_types' => [ 148 'authorization_code', 149 'refresh_token' 150 ], 151 'response_types' => [ 152 'code' 153 ], 154 'scope' => $scopes 155 ]; 156 157 $config = []; 158 if (defined('BEHAT_SITE_RUNNING')) { 159 $config['verify'] = false; 160 } 161 $client = new http_client($config); 162 $request = new Request( 163 'POST', 164 $url, 165 [ 166 'Content-type' => 'application/json', 167 'Accept' => 'application/json', 168 ], 169 json_encode($request) 170 ); 171 172 try { 173 $response = $client->send($request); 174 $responsebody = $response->getBody()->getContents(); 175 $decodedbody = json_decode($responsebody, true); 176 if (is_null($decodedbody)) { 177 throw new \moodle_exception('Error: ' . __METHOD__ . ': Failed to decode response body. Invalid JSON.'); 178 } 179 $issuer->set('clientid', $decodedbody['client_id']); 180 $issuer->set('clientsecret', $decodedbody['client_secret']); 181 $issuer->update(); 182 } catch (\Exception $e) { 183 $msg = "Could not self-register {$issuer->get('name')}. Wrong URL or JSON data [URL: $url]"; 184 throw new \moodle_exception($msg); 185 } 186 } 187 } 188 } 189 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body