Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "imsglobal/lti-1p3-tool",
"type": "library",
"require": {
"fproject/php-jwt": "^4.0",
"firebase/php-jwt": "^5.2",
"phpseclib/phpseclib": "^2.0"
},
"autoload": {
Expand Down
47 changes: 5 additions & 42 deletions src/lti/Cache.php
Original file line number Diff line number Diff line change
@@ -1,46 +1,9 @@
<?php
namespace IMSGlobal\LTI;

class Cache {

private $cache;

public function get_launch_data($key) {
$this->load_cache();
return $this->cache[$key];
}

public function cache_launch_data($key, $jwt_body) {
$this->cache[$key] = $jwt_body;
$this->save_cache();
return $this;
}

public function cache_nonce($nonce) {
$this->cache['nonce'][$nonce] = true;
$this->save_cache();
return $this;
}

public function check_nonce($nonce) {
$this->load_cache();
if (!isset($this->cache['nonce'][$nonce])) {
return false;
}
return true;
}

private function load_cache() {
$cache = file_get_contents(sys_get_temp_dir() . '/lti_cache.txt');
if (empty($cache)) {
file_put_contents(sys_get_temp_dir() . '/lti_cache.txt', '{}');
$this->cache = [];
}
$this->cache = json_decode($cache, true);
}

private function save_cache() {
file_put_contents(sys_get_temp_dir() . '/lti_cache.txt', json_encode($this->cache));
}
interface Cache {
public function get_launch_data($key);
public function cache_launch_data($key, $jwt_body);
public function cache_nonce($nonce);
public function check_nonce($nonce);
}
?>
33 changes: 3 additions & 30 deletions src/lti/Cookie.php
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
<?php
namespace IMSGlobal\LTI;

class Cookie {
public function get_cookie($name) {
if (isset($_COOKIE[$name])) {
return $_COOKIE[$name];
}
// Look for backup cookie if same site is not supported by the user's browser.
if (isset($_COOKIE["LEGACY_" . $name])) {
return $_COOKIE["LEGACY_" . $name];
}
return false;
}

public function set_cookie($name, $value, $exp = 3600, $options = []) {
$cookie_options = [
'expires' => time() + $exp
];

// SameSite none and secure will be required for tools to work inside iframes
$same_site_options = [
'samesite' => 'None',
'secure' => true
];

setcookie($name, $value, array_merge($cookie_options, $same_site_options, $options));

// Set a second fallback cookie in the event that "SameSite" is not supported
setcookie("LEGACY_" . $name, $value, array_merge($cookie_options, $options));
return $this;
}
interface Cookie {
public function get_cookie($name);
public function set_cookie($name, $value, $exp = 3600, $options = []);
}
?>
1 change: 0 additions & 1 deletion src/lti/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ public function find_registration_by_issuer($iss);
public function find_deployment($iss, $deployment_id);
}

?>
45 changes: 45 additions & 0 deletions src/lti/ImsCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
namespace IMSGlobal\LTI;

class ImsCache {

private $cache;

public function get_launch_data($key) {
$this->load_cache();
return $this->cache[$key];
}

public function cache_launch_data($key, $jwt_body) {
$this->cache[$key] = $jwt_body;
$this->save_cache();
return $this;
}

public function cache_nonce($nonce) {
$this->cache['nonce'][$nonce] = true;
$this->save_cache();
return $this;
}

public function check_nonce($nonce) {
$this->load_cache();
if (!isset($this->cache['nonce'][$nonce])) {
return false;
}
return true;
}

private function load_cache() {
$cache = file_get_contents(sys_get_temp_dir() . '/lti_cache.txt');
if (empty($cache)) {
file_put_contents(sys_get_temp_dir() . '/lti_cache.txt', '{}');
$this->cache = [];
}
$this->cache = json_decode($cache, true);
}

private function save_cache() {
file_put_contents(sys_get_temp_dir() . '/lti_cache.txt', json_encode($this->cache));
}
}
33 changes: 33 additions & 0 deletions src/lti/ImsCookie.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
namespace IMSGlobal\LTI;

class ImsCookie {
public function get_cookie($name) {
if (isset($_COOKIE[$name])) {
return $_COOKIE[$name];
}
// Look for backup cookie if same site is not supported by the user's browser.
if (isset($_COOKIE["LEGACY_" . $name])) {
return $_COOKIE["LEGACY_" . $name];
}
return false;
}

public function set_cookie($name, $value, $exp = 3600, $options = []) {
$cookie_options = [
'expires' => time() + $exp
];

// SameSite none and secure will be required for tools to work inside iframes
$same_site_options = [
'samesite' => 'None',
'secure' => true
];

setcookie($name, $value, array_merge($cookie_options, $same_site_options, $options));

// Set a second fallback cookie in the event that "SameSite" is not supported
setcookie("LEGACY_" . $name, $value, array_merge($cookie_options, $options));
return $this;
}
}
5 changes: 2 additions & 3 deletions src/lti/LTI_Assignments_Grades_Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public function __construct(LTI_Service_Connector $service_connector, $service_d
}

public function put_grade(LTI_Grade $grade, LTI_Lineitem $lineitem = null) {
if (!in_array("https://purl.imsglobal.org/spec/lti-ags/scope/score", $this->service_data['scope'])) {
if (!in_array(LTI_Constants::AGS_SCORE, $this->service_data['scope'])) {
throw new LTI_Exception('Missing required scope', 1);
}
$score_url = '';
Expand Down Expand Up @@ -42,7 +42,7 @@ public function put_grade(LTI_Grade $grade, LTI_Lineitem $lineitem = null) {
}

public function find_or_create_lineitem(LTI_Lineitem $new_line_item) {
if (!in_array("https://purl.imsglobal.org/spec/lti-ags/scope/lineitem", $this->service_data['scope'])) {
if (!in_array(LTI_Constants::AGS_LINEITEM, $this->service_data['scope'])) {
throw new LTI_Exception('Missing required scope', 1);
}
$line_items = $this->service_connector->make_service_request(
Expand Down Expand Up @@ -88,4 +88,3 @@ public function get_grades(LTI_Lineitem $lineitem) {
return $scores['body'];
}
}
?>
77 changes: 77 additions & 0 deletions src/lti/LTI_Constants.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace IMSGlobal\LTI;

class LTI_Constants
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super neat and something i've been meaning to do for an age but never brought myself to do it, so thanks for that

{
public const V1_3 = '1.3.0';

// Required message claims
public const MESSAGE_TYPE = 'https://purl.imsglobal.org/spec/lti/claim/message_type';
public const VERSION = 'https://purl.imsglobal.org/spec/lti/claim/version';
public const DEPLOYMENT_ID = 'https://purl.imsglobal.org/spec/lti/claim/deployment_id';
public const TARGET_LINK_URI = 'https://purl.imsglobal.org/spec/lti/claim/target_link_uri';
public const RESOURCE_LINK = 'https://purl.imsglobal.org/spec/lti/claim/resource_link';
public const ROLES = 'https://purl.imsglobal.org/spec/lti/claim/roles';

// Optional message claims
public const CONTEXT = 'https://purl.imsglobal.org/spec/lti/claim/context';
public const TOOL_PLATFORM = 'https://purl.imsglobal.org/spec/lti/claim/tool_platform';
public const ROLE_SCOPE_MENTOR = 'https://purlimsglobal.org/spec/lti/claim/role_scope_mentor';
public const LAUNCH_PRESENTATION = 'https://purl.imsglobal.org/spec/lti/claim/launch_presentation';
public const LIS = 'https://purl.imsglobal.org/spec/lti/claim/lis';
public const CUSTOM = 'https://purl.imsglobal.org/spec/lti/claim/custom';

// LTI DL
public const DL_CONTENT_ITEMS = 'https://purl.imsglobal.org/spec/lti-dl/claim/content_items';
public const DL_DATA = 'https://purl.imsglobal.org/spec/lti-dl/claim/data';
public const DL_DEEP_LINK_SETTINGS = 'https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings';

// LTI NRPS
public const NRPS_CLAIM_SERVICE = 'https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice';
public const NRPS_SCOPE_MEMBERSHIP_READONLY = 'https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly';

// LTI AGS
public const AGS_CLAIM_ENDPOINT = 'https://purl.imsglobal.org/spec/lti-ags/claim/endpoint';
public const AGS_SCOPE_LINEITEM = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem';
public const AGS_SCOPE_LINEITEM_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly';
public const AGS_SCOPE_RESULT_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly';
public const AGS_SCOPE_SCORE = 'https://purl.imsglobal.org/spec/lti-ags/scope/score';

// User Vocab
public const SYSTEM_ADMINISTRATOR = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#Administrator';
public const SYSTEM_NONE = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#None';
public const SYSTEM_ACCOUNTADMIN = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#AccountAdmin';
public const SYSTEM_CREATOR = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#Creator';
public const SYSTEM_SYSADMIN = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#SysAdmin';
public const SYSTEM_SYSSUPPORT = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#SysSupport';
public const SYSTEM_USER = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#User';
public const INSTITUTION_ADMINISTRATOR = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator';
public const INSTITUTION_FACULTY = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Faculty';
public const INSTITUTION_GUEST = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Guest';
public const INSTITUTION_NONE = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#None';
public const INSTITUTION_OTHER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Other';
public const INSTITUTION_STAFF = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Staff';
public const INSTITUTION_STUDENT = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Student';
public const INSTITUTION_ALUMNI = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Alumni';
public const INSTITUTION_INSTRUCTOR = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Instructor';
public const INSTITUTION_LEARNER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Learner';
public const INSTITUTION_MEMBER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Member';
public const INSTITUTION_MENTOR = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Mentor';
public const INSTITUTION_OBSERVER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Observer';
public const INSTITUTION_PROSPECTIVESTUDENT = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#ProspectiveStudent';
public const MEMBERSHIP_ADMINISTRATOR = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Administrator';
public const MEMBERSHIP_CONTENTDEVELOPER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#ContentDeveloper';
public const MEMBERSHIP_INSTRUCTOR = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor';
public const MEMBERSHIP_LEARNER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner';
public const MEMBERSHIP_MENTOR = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Mentor';
public const MEMBERSHIP_MANAGER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Manager';
public const MEMBERSHIP_MEMBER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Member';
public const MEMBERSHIP_OFFICER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Officer';

// Context Vocab
public const COURSE_TEMPLATE = 'http://purl.imsglobal.org/vocab/lis/v2/course#CourseTemplate';
public const COURSE_OFFERING = 'http://purl.imsglobal.org/vocab/lis/v2/course#CourseOffering';
public const COURSE_SECTION = 'http://purl.imsglobal.org/vocab/lis/v2/course#CourseSection';
public const COURSE_GROUP = 'http://purl.imsglobal.org/vocab/lis/v2/course#Group';
}
11 changes: 5 additions & 6 deletions src/lti/LTI_Deep_Link.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ public function get_response_jwt($resources) {
"exp" => time() + 600,
"iat" => time(),
"nonce" => 'nonce' . hash('sha256', random_bytes(64)),
"https://purl.imsglobal.org/spec/lti/claim/deployment_id" => $this->deployment_id,
"https://purl.imsglobal.org/spec/lti/claim/message_type" => "LtiDeepLinkingResponse",
"https://purl.imsglobal.org/spec/lti/claim/version" => "1.3.0",
"https://purl.imsglobal.org/spec/lti-dl/claim/content_items" => array_map(function($resource) { return $resource->to_array(); }, $resources),
"https://purl.imsglobal.org/spec/lti-dl/claim/data" => $this->deep_link_settings['data'],
LTI_Constants::DEPLOYMENT_ID => $this->deployment_id,
LTI_Constants::MESSAGE_TYPE => "LtiDeepLinkingResponse",
LTI_Constants::VERSION => LTI_Constants::V1_3,
LTI_Constants::DL_CONTENT_ITEMS => array_map(function($resource) { return $resource->to_array(); }, $resources),
LTI_Constants::DL_DATA => $this->deep_link_settings['data'],
];
return JWT::encode($message_jwt, $this->registration->get_tool_private_key(), 'RS256', $this->registration->get_kid());
}
Expand All @@ -43,4 +43,3 @@ public function output_response_form($resources) {
<?php
}
}
?>
2 changes: 1 addition & 1 deletion src/lti/LTI_Deep_Link_Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,4 @@ public function to_array() {
return $resource;
}
}
?>

1 change: 0 additions & 1 deletion src/lti/LTI_Deployment.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ public function set_deployment_id($deployment_id) {

}

?>
1 change: 0 additions & 1 deletion src/lti/LTI_Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
class LTI_Exception extends \Exception {

}
?>
1 change: 0 additions & 1 deletion src/lti/LTI_Grade.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,3 @@ public function __toString() {
]));
}
}
?>
1 change: 0 additions & 1 deletion src/lti/LTI_Lineitem.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,3 @@ public function __toString() {
]));
}
}
?>
Loading