mirror of
https://github.com/moodle/moodle.git
synced 2025-06-01 21:55:12 +02:00
MDL-58090 oauth2: Move code from subclasses to config
Allow the behaviour of each oauth service to be customised by config instead of subclasses. Part of MDL-58220
This commit is contained in:
parent
60237253a2
commit
8445556b4c
81
admin/tool/oauth2/classes/form/endpoint.php
Normal file
81
admin/tool/oauth2/classes/form/endpoint.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the form add/update oauth2 endpoint.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_oauth2\form;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use stdClass;
|
||||
use core\form\persistent;
|
||||
|
||||
/**
|
||||
* Issuer form.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class endpoint extends persistent {
|
||||
|
||||
protected static $persistentclass = 'core\\oauth2\\endpoint';
|
||||
|
||||
protected static $fieldstoremove = array('submitbutton', 'action');
|
||||
|
||||
/**
|
||||
* Define the form - called by parent constructor
|
||||
*/
|
||||
public function definition() {
|
||||
global $PAGE;
|
||||
|
||||
$mform = $this->_form;
|
||||
$endpoint = $this->get_persistent();
|
||||
|
||||
$mform->addElement('header', 'generalhdr', get_string('general'));
|
||||
|
||||
// Name.
|
||||
$mform->addElement('text', 'name', get_string('endpointname', 'tool_oauth2'), 'maxlength="255"');
|
||||
$mform->addRule('name', null, 'required', null, 'client');
|
||||
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('name', 'endpointname', 'tool_oauth2');
|
||||
|
||||
// Url.
|
||||
$mform->addElement('text', 'url', get_string('endpointurl', 'tool_oauth2'), 'maxlength="1024"');
|
||||
$mform->addRule('url', null, 'required', null, 'client');
|
||||
$mform->addRule('url', get_string('maximumchars', '', 1024), 'maxlength', 1024, 'client');
|
||||
$mform->addHelpButton('url', 'endpointurl', 'tool_oauth2');
|
||||
|
||||
$mform->addElement('hidden', 'action', 'edit');
|
||||
$mform->setType('action', PARAM_RAW);
|
||||
|
||||
$mform->addElement('hidden', 'issuerid', $endpoint->get('issuerid'));
|
||||
$mform->setType('issuerid', PARAM_INT);
|
||||
$mform->setConstant('issuerid', $this->_customdata['issuerid']);
|
||||
|
||||
$mform->addElement('hidden', 'id', $endpoint->get('id'));
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class issuer extends persistent {
|
||||
global $PAGE;
|
||||
|
||||
$mform = $this->_form;
|
||||
$provider = $this->get_persistent();
|
||||
$endpoint = $this->get_persistent();
|
||||
|
||||
$mform->addElement('header', 'generalhdr', get_string('general'));
|
||||
|
||||
@ -77,7 +77,7 @@ class issuer extends persistent {
|
||||
$mform->addHelpButton('baseurl', 'issuerbaseurl', 'tool_oauth2');
|
||||
|
||||
// Offline access type
|
||||
$options = $provider->get_behaviour_list();
|
||||
$options = $endpoint->get_behaviour_list();
|
||||
$mform->addElement('select', 'behaviour', get_string('issuerbehaviour', 'tool_oauth2'), $options);
|
||||
$mform->addHelpButton('behaviour', 'issuerbehaviour', 'tool_oauth2');
|
||||
|
||||
@ -97,7 +97,7 @@ class issuer extends persistent {
|
||||
$mform->addElement('hidden', 'action', 'edit');
|
||||
$mform->setType('action', PARAM_RAW);
|
||||
|
||||
$mform->addElement('hidden', 'id', $provider->get('id'));
|
||||
$mform->addElement('hidden', 'id', $endpoint->get('id'));
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));
|
||||
|
80
admin/tool/oauth2/classes/form/user_field_mapping.php
Normal file
80
admin/tool/oauth2/classes/form/user_field_mapping.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains the form add/update oauth2 user_field_mapping.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_oauth2\form;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use stdClass;
|
||||
use core\form\persistent;
|
||||
|
||||
/**
|
||||
* Issuer form.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class user_field_mapping extends persistent {
|
||||
|
||||
protected static $persistentclass = 'core\\oauth2\\user_field_mapping';
|
||||
|
||||
protected static $fieldstoremove = array('submitbutton', 'action');
|
||||
|
||||
/**
|
||||
* Define the form - called by parent constructor
|
||||
*/
|
||||
public function definition() {
|
||||
global $PAGE;
|
||||
|
||||
$mform = $this->_form;
|
||||
$userfieldmapping = $this->get_persistent();
|
||||
|
||||
$mform->addElement('header', 'generalhdr', get_string('general'));
|
||||
|
||||
// External.
|
||||
$mform->addElement('text', 'externalfield', get_string('userfieldexternalfield', 'tool_oauth2'), 'maxlength="255"');
|
||||
$mform->addRule('externalfield', null, 'required', null, 'client');
|
||||
$mform->addRule('externalfield', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('externalfield', 'userfieldexternalfield', 'tool_oauth2');
|
||||
|
||||
// Internal.
|
||||
$choices = $userfieldmapping->get_internalfield_list();
|
||||
$mform->addElement('select', 'internalfield', get_string('userfieldinternalfield', 'tool_oauth2'), $choices);
|
||||
$mform->addHelpButton('internalfield', 'userfieldinternalfield', 'tool_oauth2');
|
||||
|
||||
$mform->addElement('hidden', 'action', 'edit');
|
||||
$mform->setType('action', PARAM_RAW);
|
||||
|
||||
$mform->addElement('hidden', 'issuerid', $userfieldmapping->get('issuerid'));
|
||||
$mform->setConstant('issuerid', $this->_customdata['issuerid']);
|
||||
$mform->setType('issuerid', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'id', $userfieldmapping->get('id'));
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$this->add_action_buttons(true, get_string('savechanges', 'tool_oauth2'));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ class renderer extends plugin_renderer_base {
|
||||
$name = $issuer->get('name');
|
||||
$image = $issuer->get('image');
|
||||
if ($image) {
|
||||
$name = '<img width=24 height=24 alt="" src="' . $image . '"> ' . $name;
|
||||
$name = '<img width=24 height=24 alt="" src="' . s($image) . '"> ' . s($name);
|
||||
}
|
||||
$namecell = new html_table_cell($name);
|
||||
$namecell->header = true;
|
||||
@ -104,7 +104,11 @@ class renderer extends plugin_renderer_base {
|
||||
if (!empty($issuer->get('scopessupported'))) {
|
||||
$discovered = $OUTPUT->pix_icon('yes', get_string('discovered', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
$discovered = $OUTPUT->pix_icon('no', get_string('notdiscovered', 'tool_oauth2'), 'tool_oauth2');
|
||||
if ($issuer->get('behaviour') == $issuer::BEHAVIOUR_OPENID_CONNECT) {
|
||||
$discovered = $OUTPUT->pix_icon('no', get_string('notdiscovered', 'tool_oauth2'), 'tool_oauth2');
|
||||
} else {
|
||||
$discovered = '-';
|
||||
}
|
||||
}
|
||||
$discoverystatuscell = new html_table_cell($discovered);
|
||||
|
||||
@ -125,22 +129,37 @@ class renderer extends plugin_renderer_base {
|
||||
|
||||
$systemauthstatuscell = new html_table_cell($systemauth);
|
||||
|
||||
// Action links.
|
||||
$links = '';
|
||||
// Action links.
|
||||
$editurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['id' => $issuer->get('id'), 'action' => 'edit']);
|
||||
$editlink = html_writer::link($editurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
|
||||
|
||||
$links .= ' ' . $editlink;
|
||||
|
||||
// Endpoints.
|
||||
$editendpointsurl = new moodle_url('/admin/tool/oauth2/endpoints.php', ['issuerid' => $issuer->get('id')]);
|
||||
$str = get_string('editendpoints', 'tool_oauth2');
|
||||
$editendpointlink = html_writer::link($editendpointsurl, $OUTPUT->pix_icon('t/viewdetails', $str));
|
||||
$links .= ' ' . $editendpointlink;
|
||||
|
||||
// User field mapping.
|
||||
$edituserfieldmappingsurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', ['issuerid' => $issuer->get('id')]);
|
||||
$str = get_string('edituserfieldmappings', 'tool_oauth2');
|
||||
$edituserfieldmappinglink = html_writer::link($edituserfieldmappingsurl, $OUTPUT->pix_icon('t/user', $str));
|
||||
$links .= ' ' . $edituserfieldmappinglink;
|
||||
|
||||
// Delete.
|
||||
$deleteurl = new moodle_url('/admin/tool/oauth2/issuers.php', ['id' => $issuer->get('id'), 'action' => 'delete']);
|
||||
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
|
||||
$links .= ' ' . $deletelink;
|
||||
if (!$last) {
|
||||
// Move down.
|
||||
$params = ['id' => $issuer->get('id'), 'action' => 'movedown', 'sesskey' => sesskey()];
|
||||
$movedownurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
$movedownlink = html_writer::link($movedownurl, $OUTPUT->pix_icon('t/down', get_string('movedown')));
|
||||
$links .= ' ' . $movedownlink;
|
||||
}
|
||||
if (!$first) {
|
||||
// Move up.
|
||||
$params = ['id' => $issuer->get('id'), 'action' => 'moveup', 'sesskey' => sesskey()];
|
||||
$moveupurl = new moodle_url('/admin/tool/oauth2/issuers.php', $params);
|
||||
$moveuplink = html_writer::link($moveupurl, $OUTPUT->pix_icon('t/up', get_string('moveup')));
|
||||
@ -164,4 +183,119 @@ class renderer extends plugin_renderer_base {
|
||||
$table->data = $data;
|
||||
return html_writer::table($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will render one beautiful table with all the endpoints.
|
||||
*
|
||||
* @param \core\oauth2\endpoint[] $endpoints - list of all endpoints.
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function endpoints_table($endpoints, $issuerid) {
|
||||
global $CFG, $OUTPUT;
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = [
|
||||
get_string('name'),
|
||||
get_string('url'),
|
||||
get_string('edit'),
|
||||
];
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$data = [];
|
||||
|
||||
$index = 0;
|
||||
|
||||
foreach ($endpoints as $endpoint) {
|
||||
// Name.
|
||||
$name = $endpoint->get('name');
|
||||
$namecell = new html_table_cell(s($name));
|
||||
$namecell->header = true;
|
||||
|
||||
// Url
|
||||
$url = $endpoint->get('url');
|
||||
$urlcell = new html_table_cell(s($url));
|
||||
|
||||
$links = '';
|
||||
// Action links.
|
||||
$editparams = ['issuerid' => $issuerid, 'endpointid' => $endpoint->get('id'), 'action' => 'edit'];
|
||||
$editurl = new moodle_url('/admin/tool/oauth2/endpoints.php', $editparams);
|
||||
$editlink = html_writer::link($editurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
|
||||
$links .= ' ' . $editlink;
|
||||
|
||||
// Delete.
|
||||
$deleteparams = ['issuerid' => $issuerid, 'endpointid' => $endpoint->get('id'), 'action' => 'delete'];
|
||||
$deleteurl = new moodle_url('/admin/tool/oauth2/endpoints.php', $deleteparams);
|
||||
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
|
||||
$links .= ' ' . $deletelink;
|
||||
|
||||
$editcell = new html_table_cell($links);
|
||||
|
||||
$row = new html_table_row([
|
||||
$namecell,
|
||||
$urlcell,
|
||||
$editcell,
|
||||
]);
|
||||
|
||||
$data[] = $row;
|
||||
$index++;
|
||||
}
|
||||
$table->data = $data;
|
||||
return html_writer::table($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will render one beautiful table with all the user_field_mappings.
|
||||
*
|
||||
* @param \core\oauth2\user_field_mapping[] $userfieldmappings - list of all user_field_mappings.
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function user_field_mappings_table($userfieldmappings, $issuerid) {
|
||||
global $CFG, $OUTPUT;
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = [
|
||||
get_string('userfieldexternalfield', 'tool_oauth2'),
|
||||
get_string('userfieldinternalfield', 'tool_oauth2'),
|
||||
get_string('edit'),
|
||||
];
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$data = [];
|
||||
|
||||
$index = 0;
|
||||
|
||||
foreach ($userfieldmappings as $userfieldmapping) {
|
||||
// External field
|
||||
$externalfield = $userfieldmapping->get('externalfield');
|
||||
$externalfieldcell = new html_table_cell(s($externalfield));
|
||||
|
||||
// Internal field
|
||||
$internalfield = $userfieldmapping->get('internalfield');
|
||||
$internalfieldcell = new html_table_cell(s($internalfield));
|
||||
|
||||
$links = '';
|
||||
// Action links.
|
||||
$editparams = ['issuerid' => $issuerid, 'userfieldmappingid' => $userfieldmapping->get('id'), 'action' => 'edit'];
|
||||
$editurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $editparams);
|
||||
$editlink = html_writer::link($editurl, $OUTPUT->pix_icon('t/edit', get_string('edit')));
|
||||
$links .= ' ' . $editlink;
|
||||
|
||||
// Delete.
|
||||
$deleteparams = ['issuerid' => $issuerid, 'userfieldmappingid' => $userfieldmapping->get('id'), 'action' => 'delete'];
|
||||
$deleteurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $deleteparams);
|
||||
$deletelink = html_writer::link($deleteurl, $OUTPUT->pix_icon('t/delete', get_string('delete')));
|
||||
$links .= ' ' . $deletelink;
|
||||
|
||||
$editcell = new html_table_cell($links);
|
||||
|
||||
$row = new html_table_row([
|
||||
$externalfieldcell,
|
||||
$internalfieldcell,
|
||||
$editcell,
|
||||
]);
|
||||
|
||||
$data[] = $row;
|
||||
$index++;
|
||||
}
|
||||
$table->data = $data;
|
||||
return html_writer::table($table);
|
||||
}
|
||||
}
|
||||
|
128
admin/tool/oauth2/endpoints.php
Normal file
128
admin/tool/oauth2/endpoints.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* OAuth 2 Endpoing Configuration page.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
$PAGE->set_url('/admin/tool/oauth2/endpoints.php', ['issuerid' => required_param('issuerid', PARAM_INT)]);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('admin');
|
||||
$strheading = get_string('pluginname', 'tool_oauth2');
|
||||
$PAGE->set_title($strheading);
|
||||
$PAGE->set_heading($strheading);
|
||||
|
||||
require_login();
|
||||
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_oauth2');
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHAEXT);
|
||||
$issuerid = required_param('issuerid', PARAM_INT);
|
||||
$endpointid = optional_param('endpointid', '', PARAM_INT);
|
||||
$endpoint = null;
|
||||
$mform = null;
|
||||
|
||||
$issuer = \core\oauth2\api::get_issuer($issuerid);
|
||||
if (!$issuer) {
|
||||
print_error('invaliddata');
|
||||
}
|
||||
$PAGE->navbar->override_active_url(new moodle_url('/admin/tool/oauth2/issuers.php'), true);
|
||||
|
||||
if (!empty($endpointid)) {
|
||||
$endpoint = \core\oauth2\api::get_endpoint($endpointid);
|
||||
}
|
||||
|
||||
if ($action == 'edit') {
|
||||
if ($endpoint) {
|
||||
$strparams = [ 'issuer' => s($issuer->get('name')), 'endpoint' => s($endpoint->get('name')) ];
|
||||
$PAGE->navbar->add(get_string('editendpoint', 'tool_oauth2', $strparams));
|
||||
} else {
|
||||
$PAGE->navbar->add(get_string('createnewendpoint', 'tool_oauth2', s($issuer->get('name'))));
|
||||
}
|
||||
|
||||
$mform = new \tool_oauth2\form\endpoint(null, ['persistent' => $endpoint, 'issuerid' => $issuerid]);
|
||||
}
|
||||
|
||||
if ($mform && $mform->is_cancelled()) {
|
||||
redirect(new moodle_url('/admin/tool/oauth2/endpoints.php', ['issuerid' => $issuerid]));
|
||||
} else if ($action == 'edit') {
|
||||
|
||||
if ($data = $mform->get_data()) {
|
||||
|
||||
try {
|
||||
if (!empty($data->id)) {
|
||||
core\oauth2\api::update_endpoint($data);
|
||||
} else {
|
||||
core\oauth2\api::create_endpoint($data);
|
||||
}
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
} catch (Exception $e) {
|
||||
redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
if ($endpoint) {
|
||||
$strparams = [ 'issuer' => s($issuer->get('name')), 'endpoint' => s($endpoint->get('name')) ];
|
||||
echo $OUTPUT->heading(get_string('editendpoint', 'tool_oauth2', $strparams));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('createnewendpoint', 'tool_oauth2', s($issuer->get('name'))));
|
||||
}
|
||||
$mform->display();
|
||||
echo $OUTPUT->footer();
|
||||
}
|
||||
|
||||
} else if ($action == 'delete') {
|
||||
|
||||
if (!optional_param('confirm', false, PARAM_BOOL)) {
|
||||
$continueparams = [
|
||||
'action' => 'delete',
|
||||
'issuerid' => $issuerid,
|
||||
'endpointid' => $endpointid,
|
||||
'sesskey' => sesskey(),
|
||||
'confirm' => true
|
||||
];
|
||||
$continueurl = new moodle_url('/admin/tool/oauth2/endpoints.php', $continueparams);
|
||||
$cancelurl = new moodle_url('/admin/tool/oauth2/endpoints.php');
|
||||
echo $OUTPUT->header();
|
||||
$strparams = [ 'issuer' => s($issuer->get('name')), 'endpoint' => s($endpoint->get('name')) ];
|
||||
echo $OUTPUT->confirm(get_string('deleteendpointconfirm', 'tool_oauth2', $strparams), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
require_sesskey();
|
||||
core\oauth2\api::delete_endpoint($endpointid);
|
||||
redirect($PAGE->url, get_string('endpointdeleted', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('endpointsforissuer', 'tool_oauth2', s($issuer->get('name'))));
|
||||
$endpoints = core\oauth2\api::get_endpoints($issuer);
|
||||
echo $renderer->endpoints_table($endpoints, $issuerid);
|
||||
|
||||
$addurl = new moodle_url('/admin/tool/oauth2/endpoints.php', ['action' => 'edit', 'issuerid' => $issuerid]);
|
||||
echo $renderer->single_button($addurl, get_string('createnewendpoint', 'tool_oauth2', s($issuer->get('name'))));
|
||||
echo $OUTPUT->footer();
|
||||
}
|
@ -40,12 +40,12 @@ require_capability('moodle/site:config', context_system::instance());
|
||||
$renderer = $PAGE->get_renderer('tool_oauth2');
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHAEXT);
|
||||
$idpid = optional_param('id', '', PARAM_RAW);
|
||||
$issuerid = optional_param('id', '', PARAM_RAW);
|
||||
$issuer = null;
|
||||
$mform = null;
|
||||
|
||||
if ($idpid) {
|
||||
$issuer = \core\oauth2\api::get_issuer($idpid);
|
||||
if ($issuerid) {
|
||||
$issuer = \core\oauth2\api::get_issuer($issuerid);
|
||||
if (!$issuer) {
|
||||
print_error('invaliddata');
|
||||
}
|
||||
@ -53,7 +53,7 @@ if ($idpid) {
|
||||
|
||||
if ($action == 'edit') {
|
||||
if ($issuer) {
|
||||
$PAGE->navbar->add(get_string('editissuer', 'tool_oauth2', $issuer->get('name')));
|
||||
$PAGE->navbar->add(get_string('editissuer', 'tool_oauth2', s($issuer->get('name'))));
|
||||
} else {
|
||||
$PAGE->navbar->add(get_string('createnewissuer', 'tool_oauth2'));
|
||||
}
|
||||
@ -80,7 +80,7 @@ if ($mform && $mform->is_cancelled()) {
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
if ($issuer) {
|
||||
echo $OUTPUT->heading(get_string('editissuer', 'tool_oauth2', $issuer->get('name')));
|
||||
echo $OUTPUT->heading(get_string('editissuer', 'tool_oauth2', s($issuer->get('name'))));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('createnewissuer', 'tool_oauth2'));
|
||||
}
|
||||
@ -91,30 +91,30 @@ if ($mform && $mform->is_cancelled()) {
|
||||
} else if ($action == 'delete') {
|
||||
|
||||
if (!optional_param('confirm', false, PARAM_BOOL)) {
|
||||
$continueparams = ['action' => 'delete', 'id' => $idpid, 'sesskey' => sesskey(), 'confirm' => true];
|
||||
$continueparams = ['action' => 'delete', 'id' => $issuerid, 'sesskey' => sesskey(), 'confirm' => true];
|
||||
$continueurl = new moodle_url('/admin/tool/oauth2/issuers.php', $continueparams);
|
||||
$cancelurl = new moodle_url('/admin/tool/oauth2/issuers.php');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(get_string('deleteconfirm', 'tool_oauth2', $issuer->get('name')), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->confirm(get_string('deleteconfirm', 'tool_oauth2', s($issuer->get('name'))), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
require_sesskey();
|
||||
core\oauth2\api::delete_issuer($idpid);
|
||||
core\oauth2\api::delete_issuer($issuerid);
|
||||
redirect($PAGE->url, get_string('issuerdeleted', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
} else if ($action == 'auth') {
|
||||
|
||||
if (!optional_param('confirm', false, PARAM_BOOL)) {
|
||||
$continueparams = ['action' => 'auth', 'id' => $idpid, 'sesskey' => sesskey(), 'confirm' => true];
|
||||
$continueparams = ['action' => 'auth', 'id' => $issuerid, 'sesskey' => sesskey(), 'confirm' => true];
|
||||
$continueurl = new moodle_url('/admin/tool/oauth2/issuers.php', $continueparams);
|
||||
$cancelurl = new moodle_url('/admin/tool/oauth2/issuers.php');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(get_string('authconfirm', 'tool_oauth2', $issuer->get('name')), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->confirm(get_string('authconfirm', 'tool_oauth2', s($issuer->get('name'))), $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
require_sesskey();
|
||||
$params = ['sesskey' => sesskey(), 'id' => $idpid, 'action' => 'auth', 'confirm' => true, 'response' => true];
|
||||
$params = ['sesskey' => sesskey(), 'id' => $issuerid, 'action' => 'auth', 'confirm' => true, 'response' => true];
|
||||
if (core\oauth2\api::connect_system_account($issuer, new moodle_url('/admin/tool/oauth2/issuers.php', $params))) {
|
||||
redirect($PAGE->url, get_string('authconnected', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
} else {
|
||||
@ -123,12 +123,12 @@ if ($mform && $mform->is_cancelled()) {
|
||||
}
|
||||
} else if ($action == 'moveup') {
|
||||
require_sesskey();
|
||||
core\oauth2\api::move_up_issuer($idpid);
|
||||
core\oauth2\api::move_up_issuer($issuerid);
|
||||
redirect($PAGE->url);
|
||||
|
||||
} else if ($action == 'movedown') {
|
||||
require_sesskey();
|
||||
core\oauth2\api::move_down_issuer($idpid);
|
||||
core\oauth2\api::move_down_issuer($issuerid);
|
||||
redirect($PAGE->url);
|
||||
|
||||
} else {
|
||||
|
@ -22,8 +22,17 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['pluginname'] = 'Open ID Connect configuration';
|
||||
$string['pluginname'] = 'OAuth 2 Services';
|
||||
$string['editissuer'] = 'Edit identity issuer: {$a}';
|
||||
$string['editendpoint'] = 'Edit endpoint: {$a->endpoint} for issuer {$a->issuer}';
|
||||
$string['endpointsforissuer'] = 'Endpoints for issuer: {$a}';
|
||||
$string['edituserfieldmapping'] = 'Edit user field mapping for issuer {$a}';
|
||||
$string['userfieldmappingsforissuer'] = 'User field mappings for issuer: {$a}';
|
||||
$string['issuers'] = 'Issuers';
|
||||
$string['endpointname'] = 'Name';
|
||||
$string['endpointname_help'] = 'Key used to search for this endpoint. Must end with "_endpoint".';
|
||||
$string['endpointurl'] = 'Url';
|
||||
$string['endpointurl_help'] = 'URL for this endpoint. Must use https:// protocol.';
|
||||
$string['issuername'] = 'Name';
|
||||
$string['issuername_help'] = 'Name of the identity issuer. May be displayed on login page.';
|
||||
$string['issuerimage'] = 'Logo URL';
|
||||
@ -47,6 +56,8 @@ $string['configuredstatus'] = 'Configured';
|
||||
$string['discoverystatus'] = 'Discovery';
|
||||
$string['systemauthstatus'] = 'System account connected';
|
||||
$string['configured'] = 'Configured';
|
||||
$string['editendpoints'] = 'Configure endpoints';
|
||||
$string['edituserfieldmappings'] = 'Configure user field mappings';
|
||||
$string['notconfigured'] = 'Not configured';
|
||||
$string['discovered'] = 'Service discovery successful';
|
||||
$string['notdiscovered'] = 'Service discovery not successful';
|
||||
@ -55,9 +66,19 @@ $string['notloginissuer'] = 'Do not allow login';
|
||||
$string['systemaccountconnected'] = 'System account connected';
|
||||
$string['systemaccountnotconnected'] = 'System account not connected';
|
||||
$string['createnewissuer'] = 'Create new identity issuer';
|
||||
$string['createnewendpoint'] = 'Create new endpoint for issuer "{$a}"';
|
||||
$string['createnewuserfieldmapping'] = 'Create new user field mapping for issuer "{$a}"';
|
||||
$string['deleteconfirm'] = 'Are you sure you want to delete the identity issuer "{$a}"? Any plugins relying on this issuer will stop working.';
|
||||
$string['deleteendpointconfirm'] = 'Are you sure you want to delete the endpoint "{$a->endpoint}" for issuer "{$a->issuer}"? Any plugins relying on this endpoint will stop working.';
|
||||
$string['deleteuserfieldmappingconfirm'] = 'Are you sure you want to delete the user field mapping for issuer "{$a}"?';
|
||||
$string['issuerdeleted'] = 'Identity issuer deleted';
|
||||
$string['endpointdeleted'] = 'Endpoint deleted';
|
||||
$string['userfieldmappingdeleted'] = 'User field mapping deleted';
|
||||
$string['connectsystemaccount'] = 'Connect to a system account';
|
||||
$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['userfieldexternalfield'] = 'External field name';
|
||||
$string['userfieldexternalfield_help'] = 'Name of the field provided by the external OAuth system.';
|
||||
$string['userfieldinternalfield'] = 'Internal field name';
|
||||
$string['userfieldinternalfield_help'] = 'Name of the Moodle user field that should be mapped from the external field.';
|
||||
|
126
admin/tool/oauth2/userfieldmappings.php
Normal file
126
admin/tool/oauth2/userfieldmappings.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* OAuth 2 Endpoing Configuration page.
|
||||
*
|
||||
* @package tool_oauth2
|
||||
* @copyright 2017 Damyon Wiese <damyon@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
$PAGE->set_url('/admin/tool/oauth2/userfieldmappings.php', ['issuerid' => required_param('issuerid', PARAM_INT)]);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('admin');
|
||||
$strheading = get_string('pluginname', 'tool_oauth2');
|
||||
$PAGE->set_title($strheading);
|
||||
$PAGE->set_heading($strheading);
|
||||
|
||||
require_login();
|
||||
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_oauth2');
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHAEXT);
|
||||
$issuerid = required_param('issuerid', PARAM_INT);
|
||||
$userfieldmappingid = optional_param('userfieldmappingid', '', PARAM_INT);
|
||||
$userfieldmapping = null;
|
||||
$mform = null;
|
||||
|
||||
$issuer = \core\oauth2\api::get_issuer($issuerid);
|
||||
if (!$issuer) {
|
||||
print_error('invaliddata');
|
||||
}
|
||||
$PAGE->navbar->override_active_url(new moodle_url('/admin/tool/oauth2/issuers.php'), true);
|
||||
|
||||
if (!empty($userfieldmappingid)) {
|
||||
$userfieldmapping = \core\oauth2\api::get_user_field_mapping($userfieldmappingid);
|
||||
}
|
||||
|
||||
if ($action == 'edit') {
|
||||
if ($userfieldmapping) {
|
||||
$PAGE->navbar->add(get_string('edituserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
|
||||
} else {
|
||||
$PAGE->navbar->add(get_string('createnewuserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
|
||||
}
|
||||
|
||||
$mform = new \tool_oauth2\form\user_field_mapping(null, ['persistent' => $userfieldmapping, 'issuerid' => $issuerid]);
|
||||
}
|
||||
|
||||
if ($mform && $mform->is_cancelled()) {
|
||||
redirect(new moodle_url('/admin/tool/oauth2/userfieldmappings.php', ['issuerid' => $issuerid]));
|
||||
} else if ($action == 'edit') {
|
||||
|
||||
if ($data = $mform->get_data()) {
|
||||
|
||||
try {
|
||||
if (!empty($data->id)) {
|
||||
core\oauth2\api::update_user_field_mapping($data);
|
||||
} else {
|
||||
core\oauth2\api::create_user_field_mapping($data);
|
||||
}
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
} catch (Exception $e) {
|
||||
redirect($PAGE->url, $e->getMessage(), null, \core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
if ($issuer) {
|
||||
echo $OUTPUT->heading(get_string('edituserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('createnewuserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
|
||||
}
|
||||
$mform->display();
|
||||
echo $OUTPUT->footer();
|
||||
}
|
||||
|
||||
} else if ($action == 'delete') {
|
||||
|
||||
if (!optional_param('confirm', false, PARAM_BOOL)) {
|
||||
$continueparams = [
|
||||
'action' => 'delete',
|
||||
'issuerid' => $issuerid,
|
||||
'userfieldmappingid' => $userfieldmappingid,
|
||||
'sesskey' => sesskey(),
|
||||
'confirm' => true
|
||||
];
|
||||
$continueurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', $continueparams);
|
||||
$cancelurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php');
|
||||
echo $OUTPUT->header();
|
||||
$str = get_string('deleteuserfieldmappingconfirm', 'tool_oauth2', s($issuer->get('name')));
|
||||
echo $OUTPUT->confirm($str, $continueurl, $cancelurl);
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
require_sesskey();
|
||||
core\oauth2\api::delete_user_field_mapping($userfieldmappingid);
|
||||
redirect($PAGE->url, get_string('userfieldmappingdeleted', 'tool_oauth2'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('userfieldmappingsforissuer', 'tool_oauth2', s($issuer->get('name'))));
|
||||
$userfieldmappings = core\oauth2\api::get_user_field_mappings($issuer);
|
||||
echo $renderer->user_field_mappings_table($userfieldmappings, $issuerid);
|
||||
|
||||
$addurl = new moodle_url('/admin/tool/oauth2/userfieldmappings.php', ['action' => 'edit', 'issuerid' => $issuerid]);
|
||||
echo $renderer->single_button($addurl, get_string('createnewuserfieldmapping', 'tool_oauth2', s($issuer->get('name'))));
|
||||
echo $OUTPUT->footer();
|
||||
}
|
@ -318,6 +318,11 @@ class auth extends \auth_plugin_base {
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
if (empty($userinfo['username'])) {
|
||||
$errormsg = get_string('notloggedin', 'auth_oauth2');
|
||||
$SESSION->loginerrormsg = $errormsg;
|
||||
redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
|
||||
}
|
||||
|
||||
$userinfo['username'] = trim(core_text::strtolower($userinfo['username']));
|
||||
|
||||
|
@ -68,6 +68,7 @@ class api {
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
|
||||
// Microsoft is a custom setup.
|
||||
$record = (object) [
|
||||
'name' => 'Microsoft',
|
||||
'image' => 'https://www.microsoft.com/favicon.ico',
|
||||
@ -81,29 +82,43 @@ class api {
|
||||
$issuer = new issuer(0, $record);
|
||||
$issuer->create();
|
||||
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => 'authorization_endpoint',
|
||||
'url' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'
|
||||
$endpoints = [
|
||||
'authorization_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
|
||||
'token_endpoint' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
|
||||
'userinfo_endpoint' => 'https://graph.microsoft.com/v1.0/me/',
|
||||
'userpicture_endpoint' => 'https://graph.microsoft.com/v1.0/me/photo/$value',
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => 'token_endpoint',
|
||||
'url' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
foreach ($endpoints as $name => $url) {
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => $name,
|
||||
'url' => $url
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
}
|
||||
|
||||
$record = (object) [
|
||||
'issuerid' => $issuer->get('id'),
|
||||
'name' => 'end_session_endpoint',
|
||||
'url' => 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
|
||||
// Create the field mappings.
|
||||
$mapping = [
|
||||
'givenName' => 'firstname',
|
||||
'surname' => 'lastname',
|
||||
'mail' => 'email',
|
||||
'userPrincipalName' => 'username',
|
||||
'displayName' => 'alternatename',
|
||||
'officeLocation' => 'address',
|
||||
'mobilePhone' => 'phone',
|
||||
'preferredLanguage' => 'lang'
|
||||
];
|
||||
$endpoint = new endpoint(0, $record);
|
||||
$endpoint->create();
|
||||
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::count_records();
|
||||
}
|
||||
|
||||
@ -115,6 +130,14 @@ class api {
|
||||
return new issuer($id);
|
||||
}
|
||||
|
||||
public static function get_endpoint($id) {
|
||||
return new endpoint($id);
|
||||
}
|
||||
|
||||
public static function get_user_field_mapping($id) {
|
||||
return new user_field_mapping($id);
|
||||
}
|
||||
|
||||
public static function get_system_account(issuer $issuer) {
|
||||
return system_account::get_record(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
@ -132,11 +155,13 @@ class api {
|
||||
}
|
||||
|
||||
public static function get_endpoints(issuer $issuer) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
return endpoint::get_records(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
|
||||
public static function get_user_field_mappings(issuer $issuer) {
|
||||
return user_field_mapping::get_records(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
|
||||
protected static function guess_image($issuer) {
|
||||
if (empty($issuer->get('image'))) {
|
||||
$baseurl = parse_url($issuer->get('discoveryurl'));
|
||||
@ -202,6 +227,32 @@ class api {
|
||||
}
|
||||
}
|
||||
|
||||
// We got to here - must be a decent OpenID connect service. Add the default user field mapping list.
|
||||
|
||||
// Create the field mappings.
|
||||
$mapping = [
|
||||
'given_name' => 'firstname',
|
||||
'middle_name' => 'middlename',
|
||||
'family_name' => 'lastname',
|
||||
'email' => 'email',
|
||||
'sub' => 'username',
|
||||
'website' => 'url',
|
||||
'nickname' => 'alternatename',
|
||||
'picture' => 'picture',
|
||||
'address' => 'address',
|
||||
'phone' => 'phone',
|
||||
'locale' => 'lang'
|
||||
];
|
||||
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 endpoint::count_records(['issuerid' => $issuer->get('id')]);
|
||||
}
|
||||
|
||||
@ -215,6 +266,7 @@ class api {
|
||||
// Perform service discovery.
|
||||
self::discover_endpoints($issuer);
|
||||
self::guess_image($issuer);
|
||||
return $issuer;
|
||||
}
|
||||
|
||||
public static function create_issuer($data) {
|
||||
@ -227,6 +279,45 @@ class api {
|
||||
// Perform service discovery.
|
||||
self::discover_endpoints($issuer);
|
||||
self::guess_image($issuer);
|
||||
return $issuer;
|
||||
}
|
||||
|
||||
public static function update_endpoint($data) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$endpoint = new endpoint(0, $data);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$endpoint->update();
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
public static function create_endpoint($data) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$endpoint = new endpoint(0, $data);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$endpoint->create();
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
public static function update_user_field_mapping($data) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$userfieldmapping = new user_field_mapping(0, $data);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$userfieldmapping->update();
|
||||
|
||||
return $userfieldmapping;
|
||||
}
|
||||
|
||||
public static function create_user_field_mapping($data) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$userfieldmapping = new user_field_mapping(0, $data);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$userfieldmapping->create();
|
||||
return $userfieldmapping;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,7 +398,23 @@ class api {
|
||||
}
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
$issuer->delete();
|
||||
return $issuer->delete();
|
||||
}
|
||||
|
||||
public static function delete_endpoint($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$endpoint = new endpoint($id);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
return $endpoint->delete();
|
||||
}
|
||||
|
||||
public static function delete_user_field_mapping($id) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
$userfieldmapping = new user_field_mapping($id);
|
||||
|
||||
// Will throw exceptions on validation failures.
|
||||
return $userfieldmapping->delete();
|
||||
}
|
||||
|
||||
public static function connect_system_account($issuer, $returnurl) {
|
||||
@ -324,6 +431,10 @@ class api {
|
||||
$client->log_out();
|
||||
}
|
||||
|
||||
if (optional_param('error', '', PARAM_RAW)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$client->is_logged_in()) {
|
||||
redirect($client->get_login_url());
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
use moodle_url;
|
||||
use curl;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Configurable oauth2 client class where the urls come from DB.
|
||||
@ -83,35 +84,98 @@ abstract class client extends \oauth2_client {
|
||||
return $this->issuer->get_endpoint_url('authorization');
|
||||
}
|
||||
|
||||
public function get_issuer() {
|
||||
/**
|
||||
* Get the oauth2 issuer for this client.
|
||||
*
|
||||
* @return \core\oauth2\issuer Issuer
|
||||
*/
|
||||
public function get_issuer() {
|
||||
return $this->issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to append additional params to a authentication request.
|
||||
*
|
||||
* @return array (name value pairs).
|
||||
*/
|
||||
public function get_additional_login_parameters() {
|
||||
if ($this->issuer->get('behaviour') == issuer::BEHAVIOUR_OPENID_CONNECT) {
|
||||
return ['access_type' => 'offline', 'prompt' => 'consent'];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to change the scopes requested with an authentiction request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_login_scopes() {
|
||||
return 'openid profile email';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token url for OAuth 2.0 request
|
||||
*
|
||||
* We are overriding the parent function so we get this from the configured endpoint.
|
||||
*
|
||||
* @return string the auth url
|
||||
*/
|
||||
protected function token_url() {
|
||||
return $this->issuer->get_endpoint_url('token');
|
||||
}
|
||||
|
||||
/**
|
||||
* We want a unique key for each issuer / and a different key for system vs user oauth.
|
||||
*
|
||||
* @return string The unique key for the session value.
|
||||
*/
|
||||
protected function get_tokenname() {
|
||||
$name = static::class;
|
||||
$name = 'oauth2-state-' . $this->issuer->get('id');
|
||||
if ($this->system) {
|
||||
$name .= '-system';
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
protected function get_userinfo_mapping() {
|
||||
$fields = user_field_mapping::get_records(['issuerid' => $this->issuer->get('id')]);
|
||||
|
||||
$map = [];
|
||||
foreach ($fields as $field) {
|
||||
$map[$field->get('externalfield')] = $field->get('internalfield');
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
public function get_userinfo() {
|
||||
$url = $this->get_issuer()->get_endpoint_url('userinfo');
|
||||
$response = $this->get($url);
|
||||
if (!$response) {
|
||||
return false;
|
||||
}
|
||||
$userinfo = new stdClass();
|
||||
try {
|
||||
$userinfo = json_decode($response);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$map = $this->get_userinfo_mapping();
|
||||
|
||||
$user = new stdClass();
|
||||
foreach ($map as $openidproperty => $moodleproperty) {
|
||||
if (!empty($userinfo->$openidproperty)) {
|
||||
$user->$moodleproperty = $userinfo->$openidproperty;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($user->picture)) {
|
||||
$user->picture = download_file_content($user->picture, null, null, false, 10, 10, true, null, false);
|
||||
} else {
|
||||
$pictureurl = $this->issuer->get_endpoint_url('userpicture');
|
||||
if (!empty($pictureurl)) {
|
||||
$user->picture = $this->get($pictureurl);
|
||||
}
|
||||
}
|
||||
|
||||
return (array)$user;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace core\oauth2;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* We have to call directly to the graph APIs because the Microsoft Open ID Connect API is
|
||||
@ -36,19 +37,13 @@ use moodle_url;
|
||||
*/
|
||||
class client_microsoft extends client {
|
||||
|
||||
public function get_additional_login_parameters() {
|
||||
return ['prompt' => 'consent'];
|
||||
}
|
||||
|
||||
public function get_login_scopes() {
|
||||
return 'openid profile email user.read';
|
||||
if ($this->system) {
|
||||
return 'openid profile email user.read offline_access';
|
||||
} else {
|
||||
return 'openid profile email user.read';
|
||||
}
|
||||
}
|
||||
|
||||
public function get_userinfo() {
|
||||
$me = $client->get('https://graph.microsoft.com/v1.0/me/');
|
||||
var_dump($me);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,62 +37,10 @@ use Exception;
|
||||
*/
|
||||
class client_openid_connect extends client {
|
||||
|
||||
/**
|
||||
* Returns a mapping of openid properties to moodle properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_mapping() {
|
||||
return [
|
||||
'given_name' => 'firstname',
|
||||
'middle_name' => 'middlename',
|
||||
'family_name' => 'lastname',
|
||||
'email' => 'email',
|
||||
'username' => 'username',
|
||||
'website' => 'url',
|
||||
'nickname' => 'alternatename',
|
||||
'picture' => 'picture',
|
||||
'address' => 'address',
|
||||
'phone' => 'phone',
|
||||
'locale' => 'lang'
|
||||
];
|
||||
}
|
||||
|
||||
public function get_additional_login_parameters() {
|
||||
if ($this->system) {
|
||||
return ['access_type' => 'offline', 'prompt' => 'consent'];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function get_userinfo() {
|
||||
$url = $this->get_issuer()->get_endpoint_url('userinfo');
|
||||
$response = $this->get($url);
|
||||
if (!$response) {
|
||||
return false;
|
||||
}
|
||||
$userinfo = new stdClass();
|
||||
try {
|
||||
$userinfo = json_decode($response);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
if (!empty($userinfo->preferred_username)) {
|
||||
$userinfo->username = $userinfo->preferred_username;
|
||||
} else {
|
||||
$userinfo->username = $userinfo->sub;
|
||||
}
|
||||
|
||||
$map = $this->get_mapping();
|
||||
|
||||
$user = new stdClass();
|
||||
foreach ($map as $openidproperty => $moodleproperty) {
|
||||
if (!empty($userinfo->$openidproperty)) {
|
||||
$user->$moodleproperty = $userinfo->$openidproperty;
|
||||
}
|
||||
}
|
||||
|
||||
return (array)$user;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace core\oauth2;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
use lang_string;
|
||||
|
||||
/**
|
||||
* Class for loading/storing oauth2 endpoints from the DB
|
||||
@ -55,4 +56,11 @@ class endpoint extends persistent {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function validate_url($value) {
|
||||
if (strpos($value, 'https://') !== 0) {
|
||||
return new lang_string('sslonlyaccess', 'error');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
78
lib/classes/oauth2/user_field_mapping.php
Normal file
78
lib/classes/oauth2/user_field_mapping.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class for loading/storing oauth2 endpoints from the DB.
|
||||
*
|
||||
* @package core_oauth2
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\oauth2;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\persistent;
|
||||
|
||||
/**
|
||||
* Class for loading/storing oauth2 user field mappings from the DB
|
||||
*
|
||||
* @copyright 2017 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class user_field_mapping extends persistent {
|
||||
|
||||
const TABLE = 'oauth2_user_field_mapping';
|
||||
|
||||
private static $userfields = [
|
||||
'firstname',
|
||||
'middlename',
|
||||
'lastname',
|
||||
'email',
|
||||
'username',
|
||||
'idnumber',
|
||||
'url',
|
||||
'alternatename',
|
||||
'picture',
|
||||
'address',
|
||||
'phone',
|
||||
'lang'
|
||||
];
|
||||
|
||||
/**
|
||||
* Return the definition of the properties of this model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_properties() {
|
||||
return array(
|
||||
'issuerid' => array(
|
||||
'type' => PARAM_INT
|
||||
),
|
||||
'externalfield' => array(
|
||||
'type' => PARAM_ALPHANUMEXT,
|
||||
),
|
||||
'internalfield' => array(
|
||||
'type' => PARAM_ALPHANUMEXT,
|
||||
'choices' => self::$userfields,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function get_internalfield_list() {
|
||||
return array_combine(self::$userfields, self::$userfields);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="lib/db" VERSION="20170221" COMMENT="XMLDB file for core Moodle tables"
|
||||
<XMLDB PATH="lib/db" VERSION="20170224" COMMENT="XMLDB file for core Moodle tables"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@ -3513,5 +3513,22 @@
|
||||
<KEY NAME="issueridkey" TYPE="foreign-unique" FIELDS="issuerid" REFTABLE="oauth2_issuer" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="oauth2_user_field_mapping" COMMENT="Mapping of oauth user fields to moodle fields.">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was modified"/>
|
||||
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The time this record was created."/>
|
||||
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The user who modified this record."/>
|
||||
<FIELD NAME="issuerid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The oauth issuer."/>
|
||||
<FIELD NAME="externalfield" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The fieldname returned by the userinfo endpoint."/>
|
||||
<FIELD NAME="internalfield" TYPE="char" LENGTH="64" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the Moodle field this user field maps to."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="issuerkey" TYPE="foreign" FIELDS="issuerid" REFTABLE="oauth2_issuer" REFFIELDS="id"/>
|
||||
<KEY NAME="uniqexternal" TYPE="unique" FIELDS="issuerid, externalfield"/>
|
||||
<KEY NAME="uniqinternal" TYPE="unique" FIELDS="issuerid, internalfield"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
|
@ -2699,10 +2699,39 @@ function xmldb_main_upgrade($oldversion) {
|
||||
|
||||
if ($oldversion < 2017033100.01) {
|
||||
|
||||
\core\oauth2\api::install_default_issuers();
|
||||
// Define table oauth2_user_field_mapping to be created.
|
||||
$table = new xmldb_table('oauth2_user_field_mapping');
|
||||
|
||||
// Adding fields to table oauth2_user_field_mapping.
|
||||
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
|
||||
$table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('externalfield', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
|
||||
$table->add_field('internalfield', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
|
||||
|
||||
// Adding keys to table oauth2_user_field_mapping.
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
$table->add_key('issuerkey', XMLDB_KEY_FOREIGN, array('issuerid'), 'oauth2_issuer', array('id'));
|
||||
$table->add_key('uniqexternal', XMLDB_KEY_UNIQUE, array('issuerid', 'externalfield'));
|
||||
$table->add_key('uniqinternal', XMLDB_KEY_UNIQUE, array('issuerid', 'internalfield'));
|
||||
|
||||
// Conditionally launch create table for oauth2_user_field_mapping.
|
||||
if (!$dbman->table_exists($table)) {
|
||||
$dbman->create_table($table);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017033100.01);
|
||||
}
|
||||
|
||||
if ($oldversion < 2017033100.02) {
|
||||
|
||||
\core\oauth2\api::install_default_issuers();
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2017033100.02);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2766,9 +2766,9 @@ class curl {
|
||||
|
||||
// All settings of this class should be init here.
|
||||
$this->resetopt();
|
||||
//if (!empty($settings['debug'])) {
|
||||
if (!empty($settings['debug'])) {
|
||||
$this->debug = true;
|
||||
//}
|
||||
}
|
||||
if (!empty($settings['cookie'])) {
|
||||
if($settings['cookie'] === true) {
|
||||
$this->cookie = $CFG->dataroot.'/curl_cookie.txt';
|
||||
|
@ -441,6 +441,15 @@ abstract class oauth2_client extends curl {
|
||||
|
||||
// We have a token so we are logged in.
|
||||
if (isset($this->accesstoken->token)) {
|
||||
// Check that the access token has all the requested scopes.
|
||||
$scopecheck = ' ' . $this->accesstoken->scope . ' ';
|
||||
|
||||
$requiredscopes = explode(' ', $this->scope);
|
||||
foreach ($requiredscopes as $requiredscope) {
|
||||
if (strpos($scopecheck, ' ' . $requiredscope . ' ') === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -533,6 +542,10 @@ abstract class oauth2_client extends curl {
|
||||
|
||||
$r = json_decode($response);
|
||||
|
||||
if (!empty($r->error)) {
|
||||
throw new moodle_exception($r->error . ' ' . $r->error_description);
|
||||
}
|
||||
|
||||
if (!isset($r->access_token)) {
|
||||
return false;
|
||||
}
|
||||
@ -548,6 +561,12 @@ abstract class oauth2_client extends curl {
|
||||
// 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;
|
||||
|
@ -178,7 +178,7 @@
|
||||
<div class="potentialidplist" class="m-t-1">
|
||||
{{#identityproviders}}
|
||||
<div class="potentialidp">
|
||||
<a href="{{url}}" title={{#quote}}{{name}}{{/quote}} class="btn btn-secondary">
|
||||
<a href="{{url}}" title={{#quote}}{{name}}{{/quote}} class="btn btn-secondary btn-block">
|
||||
{{#iconurl}}
|
||||
<img src="{{iconurl}}" alt="" width="24" height="24"/>
|
||||
{{/iconurl}}
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2017033100.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2017033100.02; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user