Commit 7a25dad5 authored by Cecilia Vela Gurovic's avatar Cecilia Vela Gurovic Committed by Robert Lyon
Browse files

Bug 1903601: LTI Advantage (1.3) module

Impliments Names and Role Provisioning Services
Provides Basic Launch support

Change-Id: I76adc7b1dae49eb5d5f96e243d225371b88aec26
parent ec8530b0
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
<?php
/**
 * The main module file.
 *
 * @package    mahara
 * @subpackage module-monitor
 * @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.
 *
 */

defined('INTERNAL') || die();

require_once('lib/lti-1-3-php-library/lti/lti.php');
require_once(dirname(dirname(dirname(__FILE__))) . '/init.php');

use IMSGlobal\LTI;

class LTI_Advantage_Database implements LTI\Database {

    public function find_registration_by_issuer($iss) {
        $registration = get_record('lti_advantage_registration', 'issuer', $iss);

        if (!$registration) {
            return false;
        }

        $key = get_record('lti_advantage_key', 'key_set_id', $registration->key_set_id);

        if (!$key) {
            return false;
        }

        return LTI\LTI_Registration::new()
            ->set_issuer($registration->issuer)
            ->set_client_id($registration->client_id)
            ->set_auth_login_url($registration->platform_login_auth_endpoint)
            ->set_auth_token_url($registration->platform_service_auth_endpoint)
            ->set_key_set_url($registration->platform_jwks_endpoint)
            ->set_auth_server($registration->platform_auth_provider)
            ->set_kid($key->id)
            ->set_tool_private_key($key->private_key);

    }

    public function find_deployment($iss, $deployment_id) {
        // make sure we have the right id
        $sql = "
            SELECT d.deployment_id FROM
            {lti_advantage_deployment} d
            JOIN {lti_advantage_registration} r
            ON d.registration_id = r.id
            WHERE r.issuer = ? AND d.deployment_id = ?";

        $deployment = get_field_sql($sql, array($iss, $deployment_id));

        if (!$deployment) {
            return false;
        }

        return LTI\LTI_Deployment::new()
            ->set_deployment_id($deployment);
    }

    public function get_keys_in_set($key_set_id) {
        $key = get_records_array('lti_advantage_key', 'key_set_id', $key_set_id);
        if (!$key) {
            return false;
        }

        $keys = array();
        foreach ($key as $k) {
            $keys[$k->id] = $k->private_key;
        }

        return $keys;
    }
}
+73 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="module/lti_advantagedb" VERSION="20201117" COMMENT="XMLDB file for lti 1.3 related tables"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
    <TABLES>
        <TABLE NAME="lti_advantage_key_set">
            <FIELDS>
                <FIELD NAME="id"  TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="will contain uuid" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="id" />
            </KEYS>
        </TABLE>
        <TABLE NAME="lti_advantage_key">
            <FIELDS>
                <FIELD NAME="id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="will contain uuid" />
                <FIELD NAME="key_set_id"  TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="will contain uuid" />
                <FIELD NAME="private_key" TYPE="text" NOTNULL="true" />
                <FIELD NAME="alg" TYPE="text" NOTNULL="true" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="id" />
                <KEY NAME="keysetidfk" TYPE="foreign" FIELDS="key_set_id" REFTABLE="lti_advantage_key_set" REFFIELDS="id" />
            </KEYS>
        </TABLE>
        <TABLE NAME="lti_advantage_registration">
            <FIELDS>
                <FIELD NAME="id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="will contain uuid" />
                <FIELD NAME="issuer" TYPE="text" NOTNULL="true" />
                <FIELD NAME="client_id" TYPE="text" NOTNULL="true" COMMENT="This is the id received in the 'aud' during a launch" />
                <FIELD NAME="platform_login_auth_endpoint" TYPE="text" NOTNULL="true" COMMENT="The platform's OIDC login endpoint" />
                <FIELD NAME="platform_service_auth_endpoint" TYPE="text" NOTNULL="true" COMMENT="The platform's service authorization endpoint - AUTH TOKEN URL"/>
                <FIELD NAME="platform_jwks_endpoint" TYPE="text" NOTNULL="true" COMMENT="The platform's JWKS endpoint - KEY SET URL"/>
                <FIELD NAME="platform_auth_provider" TYPE="text" NOTNULL="false" />
                <FIELD NAME="key_set_id" TYPE="char" LENGTH="255" NOTNULL="true" COMMENT="will contain uuid" />
                <FIELD NAME="connectionid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="id" />
                <KEY NAME="keysetidfk" TYPE="foreign" FIELDS="key_set_id" REFTABLE="lti_advantage_key_set" REFFIELDS="id" />
                <KEY NAME="connectionidfk" TYPE="foreign" FIELDS="connectionid" REFTABLE="oauth_server_registry" REFFIELDS="id" />
            </KEYS>
        </TABLE>
        <TABLE NAME="lti_advantage_deployment">
            <FIELDS>
                <FIELD NAME="deployment_id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" />
                <FIELD NAME="registration_id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="will contain uuid" />
                <FIELD NAME="customer_id" TYPE="text" NOTNULL="true" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="registration_id,deployment_id" />
                <KEY NAME="registrationidfk" TYPE="foreign" FIELDS="registration_id" REFTABLE="lti_advantage_registration" REFFIELDS="id" />
            </KEYS>
        </TABLE>
         <TABLE NAME="lti_advantage_group_membership">
            <FIELDS>
                <FIELD NAME="id" TYPE="int" LENGTH="10" SEQUENCE="true" NOTNULL="true" />
                <FIELD NAME="context_memberships_url" TYPE="text" NOTNULL="true" />
                <FIELD NAME="service_versions" TYPE="text" NOTNULL="false" />
                <FIELD NAME="registration_id" TYPE="char" LENGTH="255" NOTNULL="true" />
                <FIELD NAME="state" TYPE="text" NOTNULL="false" />
                <FIELD NAME="group_id" TYPE="int" LENGTH="10" NOTNULL="true" />
                <FIELD NAME="external_unit_id" TYPE="text" NOTNULL="true" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="id" />
                <KEY NAME="registrationidfk" TYPE="foreign" FIELDS="registration_id" REFTABLE="lti_advantage_registration" REFFIELDS="id" />
                <KEY NAME="groupidfk" TYPE="foreign" FIELDS="group_id" REFTABLE="group" REFFIELDS="id" />
            </KEYS>
        </TABLE>
    </TABLES>
</XMLDB>
+48 −0
Original line number Diff line number Diff line
<?php
/**
 *
 * @package    mahara
 * @subpackage module-lti
 * @author     Catalyst IT Ltd
 * @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.
 *
 */

defined('INTERNAL') || die();

function xmldb_module_lti_advantage_upgrade($oldversion=0) {

  // Convert deployment_id to a varchar for MySQL key/index compatibility.
  if ($oldversion < 2021072910) {
    log_debug('Upgrade "lti_advantage_deployment" field from text to char.');

    // See if we need to add the id column.
    $table = new XMLDBTable('lti_advantage_deployment');
    if (table_exists($table)) {
      $field = new XMLDBField('deployment_id');
      if (field_exists($table, $field)) {
        // Drop the current primary key as we'll want to rebuild it.
        $key = new XMLDBKey('primary');
        $key->setAttributes(XMLDB_KEY_PRIMARY, array('registration_id', 'deployment_id'));
        if (!drop_key($table, $key)) {
          log_debug('Upgrade "lti_advantage_deployment": failed to drop key.');
          return false;
        }

        // Alter the field.
        $field->setAttributes(XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL);
        if (!change_field_type($table, $field)) {
          log_debug('Upgrade "lti_advantage_deployment": failed to change field type.');
          return false;
        }

        if (!add_key($table, $key)) {
          log_debug('Upgrade "lti_advantage_deployment": failed to add key.');
          return false;
        }
      }
    }
  }
  return true;
}
 No newline at end of file
+84 −0
Original line number Diff line number Diff line
<?php
/**
 *
 * @package    mahara
 * @subpackage module.lti_advantage
 * @author     Catalyst IT Ltd
 * @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.
 *
 */
use \IMSGlobal\LTI;
define('INTERNAL', 1);
define('PUBLIC', 1);

require_once('lib/lti-1-3-php-library/lti/lti.php');
require_once(dirname(dirname(dirname(__FILE__))) . '/init.php');
require_once('database.php');
require_once(dirname(dirname(dirname(__FILE__))) . '/lib/institution.php');
require_once('webservice/functions/module_lti_advantage_launch.php');

$launch = LTI\LTI_Message_Launch::new(new LTI_Advantage_Database())
    ->validate();

$data = $launch->get_launch_data();

global $WEBSERVICE_INSTITUTION, $WEBSERVICE_OAUTH_SERVERID;
$params = array();

// get basic parameters
$userdata = $data['http://www.brightspace.com']; // contains user id
$params['user_id'] = $userdata['user_id'];
$params['ext_user_username'] = $userdata['username'];

$params['given_name'] = $data['given_name'];
$params['family_name'] = $data['family_name'];
$params['email'] = $data['email'];
$params['iss'] = $data['iss'];
$params['deployment_id'] = $data['https://purl.imsglobal.org/spec/lti/claim/deployment_id'];

$params['launch_id'] = $launch->get_launch_id();

// get institution
$sql = "SELECT sr.id, sr.institution FROM {lti_advantage_registration} r
    JOIN {oauth_server_registry} sr
    ON sr.id = r.connectionid
    WHERE r.issuer = ? ";
$webservice = get_record_sql($sql, array($data['iss']));

$WEBSERVICE_INSTITUTION = $webservice->institution;
$WEBSERVICE_OAUTH_SERVERID = $webservice->id;

$unit = $data['https://purl.imsglobal.org/spec/lti/claim/context'];
$params['context_id'] = $unit['id'];
$params['context_label'] = $unit['label'];
$params['context_title'] = $unit['title'];
$params['context_type'] = $unit['type'];

$roles = '';
if ($userroles = $data['https://purl.imsglobal.org/spec/lti/claim/roles']) {
    foreach($userroles as $role) {
        $length = strlen('http://purl.imsglobal.org/vocab/lis/v2/membership#');
        if (substr($role, 0, $length) == 'http://purl.imsglobal.org/vocab/lis/v2/membership#') {
            $roles .= substr($role, $length) . ',';
        }
    }
    $roles = substr($roles, 0, strlen($roles) - 1);
}
$params['roles'] = $roles;

if ($launch->has_nrps()) {
    $namesroleservice = $data['https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice'];
    $params['context_memberships_url'] = $namesroleservice['context_memberships_url'];
    $params['service_versions'] = json_encode($namesroleservice['service_versions']);

}

module_lti_advantage_launch::launch_advantage($params);

redirect();

function is_course_offering($unit) {
    return (isset($unit['type']) && is_array($unit['type']) && in_array('http://purl.imsglobal.org/vocab/lis/v2/course#CourseOffering', $unit['type']));
}
+29 −0
Original line number Diff line number Diff line
<?php
/**
 *
 * @package    mahara
 * @subpackage module.lti_advantage
 * @author     Catalyst IT Ltd
 * @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.
 *
 */

define('INTERNAL', 1);
define('PUBLIC', 1);

require_once('lib/lti-1-3-php-library/lti/lti.php');
require_once('database.php');

use \IMSGlobal\LTI;

//$database = new LTI_Advantage_Database();
//LTI\JWKS_Endpoint::from_issuer($database, 'https://mahara.d2l-partners.brightspace.com')->output_jwks();

$keysetsdb = get_records_assoc('lti_advantage_key');
$keys = array();
foreach ($keysetsdb as $key) {
    $keys[$key->id] = $key->private_key;
}

LTI\JWKS_Endpoint::new($keys)->output_jwks();
 No newline at end of file
Loading