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\discovery; 18 19 use core\http_client; 20 use GuzzleHttp\Exception\ClientException; 21 22 /** 23 * Simple reader class, allowing OAuth 2 Authorization Server Metadata to be read from an auth server's well-known. 24 * 25 * {@link https://www.rfc-editor.org/rfc/rfc8414} 26 * 27 * @package core 28 * @copyright 2023 Jake Dallimore <jrhdallimore@gmail.com> 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 */ 31 class auth_server_config_reader { 32 33 /** @var \stdClass the config object read from the discovery document. */ 34 protected \stdClass $metadata; 35 36 /** @var \moodle_url the base URL for the auth server which was last used during a read.*/ 37 protected \moodle_url $issuerurl; 38 39 /** 40 * Constructor. 41 * 42 * @param http_client $httpclient an http client instance. 43 * @param string $wellknownsuffix the well-known suffix, defaulting to 'oauth-authorization-server'. 44 */ 45 public function __construct(protected http_client $httpclient, 46 protected string $wellknownsuffix = 'oauth-authorization-server') { 47 } 48 49 /** 50 * Read the metadata from the remote host. 51 * 52 * @param \moodle_url $issuerurl the auth server issuer URL. 53 * @return \stdClass the configuration data object. 54 * @throws ClientException|\GuzzleHttp\Exception\GuzzleException if the http client experiences any problems. 55 */ 56 public function read_configuration(\moodle_url $issuerurl): \stdClass { 57 $this->issuerurl = $issuerurl; 58 $this->validate_uri(); 59 60 $url = $this->get_configuration_url()->out(false); 61 $response = $this->httpclient->request('GET', $url); 62 $this->metadata = json_decode($response->getBody()); 63 return $this->metadata; 64 } 65 66 /** 67 * Make sure the base URI is suitable for use in discovery. 68 * 69 * @return void 70 * @throws \moodle_exception if the URI fails validation. 71 */ 72 protected function validate_uri() { 73 if (!empty($this->issuerurl->get_query_string())) { 74 throw new \moodle_exception('Error: '.__METHOD__.': Auth server base URL cannot contain a query component.'); 75 } 76 if (strtolower($this->issuerurl->get_scheme()) !== 'https') { 77 throw new \moodle_exception('Error: '.__METHOD__.': Auth server base URL must use HTTPS scheme.'); 78 } 79 // This catches URL fragments. Since a query string is ruled out above, out_omit_querystring(false) returns only fragments. 80 if ($this->issuerurl->out_omit_querystring() != $this->issuerurl->out(false)) { 81 throw new \moodle_exception('Error: '.__METHOD__.': Auth server base URL must not contain fragments.'); 82 } 83 } 84 85 /** 86 * Get the Auth server metadata URL. 87 * 88 * Per {@link https://www.rfc-editor.org/rfc/rfc8414#section-3}, if the issuer URL contains a path component, 89 * the well known suffix is added between the host and path components. 90 * 91 * @return \moodle_url the full URL to the auth server metadata. 92 */ 93 protected function get_configuration_url(): \moodle_url { 94 $path = $this->issuerurl->get_path(); 95 if (!empty($path) && $path !== '/') { 96 // Insert the well known suffix between the host and path components. 97 $port = $this->issuerurl->get_port() ? ':'.$this->issuerurl->get_port() : ''; 98 $uri = $this->issuerurl->get_scheme() . "://" . $this->issuerurl->get_host() . $port ."/". 99 ".well-known/" . $this->wellknownsuffix . $path; 100 } else { 101 // No path, just append the well known suffix. 102 $uri = $this->issuerurl->out(false); 103 $uri .= (substr($uri, -1) == '/' ? '' : '/'); 104 $uri .= ".well-known/$this->wellknownsuffix"; 105 } 106 107 return new \moodle_url($uri); 108 } 109 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body