diff --git a/admin/tool/oauth2/issuers.php b/admin/tool/oauth2/issuers.php index 77e4214462b..df19faddcaa 100644 --- a/admin/tool/oauth2/issuers.php +++ b/admin/tool/oauth2/issuers.php @@ -222,6 +222,12 @@ if ($mform && $mform->is_cancelled()) { $addurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params); echo $renderer->single_button($addurl, get_string('linkedin_service', 'tool_oauth2')); + // Clever template. + $docs = 'admin/tool/oauth2/issuers/clever'; + $params = ['action' => 'edittemplate', 'type' => 'clever', 'sesskey' => sesskey(), 'docslink' => $docs]; + $addurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params); + echo $renderer->single_button($addurl, get_string('clever_service', 'tool_oauth2')); + // Generic issuer. $addurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['action' => 'edit']); echo $renderer->single_button($addurl, get_string('custom_service', 'tool_oauth2')); diff --git a/admin/tool/oauth2/lang/en/tool_oauth2.php b/admin/tool/oauth2/lang/en/tool_oauth2.php index 32bd9114bf6..c5e5e2b54a8 100644 --- a/admin/tool/oauth2/lang/en/tool_oauth2.php +++ b/admin/tool/oauth2/lang/en/tool_oauth2.php @@ -27,6 +27,7 @@ $string['acceptrisk_help'] = 'Disabling email verification can potentially allow $string['authconfirm'] = 'This action will grant permanent API access to Moodle for the authenticated account. This is intended to be used as a system account for managing files owned by Moodle.'; $string['authconnected'] = 'The system account is now connected for offline access'; $string['authnotconnected'] = 'The system account was not connected for offline access'; +$string['clever_service'] = 'Clever'; $string['configured'] = 'Configured'; $string['configuredstatus'] = 'Configured'; $string['connectsystemaccount'] = 'Connect to a system account'; diff --git a/lib/classes/oauth2/client/clever.php b/lib/classes/oauth2/client/clever.php new file mode 100644 index 00000000000..1b3aa2b164b --- /dev/null +++ b/lib/classes/oauth2/client/clever.php @@ -0,0 +1,64 @@ +. + +namespace core\oauth2\client; + +use core\oauth2\client; + +/** + * Class clever - Custom client handler to fetch data from Clever + * + * @package core + * @copyright 2022 OpenStax + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class clever extends client { + /** + * Fetch the user id from the userinfo endpoint and then query userdata + * + * @return array|false + */ + public function get_userinfo() { + $userinfo = parent::get_userinfo(); + $userid = $userinfo['idnumber']; + + return $this->get_userdata($userid); + } + + /** + * Obtain user name and email data via the userdata endpoint + * + * @param string $userid User ID value + * @return array|false + */ + private function get_userdata($userid) { + $url = $this->get_issuer()->get_endpoint_url('userdata'); + $url .= '/' . $userid; + + $response = $this->get($url); + if (!$response) { + return false; + } + + $userinfo = json_decode($response); + if (json_last_error() != JSON_ERROR_NONE) { + debugging('Error encountered while decoding user information: ' . json_last_error_msg()); + return false; + } + + return $this->map_userinfo_to_fields($userinfo); + } +} diff --git a/lib/classes/oauth2/service/clever.php b/lib/classes/oauth2/service/clever.php new file mode 100644 index 00000000000..2d4c8ed4bab --- /dev/null +++ b/lib/classes/oauth2/service/clever.php @@ -0,0 +1,92 @@ +. + +namespace core\oauth2\service; + +use core\oauth2\issuer; +use core\oauth2\discovery\openidconnect; +use core\oauth2\endpoint; +use core\oauth2\user_field_mapping; + +/** + * Class for Clever OAuth service, with the specific methods related to it. + * + * @package core + * @copyright 2022 OpenStax + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class clever extends openidconnect implements issuer_interface { + /** + * Build an OAuth2 issuer, with all the default values for this service. + * + * @return issuer The issuer initialised with proper default values. + */ + public static function init(): issuer { + $record = (object) [ + 'name' => 'Clever', + 'image' => 'https://apps.clever.com/favicon.ico', + 'basicauth' => 1, + 'baseurl' => '', + 'showonloginpage' => issuer::LOGINONLY, + 'servicetype' => 'clever', + ]; + + return new issuer(0, $record); + } + + /** + * Create endpoints for this issuer. + * + * @param issuer $issuer Issuer the endpoints should be created for. + * @return issuer + */ + public static function create_endpoints(issuer $issuer): issuer { + $endpoints = [ + 'authorization_endpoint' => 'https://clever.com/oauth/authorize', + 'token_endpoint' => 'https://clever.com/oauth/tokens', + 'userinfo_endpoint' => 'https://api.clever.com/v3.0/me', + 'userdata_endpoint' => 'https://api.clever.com/v3.0/users' + ]; + foreach ($endpoints as $name => $url) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'name' => $name, + 'url' => $url + ]; + $endpoint = new endpoint(0, $record); + $endpoint->create(); + } + + // Create the field mappings. + $mapping = [ + 'data-id' => 'idnumber', + 'data-name-first' => 'firstname', + 'data-name-last' => 'lastname', + 'data-email' => 'email' + ]; + foreach ($mapping as $external => $internal) { + $record = (object) [ + 'issuerid' => $issuer->get('id'), + 'externalfield' => $external, + 'internalfield' => $internal + ]; + $userfieldmapping = new user_field_mapping(0, $record); + $userfieldmapping->create(); + } + + return $issuer; + } +}