From 49a20856ede144cf41b5781a3f461fe16812741a Mon Sep 17 00:00:00 2001 From: Davo Date: Wed, 25 Mar 2020 16:22:23 -0500 Subject: [PATCH 01/12] DEV-8345 fix index and merge erics PR --- composer.json | 2 +- src/lti/LTI_Message_Launch.php | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 804cdc3b..9efabab0 100644 --- a/composer.json +++ b/composer.json @@ -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": { diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index 5dd9b6f1..77053df1 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -191,7 +191,11 @@ private function get_public_key() { foreach ($public_key_set['keys'] as $key) { if ($key['kid'] == $this->jwt['header']['kid']) { try { - return openssl_pkey_get_details(JWK::parseKey($key)); + return openssl_pkey_get_details( + JWK::parseKeySet([ + 'keys' => [$key] + ])[$key['kid']] + ); } catch(\Exception $e) { return false; } @@ -265,6 +269,10 @@ private function validate_registration() { } private function validate_jwt_signature() { + if (!isset($this->jwt['header']['kid'])) { + throw new LTI_Exception("No KID specified in the JWT Header"); + } + // Fetch public key. $public_key = $this->get_public_key(); @@ -340,4 +348,4 @@ private function validate_message() { } } -?> \ No newline at end of file +?> From 0af27f1db211c1bc9486ee68ae3bd77a31b2fea0 Mon Sep 17 00:00:00 2001 From: Davo Date: Wed, 25 Mar 2020 16:33:15 -0500 Subject: [PATCH 02/12] DEV-8345 catch missing deployment id --- src/lti/LTI_Message_Launch.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index 77053df1..e7092559 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -289,6 +289,10 @@ private function validate_jwt_signature() { } private function validate_deployment() { + if (!isset($this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/deployment_id'])) { + throw new LTI_Exception("No deployment ID was specified", 1); + } + // Find deployment. $deployment = $this->db->find_deployment($this->jwt['body']['iss'], $this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/deployment_id']); From eebc53a2afcbdadc2d8d6e50cdca594c663dc510 Mon Sep 17 00:00:00 2001 From: Davo Date: Wed, 25 Mar 2020 16:47:41 -0500 Subject: [PATCH 03/12] DEV-8345 remove unnecessary closing tags --- src/lti/Cache.php | 1 - src/lti/Cookie.php | 1 - src/lti/Database.php | 1 - src/lti/LTI_Assignments_Grades_Service.php | 1 - src/lti/LTI_Deep_Link.php | 1 - src/lti/LTI_Deep_Link_Resource.php | 2 +- src/lti/LTI_Deployment.php | 1 - src/lti/LTI_Exception.php | 1 - src/lti/LTI_Grade.php | 1 - src/lti/LTI_Lineitem.php | 1 - src/lti/LTI_Message_Launch.php | 2 +- src/lti/LTI_Names_Roles_Provisioning_Service.php | 1 - src/lti/LTI_Registration.php | 1 - src/lti/LTI_Service_Connector.php | 1 - src/lti/Message_Validator.php | 1 - src/lti/OIDC_Exception.php | 1 - src/lti/Redirect.php | 2 -- src/lti/lti.php | 1 - src/lti/message_validators/deep_link_message_validator.php | 1 - src/lti/message_validators/resource_message_validator.php | 1 - 20 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/lti/Cache.php b/src/lti/Cache.php index 0d865711..691d2743 100644 --- a/src/lti/Cache.php +++ b/src/lti/Cache.php @@ -43,4 +43,3 @@ private function save_cache() { file_put_contents(sys_get_temp_dir() . '/lti_cache.txt', json_encode($this->cache)); } } -?> \ No newline at end of file diff --git a/src/lti/Cookie.php b/src/lti/Cookie.php index e18700b6..815a860a 100644 --- a/src/lti/Cookie.php +++ b/src/lti/Cookie.php @@ -31,4 +31,3 @@ public function set_cookie($name, $value, $exp = 3600, $options = []) { return $this; } } -?> diff --git a/src/lti/Database.php b/src/lti/Database.php index 945afd67..d002fef8 100644 --- a/src/lti/Database.php +++ b/src/lti/Database.php @@ -6,4 +6,3 @@ public function find_registration_by_issuer($iss); public function find_deployment($iss, $deployment_id); } -?> \ No newline at end of file diff --git a/src/lti/LTI_Assignments_Grades_Service.php b/src/lti/LTI_Assignments_Grades_Service.php index ffd1cde0..b3393f0d 100644 --- a/src/lti/LTI_Assignments_Grades_Service.php +++ b/src/lti/LTI_Assignments_Grades_Service.php @@ -88,4 +88,3 @@ public function get_grades(LTI_Lineitem $lineitem) { return $scores['body']; } } -?> \ No newline at end of file diff --git a/src/lti/LTI_Deep_Link.php b/src/lti/LTI_Deep_Link.php index c87cb0da..52bd053c 100644 --- a/src/lti/LTI_Deep_Link.php +++ b/src/lti/LTI_Deep_Link.php @@ -43,4 +43,3 @@ public function output_response_form($resources) { \ No newline at end of file diff --git a/src/lti/LTI_Deep_Link_Resource.php b/src/lti/LTI_Deep_Link_Resource.php index 8abeadd6..7b1d97ce 100644 --- a/src/lti/LTI_Deep_Link_Resource.php +++ b/src/lti/LTI_Deep_Link_Resource.php @@ -87,4 +87,4 @@ public function to_array() { return $resource; } } -?> + diff --git a/src/lti/LTI_Deployment.php b/src/lti/LTI_Deployment.php index ad502055..2b823831 100644 --- a/src/lti/LTI_Deployment.php +++ b/src/lti/LTI_Deployment.php @@ -20,4 +20,3 @@ public function set_deployment_id($deployment_id) { } -?> \ No newline at end of file diff --git a/src/lti/LTI_Exception.php b/src/lti/LTI_Exception.php index b54bf7d3..8cd9f27e 100644 --- a/src/lti/LTI_Exception.php +++ b/src/lti/LTI_Exception.php @@ -4,4 +4,3 @@ class LTI_Exception extends \Exception { } -?> \ No newline at end of file diff --git a/src/lti/LTI_Grade.php b/src/lti/LTI_Grade.php index 75e7ab2a..515164f8 100644 --- a/src/lti/LTI_Grade.php +++ b/src/lti/LTI_Grade.php @@ -81,4 +81,3 @@ public function __toString() { ])); } } -?> \ No newline at end of file diff --git a/src/lti/LTI_Lineitem.php b/src/lti/LTI_Lineitem.php index ba8e20a7..3b01269b 100644 --- a/src/lti/LTI_Lineitem.php +++ b/src/lti/LTI_Lineitem.php @@ -105,4 +105,3 @@ public function __toString() { ])); } } -?> \ No newline at end of file diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index e7092559..5640f051 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -352,4 +352,4 @@ private function validate_message() { } } -?> + diff --git a/src/lti/LTI_Names_Roles_Provisioning_Service.php b/src/lti/LTI_Names_Roles_Provisioning_Service.php index 993810a6..bca5489c 100644 --- a/src/lti/LTI_Names_Roles_Provisioning_Service.php +++ b/src/lti/LTI_Names_Roles_Provisioning_Service.php @@ -41,4 +41,3 @@ public function get_members() { } } -?> \ No newline at end of file diff --git a/src/lti/LTI_Registration.php b/src/lti/LTI_Registration.php index 7438253c..3a5bbac2 100644 --- a/src/lti/LTI_Registration.php +++ b/src/lti/LTI_Registration.php @@ -90,4 +90,3 @@ public function set_kid($kid) { } -?> \ No newline at end of file diff --git a/src/lti/LTI_Service_Connector.php b/src/lti/LTI_Service_Connector.php index 1c8d9115..93629414 100644 --- a/src/lti/LTI_Service_Connector.php +++ b/src/lti/LTI_Service_Connector.php @@ -87,4 +87,3 @@ public function make_service_request($scopes, $method, $url, $body = null, $cont ]; } } -?> \ No newline at end of file diff --git a/src/lti/Message_Validator.php b/src/lti/Message_Validator.php index d12be20b..6ef79e46 100644 --- a/src/lti/Message_Validator.php +++ b/src/lti/Message_Validator.php @@ -5,4 +5,3 @@ interface Message_Validator { public function validate($jwt_body); public function can_validate($jwt_body); } -?> \ No newline at end of file diff --git a/src/lti/OIDC_Exception.php b/src/lti/OIDC_Exception.php index d492f4d2..9efcce64 100644 --- a/src/lti/OIDC_Exception.php +++ b/src/lti/OIDC_Exception.php @@ -4,4 +4,3 @@ class OIDC_Exception extends \Exception { } -?> \ No newline at end of file diff --git a/src/lti/Redirect.php b/src/lti/Redirect.php index 647e8f44..a5595c80 100644 --- a/src/lti/Redirect.php +++ b/src/lti/Redirect.php @@ -79,5 +79,3 @@ public function do_js_redirect() { } } - -?> \ No newline at end of file diff --git a/src/lti/lti.php b/src/lti/lti.php index 67d9a04c..5a5c2181 100644 --- a/src/lti/lti.php +++ b/src/lti/lti.php @@ -5,4 +5,3 @@ } define("TOOL_HOST", ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?: $_SERVER['REQUEST_SCHEME']) . '://' . $_SERVER['HTTP_HOST']); Firebase\JWT\JWT::$leeway = 5; -?> \ No newline at end of file diff --git a/src/lti/message_validators/deep_link_message_validator.php b/src/lti/message_validators/deep_link_message_validator.php index eefb746a..dd738b71 100644 --- a/src/lti/message_validators/deep_link_message_validator.php +++ b/src/lti/message_validators/deep_link_message_validator.php @@ -33,4 +33,3 @@ public function validate($jwt_body) { return true; } } -?> \ No newline at end of file diff --git a/src/lti/message_validators/resource_message_validator.php b/src/lti/message_validators/resource_message_validator.php index 22521167..e6717a9e 100644 --- a/src/lti/message_validators/resource_message_validator.php +++ b/src/lti/message_validators/resource_message_validator.php @@ -23,4 +23,3 @@ public function validate($jwt_body) { return true; } } -?> \ No newline at end of file From 328c4e736fec96a821d46daa91bfa4f8fae88cb0 Mon Sep 17 00:00:00 2001 From: Davo Date: Wed, 25 Mar 2020 16:57:58 -0500 Subject: [PATCH 04/12] DEV-8345 make cookie and cache interfaces as described --- src/lti/Cache.php | 46 ++++------------------------------ src/lti/Cookie.php | 32 +++-------------------- src/lti/ImsCache.php | 45 +++++++++++++++++++++++++++++++++ src/lti/ImsCookie.php | 33 ++++++++++++++++++++++++ src/lti/LTI_Message_Launch.php | 4 +-- src/lti/LTI_OIDC_Login.php | 6 ++--- src/lti/Redirect.php | 2 +- 7 files changed, 92 insertions(+), 76 deletions(-) create mode 100644 src/lti/ImsCache.php create mode 100644 src/lti/ImsCookie.php diff --git a/src/lti/Cache.php b/src/lti/Cache.php index 691d2743..f8c13c4b 100644 --- a/src/lti/Cache.php +++ b/src/lti/Cache.php @@ -1,45 +1,9 @@ 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); } diff --git a/src/lti/Cookie.php b/src/lti/Cookie.php index 815a860a..1d588fec 100644 --- a/src/lti/Cookie.php +++ b/src/lti/Cookie.php @@ -1,33 +1,7 @@ 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 = []); } diff --git a/src/lti/ImsCache.php b/src/lti/ImsCache.php new file mode 100644 index 00000000..b52f71f5 --- /dev/null +++ b/src/lti/ImsCache.php @@ -0,0 +1,45 @@ +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)); + } +} diff --git a/src/lti/ImsCookie.php b/src/lti/ImsCookie.php new file mode 100644 index 00000000..ee1feb35 --- /dev/null +++ b/src/lti/ImsCookie.php @@ -0,0 +1,33 @@ + 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; + } +} diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index 5640f051..da84015e 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -29,12 +29,12 @@ function __construct(Database $database, Cache $cache = null, Cookie $cookie = n $this->launch_id = uniqid("lti1p3_launch_", true); if ($cache === null) { - $cache = new Cache(); + $cache = new ImsCache(); } $this->cache = $cache; if ($cookie === null) { - $cookie = new Cookie(); + $cookie = new ImsCookie(); } $this->cookie = $cookie; } diff --git a/src/lti/LTI_OIDC_Login.php b/src/lti/LTI_OIDC_Login.php index 2c135c09..4886e61b 100644 --- a/src/lti/LTI_OIDC_Login.php +++ b/src/lti/LTI_OIDC_Login.php @@ -17,12 +17,12 @@ class LTI_OIDC_Login { function __construct(Database $database, Cache $cache = null, Cookie $cookie = null) { $this->db = $database; if ($cache === null) { - $cache = new Cache(); + $cache = new ImsCache(); } $this->cache = $cache; if ($cookie === null) { - $cookie = new Cookie(); + $cookie = new ImsCookie(); } $this->cookie = $cookie; } @@ -117,4 +117,4 @@ protected function validate_oidc_login($request) { // Return Registration. return $registration; } -} \ No newline at end of file +} diff --git a/src/lti/Redirect.php b/src/lti/Redirect.php index a5595c80..20ca2e2b 100644 --- a/src/lti/Redirect.php +++ b/src/lti/Redirect.php @@ -19,7 +19,7 @@ public function do_redirect() { public function do_hybrid_redirect(Cookie $cookie = null) { if ($cookie == null) { - $cookie = new Cookie(); + $cookie = new ImsCookie(); } if (!empty($cookie->get_cookie(self::$CAN_302_COOKIE))) { return $this->do_redirect(); From 65eba9211c57dc83e7b1faf5faa9b9f62acb0684 Mon Sep 17 00:00:00 2001 From: Davo Date: Thu, 26 Mar 2020 12:03:03 -0500 Subject: [PATCH 05/12] DEV-8345 use firebase exception --- src/lti/LTI_Message_Launch.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index da84015e..776c72d6 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -3,6 +3,7 @@ use Firebase\JWT\JWK; use Firebase\JWT\JWT; +use Firebase\JWT\ExpiredException; JWT::$leeway = 5; @@ -279,7 +280,7 @@ private function validate_jwt_signature() { // Validate JWT signature try { JWT::decode($this->request['id_token'], $public_key['key'], array('RS256')); - } catch(\Exception $e) { + } catch(ExpiredException $e) { var_dump($e); // Error validating signature. throw new LTI_Exception("Invalid signature on id_token", 1); From fd44a2254da3e507e8cfbce8d0df960cb1be18cb Mon Sep 17 00:00:00 2001 From: Davo Date: Thu, 26 Mar 2020 12:05:03 -0500 Subject: [PATCH 06/12] DEV-8345 dont var_dump --- src/lti/LTI_Message_Launch.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index 776c72d6..f971c328 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -281,7 +281,6 @@ private function validate_jwt_signature() { try { JWT::decode($this->request['id_token'], $public_key['key'], array('RS256')); } catch(ExpiredException $e) { - var_dump($e); // Error validating signature. throw new LTI_Exception("Invalid signature on id_token", 1); } From ea60aed2c1ac05449c41e749dc9cb29d164d48b0 Mon Sep 17 00:00:00 2001 From: Davo Date: Thu, 26 Mar 2020 12:30:14 -0500 Subject: [PATCH 07/12] DEV-8345 add consts --- src/lti/LTI_Constants.php | 71 +++++++++++++++++++ src/lti/LTI_Deep_Link.php | 6 +- src/lti/LTI_Message_Launch.php | 12 ++-- .../deep_link_message_validator.php | 6 +- .../resource_message_validator.php | 8 +-- 5 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 src/lti/LTI_Constants.php diff --git a/src/lti/LTI_Constants.php b/src/lti/LTI_Constants.php new file mode 100644 index 00000000..14bade3c --- /dev/null +++ b/src/lti/LTI_Constants.php @@ -0,0 +1,71 @@ + 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", + LTI_Constants::DEPLOYMENT_ID => $this->deployment_id, + LTI_Constants::MESSAGE_TYPE => "LtiDeepLinkingResponse", + LTI_Constants::VERSION => LTI_Constants::V1_3, "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'], ]; diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index f971c328..84ee4599 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -137,7 +137,7 @@ public function get_ags() { public function get_deep_link() { return new LTI_Deep_Link( $this->registration, - $this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/deployment_id'], + $this->jwt['body'][LTI_Constants::DEPLOYMENT_ID], $this->jwt['body']['https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings']); } @@ -147,7 +147,7 @@ public function get_deep_link() { * @return boolean Returns true if the current launch is a deep linking launch. */ public function is_deep_link_launch() { - return $this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/message_type'] === 'LtiDeepLinkingRequest'; + return $this->jwt['body'][LTI_Constants::MESSAGE_TYPE] === 'LtiDeepLinkingRequest'; } /** @@ -156,7 +156,7 @@ public function is_deep_link_launch() { * @return boolean Returns true if the current launch is a resource launch. */ public function is_resource_launch() { - return $this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/message_type'] === 'LtiResourceLinkRequest'; + return $this->jwt['body'][LTI_Constants::MESSAGE_TYPE] === 'LtiResourceLinkRequest'; } /** @@ -289,12 +289,12 @@ private function validate_jwt_signature() { } private function validate_deployment() { - if (!isset($this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/deployment_id'])) { + if (!isset($this->jwt['body'][LTI_Constants::DEPLOYMENT_ID])) { throw new LTI_Exception("No deployment ID was specified", 1); } // Find deployment. - $deployment = $this->db->find_deployment($this->jwt['body']['iss'], $this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/deployment_id']); + $deployment = $this->db->find_deployment($this->jwt['body']['iss'], $this->jwt['body'][LTI_Constants::DEPLOYMENT_ID]); if (empty($deployment)) { // deployment not recognized. @@ -305,7 +305,7 @@ private function validate_deployment() { } private function validate_message() { - if (empty($this->jwt['body']['https://purl.imsglobal.org/spec/lti/claim/message_type'])) { + if (empty($this->jwt['body'][LTI_Constants::MESSAGE_TYPE])) { // Unable to identify message type. throw new LTI_Exception("Invalid message type", 1); } diff --git a/src/lti/message_validators/deep_link_message_validator.php b/src/lti/message_validators/deep_link_message_validator.php index dd738b71..af821af8 100644 --- a/src/lti/message_validators/deep_link_message_validator.php +++ b/src/lti/message_validators/deep_link_message_validator.php @@ -3,17 +3,17 @@ class Deep_Link_Message_Validator implements Message_Validator { public function can_validate($jwt_body) { - return $jwt_body['https://purl.imsglobal.org/spec/lti/claim/message_type'] === 'LtiDeepLinkingRequest'; + return $jwt_body[LTI_Constants::MESSAGE_TYPE] === 'LtiDeepLinkingRequest'; } public function validate($jwt_body) { if (empty($jwt_body['sub'])) { throw new LTI_Exception('Must have a user (sub)'); } - if ($jwt_body['https://purl.imsglobal.org/spec/lti/claim/version'] !== '1.3.0') { + if ($jwt_body[LTI_Constants::VERSION] !== LTI_Constants::V1_3) { throw new LTI_Exception('Incorrect version, expected 1.3.0'); } - if (!isset($jwt_body['https://purl.imsglobal.org/spec/lti/claim/roles'])) { + if (!isset($jwt_body[LTI_Constants::ROLES])) { throw new LTI_Exception('Missing Roles Claim'); } if (empty($jwt_body['https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings'])) { diff --git a/src/lti/message_validators/resource_message_validator.php b/src/lti/message_validators/resource_message_validator.php index e6717a9e..d9b13db6 100644 --- a/src/lti/message_validators/resource_message_validator.php +++ b/src/lti/message_validators/resource_message_validator.php @@ -3,20 +3,20 @@ class Resource_Message_Validator implements Message_Validator { public function can_validate($jwt_body) { - return $jwt_body['https://purl.imsglobal.org/spec/lti/claim/message_type'] === 'LtiResourceLinkRequest'; + return $jwt_body[LTI_Constants::MESSAGE_TYPE] === 'LtiResourceLinkRequest'; } public function validate($jwt_body) { if (empty($jwt_body['sub'])) { throw new LTI_Exception('Must have a user (sub)'); } - if ($jwt_body['https://purl.imsglobal.org/spec/lti/claim/version'] !== '1.3.0') { + if ($jwt_body[LTI_Constants::VERSION] !== LTI_Constants::V1_3) { throw new LTI_Exception('Incorrect version, expected 1.3.0'); } - if (!isset($jwt_body['https://purl.imsglobal.org/spec/lti/claim/roles'])) { + if (!isset($jwt_body[LTI_Constants::ROLES])) { throw new LTI_Exception('Missing Roles Claim'); } - if (empty($jwt_body['https://purl.imsglobal.org/spec/lti/claim/resource_link']['id'])) { + if (empty($jwt_body[LTI_Constants::RESOURCE_LINK]['id'])) { throw new LTI_Exception('Missing Resource Link Id'); } From 61d75e58fddf98dd24a84b432b9e3868596d01f0 Mon Sep 17 00:00:00 2001 From: Davo Date: Thu, 26 Mar 2020 12:39:44 -0500 Subject: [PATCH 08/12] DEV-8345 remove more magic strings --- src/lti/LTI_Assignments_Grades_Service.php | 4 ++-- src/lti/LTI_Constants.php | 8 +++++++- src/lti/LTI_Deep_Link.php | 4 ++-- src/lti/LTI_Message_Launch.php | 10 +++++----- src/lti/LTI_Names_Roles_Provisioning_Service.php | 2 +- .../message_validators/deep_link_message_validator.php | 4 ++-- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/lti/LTI_Assignments_Grades_Service.php b/src/lti/LTI_Assignments_Grades_Service.php index b3393f0d..816c8757 100644 --- a/src/lti/LTI_Assignments_Grades_Service.php +++ b/src/lti/LTI_Assignments_Grades_Service.php @@ -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 = ''; @@ -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( diff --git a/src/lti/LTI_Constants.php b/src/lti/LTI_Constants.php index 14bade3c..e7ba3477 100644 --- a/src/lti/LTI_Constants.php +++ b/src/lti/LTI_Constants.php @@ -22,8 +22,14 @@ class LTI_Constants const LIS = 'https://purl.imsglobal.org/spec/lti/claim/lis'; const CUSTOM = 'https://purl.imsglobal.org/spec/lti/claim/custom'; + // LTI DL + const DL_CONTENT_ITEMS = 'https://purl.imsglobal.org/spec/lti-dl/claim/content_items'; + const DL_DATA = 'https://purl.imsglobal.org/spec/lti-dl/claim/data'; + const DL_DEEP_LINK_SETTINGS = 'https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings'; + // LTI NRPS - const NRPS = 'https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice'; + const NRPS_NAMESROLESPROVISIONINGSERVICE = 'https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice'; + const NRPS_CONTEXT_MEMBERSHIP_READ_ONLY = 'https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly'; // LTI AGS const AGS_ENDPOINT = 'https://purl.imsglobal.org/spec/lti-ags/claim/endpoint'; diff --git a/src/lti/LTI_Deep_Link.php b/src/lti/LTI_Deep_Link.php index 9d123bc1..69362d09 100644 --- a/src/lti/LTI_Deep_Link.php +++ b/src/lti/LTI_Deep_Link.php @@ -24,8 +24,8 @@ public function get_response_jwt($resources) { LTI_Constants::DEPLOYMENT_ID => $this->deployment_id, LTI_Constants::MESSAGE_TYPE => "LtiDeepLinkingResponse", LTI_Constants::VERSION => LTI_Constants::V1_3, - "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::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()); } diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index 84ee4599..1f7963b4 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -95,7 +95,7 @@ public function validate(array $request = null) { * @return boolean Returns a boolean indicating the availability of names and roles. */ public function has_nrps() { - return !empty($this->jwt['body']['https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice']['context_memberships_url']); + return !empty($this->jwt['body'][LTI_Constants::NRPS_NAMESROLESPROVISIONINGSERVICE]['context_memberships_url']); } /** @@ -106,7 +106,7 @@ public function has_nrps() { public function get_nrps() { return new LTI_Names_Roles_Provisioning_Service( new LTI_Service_Connector($this->registration), - $this->jwt['body']['https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice']); + $this->jwt['body'][LTI_Constants::NRPS_NAMESROLESPROVISIONINGSERVICE]); } /** @@ -115,7 +115,7 @@ public function get_nrps() { * @return boolean Returns a boolean indicating the availability of assignments and grades. */ public function has_ags() { - return !empty($this->jwt['body']['https://purl.imsglobal.org/spec/lti-ags/claim/endpoint']); + return !empty($this->jwt['body'][LTI_Constants::AGS_ENDPOINT]); } /** @@ -126,7 +126,7 @@ public function has_ags() { public function get_ags() { return new LTI_Assignments_Grades_Service( new LTI_Service_Connector($this->registration), - $this->jwt['body']['https://purl.imsglobal.org/spec/lti-ags/claim/endpoint']); + $this->jwt['body'][LTI_Constants::AGS_ENDPOINT]); } /** @@ -138,7 +138,7 @@ public function get_deep_link() { return new LTI_Deep_Link( $this->registration, $this->jwt['body'][LTI_Constants::DEPLOYMENT_ID], - $this->jwt['body']['https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings']); + $this->jwt['body'][LTI_Constants::DL_DEEP_LINK_SETTINGS]); } /** diff --git a/src/lti/LTI_Names_Roles_Provisioning_Service.php b/src/lti/LTI_Names_Roles_Provisioning_Service.php index bca5489c..2801da71 100644 --- a/src/lti/LTI_Names_Roles_Provisioning_Service.php +++ b/src/lti/LTI_Names_Roles_Provisioning_Service.php @@ -19,7 +19,7 @@ public function get_members() { while ($next_page) { $page = $this->service_connector->make_service_request( - ['https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly'], + [LTI_Constants::NRPS_CONTEXT_MEMBERSHIP_READ_ONLY], 'GET', $next_page, null, diff --git a/src/lti/message_validators/deep_link_message_validator.php b/src/lti/message_validators/deep_link_message_validator.php index af821af8..2425b1ea 100644 --- a/src/lti/message_validators/deep_link_message_validator.php +++ b/src/lti/message_validators/deep_link_message_validator.php @@ -16,10 +16,10 @@ public function validate($jwt_body) { if (!isset($jwt_body[LTI_Constants::ROLES])) { throw new LTI_Exception('Missing Roles Claim'); } - if (empty($jwt_body['https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings'])) { + if (empty($jwt_body[LTI_Constants::DL_DEEP_LINK_SETTINGS])) { throw new LTI_Exception('Missing Deep Linking Settings'); } - $deep_link_settings = $jwt_body['https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings']; + $deep_link_settings = $jwt_body[LTI_Constants::DL_DEEP_LINK_SETTINGS]; if (empty($deep_link_settings['deep_link_return_url'])) { throw new LTI_Exception('Missing Deep Linking Return URL'); } From 4356b4201312a6239318a3c5b0ff5059ef4f5dd6 Mon Sep 17 00:00:00 2001 From: Davo Date: Thu, 26 Mar 2020 12:42:17 -0500 Subject: [PATCH 09/12] DEV-8345 add cookie const --- src/lti/LTI_Constants.php | 112 ++++++++++++++++++------------------- src/lti/LTI_OIDC_Login.php | 4 +- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/lti/LTI_Constants.php b/src/lti/LTI_Constants.php index e7ba3477..a6ffa26c 100644 --- a/src/lti/LTI_Constants.php +++ b/src/lti/LTI_Constants.php @@ -4,74 +4,74 @@ class LTI_Constants { - CONST V1_3 = '1.3.0'; + public const V1_3 = '1.3.0'; // Required message claims - const MESSAGE_TYPE = 'https://purl.imsglobal.org/spec/lti/claim/message_type'; - const VERSION = 'https://purl.imsglobal.org/spec/lti/claim/version'; - const DEPLOYMENT_ID = 'https://purl.imsglobal.org/spec/lti/claim/deployment_id'; - const TARGET_LINK_URI = 'https://purl.imsglobal.org/spec/lti/claim/target_link_uri'; - const RESOURCE_LINK = 'https://purl.imsglobal.org/spec/lti/claim/resource_link'; - const ROLES = 'https://purl.imsglobal.org/spec/lti/claim/roles'; + 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 - const CONTEXT = 'https://purl.imsglobal.org/spec/lti/claim/context'; - const TOOL_PLATFORM = 'https://purl.imsglobal.org/spec/lti/claim/tool_platform'; - const ROLE_SCOPE_MENTOR = 'https://purlimsglobal.org/spec/lti/claim/role_scope_mentor'; - const LAUNCH_PRESENTATION = 'https://purl.imsglobal.org/spec/lti/claim/launch_presentation'; - const LIS = 'https://purl.imsglobal.org/spec/lti/claim/lis'; - const CUSTOM = 'https://purl.imsglobal.org/spec/lti/claim/custom'; + 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 - const DL_CONTENT_ITEMS = 'https://purl.imsglobal.org/spec/lti-dl/claim/content_items'; - const DL_DATA = 'https://purl.imsglobal.org/spec/lti-dl/claim/data'; - const DL_DEEP_LINK_SETTINGS = 'https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings'; + 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 - const NRPS_NAMESROLESPROVISIONINGSERVICE = 'https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice'; - const NRPS_CONTEXT_MEMBERSHIP_READ_ONLY = 'https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly'; + public const NRPS_NAMESROLESPROVISIONINGSERVICE = 'https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice'; + public const NRPS_CONTEXT_MEMBERSHIP_READ_ONLY = 'https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly'; // LTI AGS - const AGS_ENDPOINT = 'https://purl.imsglobal.org/spec/lti-ags/claim/endpoint'; - const AGS_LINEITEM = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem'; - const AGS_LINEITEM_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly'; - const AGS_RESULT_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly'; - const AGS_SCORE = 'https://purl.imsglobal.org/spec/lti-ags/scope/score'; + public const AGS_ENDPOINT = 'https://purl.imsglobal.org/spec/lti-ags/claim/endpoint'; + public const AGS_LINEITEM = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem'; + public const AGS_LINEITEM_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly'; + public const AGS_RESULT_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly'; + public const AGS_SCORE = 'https://purl.imsglobal.org/spec/lti-ags/scope/score'; // User Vocab - const SYSTEM_ADMINISTRATOR = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#Administrator'; - const SYSTEM_NONE = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#None'; - const SYSTEM_ACCOUNTADMIN = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#AccountAdmin'; - const SYSTEM_CREATOR = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#Creator'; - const SYSTEM_SYSADMIN = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#SysAdmin'; - const SYSTEM_SYSSUPPORT = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#SysSupport'; - const SYSTEM_USER = 'http://purl.imsglobal.org/vocab/lis/v2/system/person#User'; - const INSTITUTION_ADMINISTRATOR = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator'; - const INSTITUTION_FACULTY = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Faculty'; - const INSTITUTION_GUEST = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Guest'; - const INSTITUTION_NONE = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#None'; - const INSTITUTION_OTHER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Other'; - const INSTITUTION_STAFF = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Staff'; - const INSTITUTION_STUDENT = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Student'; - const INSTITUTION_ALUMNI = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Alumni'; - const INSTITUTION_INSTRUCTOR = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Instructor'; - const INSTITUTION_LEARNER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Learner'; - const INSTITUTION_MEMBER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Member'; - const INSTITUTION_MENTOR = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Mentor'; - const INSTITUTION_OBSERVER = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#Observer'; - const INSTITUTION_PROSPECTIVESTUDENT = 'http://purl.imsglobal.org/vocab/lis/v2/institution/person#ProspectiveStudent'; - const MEMBERSHIP_ADMINISTRATOR = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Administrator'; - const MEMBERSHIP_CONTENTDEVELOPER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#ContentDeveloper'; - const MEMBERSHIP_INSTRUCTOR = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor'; - const MEMBERSHIP_LEARNER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'; - const MEMBERSHIP_MENTOR = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Mentor'; - const MEMBERSHIP_MANAGER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Manager'; - const MEMBERSHIP_MEMBER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Member'; - const MEMBERSHIP_OFFICER = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Officer'; + 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 - const COURSE_TEMPLATE = 'http://purl.imsglobal.org/vocab/lis/v2/course#CourseTemplate'; - const COURSE_OFFERING = 'http://purl.imsglobal.org/vocab/lis/v2/course#CourseOffering'; - const COURSE_SECTION = 'http://purl.imsglobal.org/vocab/lis/v2/course#CourseSection'; - const COURSE_GROUP = 'http://purl.imsglobal.org/vocab/lis/v2/course#Group'; + 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'; } diff --git a/src/lti/LTI_OIDC_Login.php b/src/lti/LTI_OIDC_Login.php index 4886e61b..4c43aa66 100644 --- a/src/lti/LTI_OIDC_Login.php +++ b/src/lti/LTI_OIDC_Login.php @@ -3,6 +3,8 @@ class LTI_OIDC_Login { + public const COOKIE_PREFIX = 'lti1p3_'; + private $db; private $cache; private $cookie; @@ -62,7 +64,7 @@ public function do_oidc_login_redirect($launch_url, array $request = null) { // Generate State. // Set cookie (short lived) $state = str_replace('.', '_', uniqid('state-', true)); - $this->cookie->set_cookie("lti1p3_$state", $state, 60); + $this->cookie->set_cookie(static::COOKIE_PREFIX.$state, $state, 60); // Generate Nonce. $nonce = uniqid('nonce-', true); From 7fd9ffa0b680ae21251ad83d93b93d05317327ee Mon Sep 17 00:00:00 2001 From: Davo Date: Thu, 26 Mar 2020 14:43:19 -0500 Subject: [PATCH 10/12] DEV-8345 add missing version exception --- src/lti/message_validators/resource_message_validator.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lti/message_validators/resource_message_validator.php b/src/lti/message_validators/resource_message_validator.php index d9b13db6..65559afc 100644 --- a/src/lti/message_validators/resource_message_validator.php +++ b/src/lti/message_validators/resource_message_validator.php @@ -10,6 +10,9 @@ public function validate($jwt_body) { if (empty($jwt_body['sub'])) { throw new LTI_Exception('Must have a user (sub)'); } + if (!isset($jwt_body[LTI_Constants::VERSION])) { + throw new LTI_Exception('Missing LTI Version'); + } if ($jwt_body[LTI_Constants::VERSION] !== LTI_Constants::V1_3) { throw new LTI_Exception('Incorrect version, expected 1.3.0'); } From bdeafef7ff6b9de9ce07aa9a7409e3cdc9269e20 Mon Sep 17 00:00:00 2001 From: Eric Tendian Date: Tue, 21 Apr 2020 13:07:37 -0500 Subject: [PATCH 11/12] Throw exception if nonce is missing This will prevent an error occurring when doing LTI 1.3 certification on a bad launch test case. --- src/lti/LTI_Message_Launch.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lti/LTI_Message_Launch.php b/src/lti/LTI_Message_Launch.php index 1f7963b4..846ecdd9 100644 --- a/src/lti/LTI_Message_Launch.php +++ b/src/lti/LTI_Message_Launch.php @@ -245,6 +245,9 @@ private function validate_jwt_format() { } private function validate_nonce() { + if (!isset($this->jwt['body']['nonce'])) { + throw new LTI_Exception("Missing Nonce"); + } if (!$this->cache->check_nonce($this->jwt['body']['nonce'])) { //throw new LTI_Exception("Invalid Nonce"); } From 35e10f699aacfe0e8c00040017d354b31089e182 Mon Sep 17 00:00:00 2001 From: Davo Date: Mon, 8 Jun 2020 10:22:35 -0500 Subject: [PATCH 12/12] rename constants --- src/lti/LTI_Constants.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lti/LTI_Constants.php b/src/lti/LTI_Constants.php index a6ffa26c..80703cdf 100644 --- a/src/lti/LTI_Constants.php +++ b/src/lti/LTI_Constants.php @@ -28,15 +28,15 @@ class LTI_Constants public const DL_DEEP_LINK_SETTINGS = 'https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings'; // LTI NRPS - public const NRPS_NAMESROLESPROVISIONINGSERVICE = 'https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice'; - public const NRPS_CONTEXT_MEMBERSHIP_READ_ONLY = 'https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly'; + 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_ENDPOINT = 'https://purl.imsglobal.org/spec/lti-ags/claim/endpoint'; - public const AGS_LINEITEM = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem'; - public const AGS_LINEITEM_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly'; - public const AGS_RESULT_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly'; - public const AGS_SCORE = 'https://purl.imsglobal.org/spec/lti-ags/scope/score'; + 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';