Commit 5ecdb0d8 authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review
Browse files

Merge changes from topic 'LTI as child'

* changes:
  Bug 1691317: Allow SAML find user by email address
  Bug 1691317: Making the LTI SSO be a child of another auth
  Bug 1716541: Allowing the check of 'mahara' institution for LTI login
parents 589e4aeb 826d97b4
......@@ -185,7 +185,10 @@ class AuthSaml extends Auth {
throw new AccessDeniedException();
}
}
if ($isremote) {
if ($isremote && !empty($email) && $this->config['loginlink']) {
$user->find_by_email_address($email);
}
else if ($isremote) {
$user->find_by_instanceid_username($this->instanceid, $remoteuser, $isremote);
}
else {
......
......@@ -159,6 +159,53 @@ class User {
return $this;
}
/**
* Populates this object with the user record identified by the given
* email address. Checks in all the places email can be recorded.
*
* @throws AuthUnknownUserException If the user cannot be found. Note that
* deleted users _can_ be found
* @throws UserException If there are more than one user found.
*/
public function find_by_email_address($email) {
if (!is_string($email)) {
throw new InvalidArgumentException('email parameter must be a string to create a User object');
}
$email = strtolower($email);
$sql = 'SELECT
u.*,
' . db_format_tsfield('expiry') . ',
' . db_format_tsfield('lastlogin') . ',
' . db_format_tsfield('lastlastlogin') . ',
' . db_format_tsfield('lastaccess') . ',
' . db_format_tsfield('suspendedctime') . ',
' . db_format_tsfield('ctime') . '
FROM
{usr} u
WHERE u.id IN (
SELECT u.id FROM {usr} u
JOIN {artefact} a ON a.owner = u.id
JOIN {artefact_internal_profile_email} ae ON (ae.owner = u.id and ae.artefact = a.id)
WHERE a.artefacttype = ? AND (LOWER(u.email) = ? OR LOWER(a.title) = ?) GROUP BY u.id
)';
$user = get_record_sql($sql, array('email', $email, $email));
if (false == $user) {
throw new AuthUnknownUserException("User with email \"$email\" is not known");
}
if (count($user) > 1) {
throw new UserException("More than one user with email \"$email\" found");
}
$this->populate($user);
$this->reset_institutions();
return $this;
}
/**
* Finds details for a user given a username and their authentication
* instance.
......
<!-- @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later -->
<!-- @copyright For copyright information on Mahara, please see the README file distributed with this software. -->
<h3>Parent authority</h3>
<p>If you set a parent authority, users will be able to log in using that
authority as well as single sign-on via LTI.</p>
<p>For example, you could set up SAML authentication in your institution
and have that be the parent of LTI. That means that users will be able
to log in via Mahara's inbuilt login form using the SSO button there
as well as via LTI SSO from an external application.</p>
<p>You do not have to set a parent authority. If you do not, users will
only be able to access Mahara via LTI.</p>
\ No newline at end of file
......@@ -28,3 +28,4 @@ $string['webserviceproviderenabled'] = 'Incoming web service requests allowed';
$string['institutiondenied'] = 'Access to \'%s\' is denied. Please contact your institution administrator.';
$string['notreadylabel'] = 'Not ready';
$string['readylabel'] = 'Ready';
$string['parentauthforlti'] = 'Parent authority';
......@@ -18,6 +18,7 @@ class PluginModuleLti extends PluginModule {
private static $default_config = array(
'autocreateusers' => false,
'parentauth' => null,
);
public static function postinst($fromversion) {
......@@ -143,22 +144,58 @@ class PluginModuleLti extends PluginModule {
}
public static function get_oauth_service_config_options($serverid) {
$dbconfig = get_records_assoc('oauth_server_config', 'oauthserverregistryid', $serverid, '', 'field, value');
$rawdbconfig = get_records_sql_array('SELECT c.field, c.value, r.institution FROM {oauth_server_registry} r
LEFT JOIN {oauth_server_config} c ON c.oauthserverregistryid = r.id
WHERE r.id = ?', array($serverid));
$dbconfig = new stdClass();
foreach ($rawdbconfig as $raw) {
$dbconfig->institution = $raw->institution;
if (!empty($raw->field)) {
$dbconfig->{$raw->field} = $raw->value;
}
}
$elements = array(
'institution' => array(
'type' => 'html',
'title' => get_string('institution'),
'value' => institution_display_name($dbconfig->institution),
),
'autocreateusers' => array(
'type' => 'switchbox',
'title' => get_string('autocreateusers', 'module.lti'),
'defaultvalue' => isset($dbconfig['autocreateusers']->value) ? $dbconfig['autocreateusers']->value : self::$default_config['autocreateusers'],
'defaultvalue' => isset($dbconfig->autocreateusers) ? $dbconfig->autocreateusers : self::$default_config['autocreateusers'],
),
);
// Get the active auth instances for this institution that are not webservices
if ($instances = get_records_sql_array("SELECT ai.* FROM {oauth_server_registry} osr
JOIN {auth_instance} ai ON ai.institution = osr.institution
WHERE osr.id = ? AND ai.active = 1 AND ai.authname != 'webservice'", array($serverid))) {
$options = array('' => get_string('None', 'admin'));
foreach ($instances as $instance) {
$options[$instance->id] = get_string('title', 'auth.' . $instance->authname);
}
$elements['parentauth'] = array(
'type' => 'select',
'title' => get_string('parentauthforlti', 'module.lti'),
'defaultvalue' => isset($dbconfig->parentauth) ? $dbconfig->parentauth : self::$default_config['parentauth'],
'options' => $options,
'help' => true,
);
}
return $elements;
}
public static function save_oauth_service_config_options($serverid, $values) {
return update_oauth_server_config($serverid, 'autocreateusers', (int)$values['autocreateusers']);
$options = array('autocreateusers', 'parentauth');
foreach ($options as $option) {
$fordb = isset($values[$option]) ? $values[$option] : null;
update_oauth_server_config($serverid, $option, $fordb);
}
return true;
}
// Disable form fields that are not needed by this plugin
......
......@@ -131,6 +131,11 @@ class module_lti_launch extends external_api {
if (!$is_site_admin) {
// check user is member of configured OAuth institution
$institutions = array_keys(load_user_institutions($userid));
if (empty($institutions)) {
// we check if they are in the 'mahara' institution
$institutions = array('mahara');
}
if (!in_array($WEBSERVICE_INSTITUTION, $institutions)) {
$USER->logout();
die_info(get_string('institutiondenied', 'module.lti', institution_display_name($WEBSERVICE_INSTITUTION)));
......@@ -140,6 +145,7 @@ class module_lti_launch extends external_api {
// Auto create user if auth allowed
$canautocreate = get_field('oauth_server_config', 'value', 'oauthserverregistryid', $WEBSERVICE_OAUTH_SERVERID, 'field', 'autocreateusers');
$parentauthid = get_field('oauth_server_config', 'value', 'oauthserverregistryid', $WEBSERVICE_OAUTH_SERVERID, 'field', 'parentauth');
if (!$userid) {
if ($canautocreate) {
......@@ -149,7 +155,7 @@ class module_lti_launch extends external_api {
$user->password = sha1(uniqid('', true));
$user->firstname = $params['lis_person_name_given'];
$user->lastname = $params['lis_person_name_family'];
$user->authinstance = $authinstanceid;
$user->authinstance = !empty($parentauthid) ? $parentauthid : $authinstanceid;
// Make sure that the username doesn't already exist
if (get_record('usr', 'username', $user->email)) {
......@@ -163,6 +169,15 @@ class module_lti_launch extends external_api {
$updateremote = false;
$updateuser = false;
if ($parentauthid) {
$authremoteuser = new StdClass;
$authremoteuser->authinstance = $parentauthid;
$authremoteuser->remoteusername = $user->username;
$authremoteuser->localusr = $user->id;
insert_record('auth_remote_user', $authremoteuser);
}
}
else {
$USER->logout();
......@@ -171,13 +186,22 @@ class module_lti_launch extends external_api {
}
$user = get_record('usr', 'id', $userid, 'deleted', 0);
if ($updateuser) {
$user->email = $params['lis_person_contact_email_primary'];
$user->firstname = $params['lis_person_name_given'];
$user->lastname = $params['lis_person_name_family'];
$user->authinstance = !empty($parentauthid) ? $parentauthid : $authinstanceid;
unset($user->password);
update_user($user);
$profilefields = new StdClass;
$remoteuser = null;
// We need to update the following fields for both the usr and artefact tables
foreach (array('firstname', 'lastname', 'email') as $field) {
if (isset($user->{$field})) {
$profilefields->{$field} = $user->{$field};
}
}
update_user($user, $profilefields, $remoteuser);
}
log_debug('found userid: '.$user->id);
......
......@@ -608,6 +608,8 @@ function webservice_server_config_form($serverid) {
'sflist' => array(
'value' => pieform(array(
'name' => 'oauthconfigoptions',
'plugintype' => $moduletype,
'pluginname' => $module,
'successcallback' => 'webservice_server_config_submit',
'elements' => $elements)),
)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment