diff --git a/lib/classes/oauth2/api.php b/lib/classes/oauth2/api.php index 9d62a2de3f8..bd1a9c51523 100644 --- a/lib/classes/oauth2/api.php +++ b/lib/classes/oauth2/api.php @@ -197,7 +197,50 @@ class api { return system_account::get_record(['issuerid' => $issuer->get('id')]); } + public static function get_system_scopes_for_issuer($issuer) { + $scopes = $issuer->get('loginscopesoffline'); + + $pluginsfunction = get_plugins_with_function('oauth2_system_scopes', 'lib.php'); + foreach ($pluginsfunction as $plugintype => $plugins) { + foreach ($plugins as $pluginfunction) { + // Get additional scopes from the plugin. + $pluginscopes = $pluginfunction($issuer); + if (empty($pluginscopes)) { + continue; + } + + // Merge the additional scopes with the existing ones. + $additionalscopes = explode(' ', $pluginscopes); + + foreach ($additionalscopes as $scope) { + if (!empty($scope)) { + if (strpos(' ' . $scopes . ' ', ' ' . $scope . ' ') === false) { + $scopes .= ' ' . $scope; + } + } + } + } + } + + return $scopes; + } + public static function get_system_oauth_client(issuer $issuer) { + $systemaccount = self::get_system_account($issuer); + if (empty($systemaccount)) { + return false; + } + // Get all the scopes! + $scopes = self::get_system_scopes_for_issuer($issuer); + + $client = new \core\oauth2\client($issuer, null, $scopes, true); + + if (!$client->is_logged_in()) { + if (!$client->update_refresh_token($systemaccount)) { + return false; + } + } + return $client; } public static function get_user_oauth_client(issuer $issuer, moodle_url $currenturl, $additionalscopes = '') { diff --git a/lib/classes/oauth2/client.php b/lib/classes/oauth2/client.php index 263db910eac..3947b0c3dac 100644 --- a/lib/classes/oauth2/client.php +++ b/lib/classes/oauth2/client.php @@ -156,6 +156,65 @@ class client extends \oauth2_client { return $map; } + /** + * Upgrade a refresh token from oauth 2.0 to an access token + * + * @return boolean true if token is upgraded succesfully + */ + public function upgrade_refresh_token(system_account $systemaccount) { + $refreshtoken = $systemaccount->get('refreshtoken'); + + $params = array('refresh_token' => $refreshtoken, + 'client_id' => $this->clientid, + 'client_secret' => $this->clientsecret, + 'grant_type' => 'refresh_token' + ); + + // Requests can either use http GET or POST. + if ($this->use_http_get()) { + $response = $this->get($this->token_url(), $params); + } else { + $response = $this->post($this->token_url(), $this->build_post_data($params)); + } + + if (!$this->info['http_code'] === 200) { + throw new moodle_exception('Could not upgrade oauth token'); + } + + $r = json_decode($response); + + if (!empty($r->error)) { + throw new moodle_exception($r->error . ' ' . $r->error_description); + } + + if (!isset($r->access_token)) { + return false; + } + + if (isset($r->refresh_token)) { + $systemaccount->set('refreshtoken', $r->refresh_token); + $systemaccount->update(); + $this->refreshtoken = $r->refresh_token; + } + + // Store the token an expiry time. + $accesstoken = new stdClass; + $accesstoken->token = $r->access_token; + if (isset($r->expires_in)) { + // Expires 10 seconds before actual expiry. + $accesstoken->expires = (time() + ($r->expires_in - 10)); + } + if (isset($r->scope)) { + $accesstoken->scope = $r->scope; + } else { + $accesstoken->scope = $this->scope; + } + // Also add the scopes. + $this->store_token($accesstoken); + + return true; + } + public function get_userinfo() { $url = $this->get_issuer()->get_endpoint_url('userinfo'); $response = $this->get($url);