36    public $ltiVersion = 
null;
 
   50    public $secret = 
null;
 
   57    public $signatureMethod = 
'HMAC-SHA1';
 
   64    public $encryptionMethod = 
'';
 
   71    public $dataConnector = 
null;
 
   81    public $rsaKey = 
null;
 
   88    public $requiredScopes = array();
 
  109    public $reason = 
null;
 
  116    public $details = array();
 
  123    public $warnings = array();
 
  130    public $debugMode = 
false;
 
  137    public $enabled = 
false;
 
  144    public $enableFrom = 
null;
 
  151    public $enableUntil = 
null;
 
  158    public $lastAccess = 
null;
 
  165    public $created = 
null;
 
  172    public $updated = 
null;
 
  179    protected $jwt = 
null;
 
  186    protected $rawParameters = 
null;
 
  193    protected $messageParameters = 
null;
 
  214    private $settings = 
null;
 
  221    private $settingsChanged = 
false;
 
  273        if (array_key_exists($name, $this->settings)) {
 
  274            $value = $this->settings[$name];
 
  290        $old_value = $this->getSetting($name);
 
  291        if ($value !== $old_value) {
 
  292            if (!empty($value)) {
 
  293                $this->settings[$name] = $value;
 
  295                unset($this->settings[$name]);
 
  297            $this->settingsChanged = 
true;
 
  308        return $this->settings;
 
  318        $this->settings = $settings;
 
  328        if ($this->settingsChanged) {
 
  344        return !empty($this->jwt) && $this->jwt->hasJwt();
 
  364        if (is_null($this->rawParameters)) {
 
  368        return $this->rawParameters;
 
  380        $messageClaims = 
null;
 
  381        if (!is_null($this->messageParameters)) {
 
  382            $messageParameters = $this->messageParameters;
 
  384            if (!empty($messageParameters[
'lti_message_type'])) {
 
  388                $messageType = $messageParameters[
'lti_message_type'];
 
  390            if (!empty($messageParameters[
'accept_media_types'])) {
 
  391                $mediaTypes = array_map(
'trim', explode(
',', $messageParameters[
'accept_media_types']));
 
  392                $mediaTypes = array_filter($mediaTypes);
 
  394                if (!empty($messageParameters[
'accept_types'])) {
 
  395                    $types = array_map(
'trim', explode(
',', $this->messageParameters[
'accept_types']));
 
  396                    $types = array_filter($types);
 
  397                    foreach ($mediaTypes as $mediaType) {
 
  398                        if (strpos($mediaType, 
'application/vnd.ims.lti.') === 0) {
 
  399                            unset($mediaTypes[array_search($mediaType, $mediaTypes)]);
 
  402                    $messageParameters[
'accept_media_types'] = implode(
',', $mediaTypes);
 
  404                    foreach ($mediaTypes as $mediaType) {
 
  405                        if ($mediaType === Item::LTI_LINK_MEDIA_TYPE) {
 
  406                            unset($mediaTypes[array_search(Item::LTI_LINK_MEDIA_TYPE, $mediaTypes)]);
 
  407                            $messageParameters[
'accept_media_types'] = implode(
',', $mediaTypes);
 
  408                            $types[] = Item::TYPE_LTI_LINK;
 
  409                        } elseif ($mediaType === Item::LTI_ASSIGNMENT_MEDIA_TYPE) {
 
  410                            unset($mediaTypes[array_search(Item::LTI_ASSIGNMENT_MEDIA_TYPE, $mediaTypes)]);
 
  411                            $messageParameters[
'accept_media_types'] = implode(
',', $mediaTypes);
 
  412                            $types[] = Item::TYPE_LTI_ASSIGNMENT;
 
  413                        } elseif (substr($mediaType, 0, 6) === 
'image/') {
 
  417                        } elseif ($mediaType === 
'text/html') {
 
  421                        } elseif ($mediaType === 
'*/*') {
 
  430                    $types = array_unique($types);
 
  431                    $messageParameters[
'accept_types'] = implode(
',', $types);
 
  434            if (!empty($messageParameters[
'accept_presentation_document_targets'])) {
 
  435                $documentTargets = array_map(
'trim', explode(
',', $messageParameters[
'accept_presentation_document_targets']));
 
  436                $documentTargets = array_filter($documentTargets);
 
  438                foreach ($documentTargets as $documentTarget) {
 
  439                    switch ($documentTarget) {
 
  446                            $targets[] = $documentTarget;
 
  450                $targets = array_unique($targets);
 
  451                $messageParameters[
'accept_presentation_document_targets'] = implode(
',', $targets);
 
  453            $messageClaims = array();
 
  454            if (!empty($messageParameters[
'oauth_consumer_key'])) {
 
  455                $messageClaims[
'aud'] = array($messageParameters[
'oauth_consumer_key']);
 
  457            foreach ($messageParameters as $key => $value) {
 
  465                    if (isset($mapping[
'isObject']) && $mapping[
'isObject']) {
 
  467                    } elseif (isset($mapping[
'isArray']) && $mapping[
'isArray']) {
 
  468                        $value = array_map(
'trim', explode(
',', $value));
 
  469                        $value = array_filter($value);
 
  471                    } elseif (isset($mapping[
'isBoolean']) && $mapping[
'isBoolean']) {
 
  472                        $value = (is_bool($value)) ? $value : $value === 
'true';
 
  473                    } elseif (isset($mapping[
'isInteger']) && $mapping[
'isInteger']) {
 
  474                        $value = intval($value);
 
  475                    } elseif (is_bool($value)) {
 
  476                        $value = ($value) ? 
'true' : 
'false';
 
  478                        $value = strval($value);
 
  482                    if (!empty($mapping[
'suffix'])) {
 
  483                        $claim .= 
"-{$mapping['suffix']}";
 
  486                    if (is_null($mapping[
'group'])) {
 
  487                        $claim = $mapping[
'claim'];
 
  488                    } elseif (empty($mapping[
'group'])) {
 
  489                        $claim .= $mapping[
'claim'];
 
  491                        $group = $claim . $mapping[
'group'];
 
  492                        $claim = $mapping[
'claim'];
 
  494                } elseif (substr($key, 0, 7) === 
'custom_') {
 
  496                    $claim = substr($key, 7);
 
  497                } elseif (substr($key, 0, 4) === 
'ext_') {
 
  498                    if ($key === 
'ext_d2l_username') {
 
  499                        $group = 
'http://www.brightspace.com';
 
  503                        $claim = substr($key, 4);
 
  505                } elseif (substr($key, 0, 7) === 
'lti1p1_') {
 
  507                    $claim = substr($key, 7);
 
  512                        if (!is_null($json)) {
 
  520                    if ($fullyQualified) {
 
  522                            $messageClaims = array_merge($messageClaims, self::fullyQualifyClaim($claim, $value));
 
  524                            $messageClaims = array_merge($messageClaims, self::fullyQualifyClaim(
"{$group}/{$claim}", $value));
 
  526                    } elseif (empty($group)) {
 
  527                        $messageClaims[$claim] = $value;
 
  529                        $messageClaims[$group][$claim] = $value;
 
  533            if (!empty($messageParameters[
'unmapped_claims'])) {
 
  535                foreach ($claims as $claim => $value) {
 
  536                    if ($fullyQualified) {
 
  537                        $messageClaims = array_merge($messageClaims, self::fullyQualifyClaim($claim, $value));
 
  538                    } elseif (!is_object($value)) {
 
  539                        $messageClaims[$claim] = $value;
 
  540                    } elseif (!isset($messageClaims[$claim])) {
 
  541                        $messageClaims[$claim] = $value;
 
  543                        $objVars = get_object_vars($value);
 
  544                        foreach ($objVars as $attrName => $attrValue) {
 
  545                            if (is_object($messageClaims[$claim])) {
 
  546                                $messageClaims[$claim]->{$attrName} = $attrValue;
 
  548                                $messageClaims[$claim][$attrName] = $attrValue;
 
  556        return $messageClaims;
 
  570        if (!is_array($roles)) {
 
  571            $roles = array_map(
'trim', explode(
',', $roles));
 
  572            $roles = array_filter($roles);
 
  574        $parsedRoles = array();
 
  575        foreach ($roles as $role) {
 
  577            if ((substr($role, 0, 4) !== 
'urn:') &&
 
  578                (substr($role, 0, 7) !== 
'http://') && (substr($role, 0, 8) !== 
'https://')) {
 
  579                switch ($ltiVersion) {
 
  581                        $role = str_replace(
'#', 
'/', $role);
 
  582                        $role = 
"urn:lti:role:ims/lis/{$role}";
 
  586                        $pos = strrpos($role, 
'#');
 
  587                        if ($pos === 
false) {
 
  592                        $role = 
"http://purl.imsglobal.org/vocab/lis/v2/membership{$sep}{$role}";
 
  596            $systemRoles = array(
 
  604            $institutionRoles = array(
 
  616                'ProspectiveStudent',
 
  620            switch ($ltiVersion) {
 
  622                    if (in_array(substr($role, 0, 53),
 
  623                            array(
'http://purl.imsglobal.org/vocab/lis/v2/system/person#',
 
  624                                'http://purl.imsglobal.org/vocab/lis/v2/system/person/'))) {
 
  625                        $role = 
'urn:lti:sysrole:ims/lis/' . substr($role, 53);
 
  626                    } elseif (in_array(substr($role, 0, 58),
 
  627                            array(
'http://purl.imsglobal.org/vocab/lis/v2/institution/person#',
 
  628                                'http://purl.imsglobal.org/vocab/lis/v2/institution/person/'))) {
 
  629                        $role = 
'urn:lti:instrole:ims/lis/' . substr($role, 58);
 
  630                    } elseif (substr($role, 0, 50) === 
'http://purl.imsglobal.org/vocab/lis/v2/membership#') {
 
  631                        $principalRole = substr($role, 50);
 
  632                        if (($principalRole === 
'Instructor') &&
 
  633                            (!empty(preg_grep(
'/^http:\/\/purl.imsglobal.org\/vocab\/lis\/v2\/membership\/Instructor#TeachingAssistant.*$/',
 
  635                            !empty(preg_grep(
'/^Instructor#TeachingAssistant.*$/', $roles)))) {
 
  637                        } elseif (!empty(preg_grep(
"/^http:\/\/purl.imsglobal.org\/vocab\/lis\/v2\/membership\/{$principalRole}#.*$/",
 
  639                            !empty(preg_grep(
'/^{$principalRole}#.*$/', $roles))) {
 
  642                            $role = 
"urn:lti:role:ims/lis/{$principalRole}";
 
  644                    } elseif (substr($role, 0, 50) === 
'http://purl.imsglobal.org/vocab/lis/v2/membership/') {
 
  645                        $subroles = explode(
'#', substr($role, 50));
 
  646                        if (count($subroles) === 2) {
 
  647                            if (($subroles[0] === 
'Instructor') && ($subroles[1] === 
'TeachingAssistant')) {
 
  648                                $role = 
'urn:lti:role:ims/lis/TeachingAssistant';
 
  649                            } elseif (($subroles[0] === 
'Instructor') && (substr($subroles[1], 0, 17) === 
'TeachingAssistant')) {
 
  650                                $role = 
"urn:lti:role:ims/lis/TeachingAssistant#{$subroles[1]}";
 
  652                                $role = 
"urn:lti:role:ims/lis/{$subroles[0]}/{$subroles[1]}";
 
  655                            $role = 
'urn:lti:role:ims/lis/' . substr($role, 50);
 
  657                    } elseif (in_array(substr($role, 0, 46),
 
  658                            array(
'http://purl.imsglobal.org/vocab/lis/v2/person#',
 
  659                                'http://purl.imsglobal.org/vocab/lis/v2/person/'))) {
 
  660                        if (in_array(substr($role, 46), $systemRoles)) {
 
  661                            $role = 
'urn:lti:sysrole:ims/lis/' . substr($role, 46);
 
  662                        } elseif (in_array(substr($role, 46), $institutionRoles)) {
 
  663                            $role = 
'urn:lti:instrole:ims/lis/' . substr($role, 46);
 
  665                    } elseif (strpos($role, 
'Instructor#TeachingAssistant') !== 
false) {
 
  666                        if (substr($role, -28) === 
'Instructor#TeachingAssistant') {
 
  667                            $role = str_replace(
'Instructor#', 
'', $role);
 
  669                            $role = str_replace(
'Instructor#', 
'TeachingAssistant/', $role);
 
  671                    } elseif ((substr($role, -10) === 
'Instructor') &&
 
  672                        !empty(preg_grep(
'/^http:\/\/purl.imsglobal.org\/vocab\/lis\/v2\/membership\/Instructor#TeachingAssistant.*$/',
 
  676                    $role = str_replace(
'#', 
'/', $role);
 
  680                    if (substr($role, 0, 24) === 
'urn:lti:sysrole:ims/lis/') {
 
  681                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/person';
 
  682                        $role = substr($role, 24);
 
  683                    } elseif (substr($role, 0, 25) === 
'urn:lti:instrole:ims/lis/') {
 
  684                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/person';
 
  685                        $role = substr($role, 25);
 
  686                    } elseif (substr($role, 0, 21) === 
'urn:lti:role:ims/lis/') {
 
  687                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/membership';
 
  688                        $subroles = explode(
'/', substr($role, 21));
 
  689                        if (count($subroles) === 2) {
 
  690                            if (($subroles[0] === 
'Instructor') && ($subroles[1] === 
'TeachingAssistant')) {
 
  691                                $role = 
'TeachingAssistant';
 
  692                            } elseif (($subroles[0] === 
'Instructor') && (substr($subroles[1], 0, 17) === 
'TeachingAssistant')) {
 
  693                                $role = 
"TeachingAssistant#{$subroles[1]}";
 
  695                                $role = 
"{$subroles[0]}#{$subroles[1]}";
 
  697                        } elseif ((count($subroles) === 1) && (!empty(preg_grep(
"/^http:\/\/purl.imsglobal.org\/vocab\/lis\/v2\/membership\/{$subroles[0]}#.*$/",
 
  699                            !empty(preg_grep(
'/^{$subroles[0]#.*$/', $roles)))) {
 
  702                            $role = substr($role, 21);
 
  704                    } elseif (in_array(substr($role, 0, 53),
 
  705                            array(
'http://purl.imsglobal.org/vocab/lis/v2/system/person#',
 
  706                                'http://purl.imsglobal.org/vocab/lis/v2/system/person/'))) {
 
  707                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/person';
 
  708                        $role = substr($role, 53);
 
  709                    } elseif (in_array(substr($role, 0, 58),
 
  710                            array(
'http://purl.imsglobal.org/vocab/lis/v2/institution/person#',
 
  711                                'http://purl.imsglobal.org/vocab/lis/v2/institution/person/'))) {
 
  712                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/person';
 
  713                        $role = substr($role, 58);
 
  714                    } elseif (substr($role, 0, 50) === 
'http://purl.imsglobal.org/vocab/lis/v2/membership#') {
 
  715                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/membership';
 
  716                        $principalRole = substr($role, 50);
 
  717                        $principalRole2 = str_replace(
'/', 
'\\/', $principalRole);
 
  718                        if (($principalRole === 
'Instructor') &&
 
  719                            (!empty(preg_grep(
'/^http:\/\/purl.imsglobal.org\/vocab\/lis\/v2\/membership\/Instructor#TeachingAssistant.*$/',
 
  721                            !empty(preg_grep(
'/^Instructor#TeachingAssistant.*$/', $roles)))) {
 
  723                        } elseif (!empty(preg_grep(
"/^http:\/\/purl.imsglobal.org\/vocab\/lis\/v2\/membership\/{$principalRole2}#.*$/",
 
  725                            !empty(preg_grep(
'/^{$principalRole2}#.*$/', $roles))) {
 
  728                            $role = $principalRole;
 
  730                    } elseif (substr($role, 0, 50) === 
'http://purl.imsglobal.org/vocab/lis/v2/membership/') {
 
  731                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/membership';
 
  732                        $subroles = explode(
'#', substr($role, 50));
 
  733                        if (count($subroles) === 2) {
 
  734                            if (($subroles[0] === 
'Instructor') && ($subroles[1] === 
'TeachingAssistant')) {
 
  735                                $role = 
'TeachingAssistant';
 
  736                            } elseif (($subroles[0] === 
'Instructor') && (substr($subroles[1], 0, 17) === 
'TeachingAssistant')) {
 
  737                                $role = 
"TeachingAssistant#{$subroles[1]}";
 
  739                                $role = 
"{$subroles[0]}#{$subroles[1]}";
 
  742                            $role = substr($role, 50);
 
  746                        $pos = strrpos($role, 
'/');
 
  747                        if ((strpos($role, 
'#') !== 
false) || ($pos !== 
false)) {
 
  749                            if ($pos !== 
false) {
 
  750                                $role = substr($role, 0, $pos) . 
'#' . substr($role, $pos + 1);
 
  755                        $role = 
"{$prefix}{$role}";
 
  760                    if (substr($role, 0, 24) === 
'urn:lti:sysrole:ims/lis/') {
 
  761                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/system/person';
 
  762                        $role = substr($role, 24);
 
  763                    } elseif (substr($role, 0, 25) === 
'urn:lti:instrole:ims/lis/') {
 
  764                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/institution/person';
 
  765                        $role = substr($role, 25);
 
  766                    } elseif (substr($role, 0, 21) === 
'urn:lti:role:ims/lis/') {
 
  767                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/membership';
 
  768                        $subroles = explode(
'/', substr($role, 21));
 
  769                        if (count($subroles) === 2) {
 
  770                            if ($subroles[0] === 
'TeachingAssistant') {
 
  771                                $role = 
"Instructor#{$subroles[1]}";
 
  772                                if ($addPrincipalRole) {
 
  773                                    $parsedRoles[] = 
"{$prefix}#Instructor";
 
  776                                $role = 
"{$subroles[0]}#{$subroles[1]}";
 
  777                                if ($addPrincipalRole) {
 
  778                                    $parsedRoles[] = 
"{$prefix}#{$subroles[0]}";
 
  781                        } elseif ($subroles[0] === 
'TeachingAssistant') {
 
  782                            $role = 
'Instructor#TeachingAssistant';
 
  783                            if ($addPrincipalRole) {
 
  784                                $parsedRoles[] = 
"{$prefix}#Instructor";
 
  787                            $role = substr($role, 21);
 
  789                    } elseif (substr($role, 0, 46) === 
'http://purl.imsglobal.org/vocab/lis/v2/person#') {
 
  790                        if (in_array(substr($role, 46), $systemRoles)) {
 
  791                            $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/system/person';
 
  792                        } elseif (in_array(substr($role, 46), $institutionRoles)) {
 
  793                            $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/institution/person';
 
  795                        $role = substr($role, 46);
 
  796                        $pos = strrpos($role, 
'/');
 
  797                        if ($pos !== 
false) {
 
  798                            $role = substr($role, 0, $pos - 1) . 
'#' . substr($role, $pos + 1);
 
  800                    } elseif (substr($role, 0, 50) === 
'http://purl.imsglobal.org/vocab/lis/v2/membership#') {
 
  801                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/membership';
 
  802                        if (substr($role, 50, 18) === 
'TeachingAssistant') {
 
  803                            $role = 
'Instructor#TeachingAssistant';
 
  804                            if ($addPrincipalRole) {
 
  805                                $parsedRoles[] = 
"{$prefix}#Instructor";
 
  808                            $role = substr($role, 50);
 
  810                    } elseif (substr($role, 0, 50) === 
'http://purl.imsglobal.org/vocab/lis/v2/membership/') {
 
  811                        $prefix = 
'http://purl.imsglobal.org/vocab/lis/v2/membership';
 
  812                        $subroles = explode(
'#', substr($role, 50));
 
  813                        if (count($subroles) === 2) {
 
  814                            if ($subroles[0] === 
'TeachingAssistant') {
 
  815                                $role = 
"Instructor#{subroles[1]}";
 
  816                                if ($addPrincipalRole) {
 
  817                                    $parsedRoles[] = 
"{$prefix}#Instructor";
 
  820                                $role = substr($role, 50);
 
  821                                if ($addPrincipalRole) {
 
  822                                    $parsedRoles[] = 
"{$prefix}#{$subroles[0]}";
 
  826                            $role = substr($role, 50);
 
  829                    if (!empty($prefix) && !empty($role)) {
 
  830                        $pos = strrpos($role, 
'/');
 
  831                        if ((strpos($role, 
'#') !== 
false) || ($pos !== 
false)) {
 
  833                            if ($pos !== 
false) {
 
  834                                $role = substr($role, 0, $pos) . 
'#' . substr($role, $pos + 1);
 
  839                        $role = 
"{$prefix}{$role}";
 
  844                $parsedRoles[] = $role;
 
  848        return array_unique($parsedRoles);
 
  865            $params[
'lti_version'] = $version;
 
  866            $params[
'lti_message_type'] = $type;
 
  868            $params = $this->addSignature($url, $params, 
'POST', 
'application/x-www-form-urlencoded');
 
  889    public function signMessage(&$url, $type, $version, $params, $loginHint = 
null, $ltiMessageHint = 
null)
 
  892            if (!isset($loginHint) || (strlen($loginHint) <= 0)) {
 
  893                if (isset($params[
'user_id']) && (strlen($params[
'user_id']) > 0)) {
 
  894                    $loginHint = $params[
'user_id'];
 
  896                    $loginHint = 
'Anonymous';
 
  900            $params[
'lti_version'] = $version;
 
  901            $params[
'lti_message_type'] = $type;
 
  902            $this->onInitiateLogin($url, $loginHint, $ltiMessageHint, $params);
 
  905                'iss' => $this->platformId,
 
  906                'target_link_uri' => $url,
 
  907                'login_hint' => $loginHint
 
  909            if (!is_null($ltiMessageHint)) {
 
  910                $params[
'lti_message_hint'] = $ltiMessageHint;
 
  912            if (!empty($this->clientId)) {
 
  913                $params[
'client_id'] = $this->clientId;
 
  915            if (!empty($this->deploymentId)) {
 
  916                $params[
'lti_deployment_id'] = $this->deploymentId;
 
  921            if (!empty(static::$browserStorageFrame)) {
 
  922                if (strpos($url, 
'?') === 
false) {
 
  927                $url .= 
"{$sep}lti_storage_target=" . static::$browserStorageFrame;
 
  930            $params = $this->signParameters($url, $type, $version, $params);
 
  948    public function sendMessage($url, $type, $messageParams, $target = 
'', $userId = 
null, $hint = 
null)
 
  950        $sendParams = $this->signMessage($url, $type, $this->ltiVersion, $messageParams, $userId, $hint);
 
  970            $header = $this->addSignature($url, $data, $method, $type);
 
  988        $header = $this->addSignature($service->endpoint, $data, $method, $format);
 
  991        $http = 
new HttpMessage($service->endpoint, $method, $data, $header);
 
  993        if ($http->send() && !empty($http->response)) {
 
  995            $http->ok = !is_null($http->responseJson);
 
 1008        return empty($this->signatureMethod) || (substr($this->signatureMethod, 0, 2) !== 
'RS');
 
 1024    public function addSignature($endpoint, $data, $method = 
'POST', $type = 
null, $nonce = 
'', $hash = 
null, $timestamp = 
null)
 
 1026        if ($this->useOAuth1()) {
 
 1027            return $this->addOAuth1Signature($endpoint, $data, $method, $type, $hash, $timestamp);
 
 1029            return $this->addJWTSignature($endpoint, $data, $method, $type, $nonce, $timestamp);
 
 1040        $ok = $_SERVER[
'REQUEST_METHOD'] === 
'POST';
 
 1042            $this->reason = 
'LTI messages must use HTTP POST';
 
 1043        } elseif (!empty($this->jwt) && !empty($this->jwt->hasJwt())) {
 
 1045            $context = $this->jwt->getClaim(
'https://purl.imsglobal.org/spec/lti/claim/context');
 
 1046            $resourceLink = $this->jwt->getClaim(
'https://purl.imsglobal.org/spec/lti/claim/resource_link');
 
 1047            if (is_null($this->messageParameters[
'oauth_consumer_key']) || (strlen($this->messageParameters[
'oauth_consumer_key']) <= 0)) {
 
 1048                $this->reason = 
'Missing iss claim';
 
 1049            } elseif (empty($this->jwt->getClaim(
'iat', 
''))) {
 
 1050                $this->reason = 
'Missing iat claim';
 
 1051            } elseif (empty($this->jwt->getClaim(
'exp', 
''))) {
 
 1052                $this->reason = 
'Missing exp claim';
 
 1053            } elseif (intval($this->jwt->getClaim(
'iat')) > intval($this->jwt->getClaim(
'exp'))) {
 
 1054                $this->reason = 
'iat claim must not have a value greater than exp claim';
 
 1055            } elseif (empty($this->jwt->getClaim(
'nonce', 
''))) {
 
 1056                $this->reason = 
'Missing nonce claim';
 
 1057            } elseif (!empty($context) && property_exists($context, 
'id') && (empty($context->id) || !is_string($context->id))) {
 
 1058                $this->reason = 
'Invalid value for id property in https://purl.imsglobal.org/spec/lti/claim/context claim';
 
 1059            } elseif (!empty($resourceLink) && property_exists($resourceLink, 
'id') && (empty($resourceLink->id) || !is_string($resourceLink->id))) {
 
 1060                $this->reason = 
'Invalid value for id property in https://purl.imsglobal.org/spec/lti/claim/resource_link claim';
 
 1066        if (isset($this->messageParameters[
'oauth_signature_method'])) {
 
 1067            $this->signatureMethod = $this->messageParameters[
'oauth_signature_method'];
 
 1068            if (($this instanceof 
Tool) && !empty($this->platform)) {
 
 1069                $this->platform->signatureMethod = $this->signatureMethod;
 
 1074            $ok = isset($this->messageParameters[
'lti_message_type']);
 
 1076                $this->reason = 
'Missing lti_message_type parameter.';
 
 1080            $ok = isset($this->messageParameters[
'lti_version']) && in_array($this->messageParameters[
'lti_version'],
 
 1083                $this->reason = 
'Invalid or missing lti_version parameter.';
 
 1100            $secret = $this->secret;
 
 1101        } elseif (($this instanceof 
Tool) && !empty($this->platform)) {
 
 1102            $key = $this->platform->getKey();
 
 1103            $secret = $this->platform->secret;
 
 1108        if ($this instanceof 
Tool) {
 
 1109            $platform = $this->platform;
 
 1110            $publicKey = $this->platform->rsaKey;
 
 1111            $jku = $this->platform->jku;
 
 1118                $publicKey = $this->rsaKey;
 
 1122        if (empty($this->jwt) || empty($this->jwt->hasJwt())) {  
 
 1127                $server->add_signature_method($method);
 
 1129                $server->add_signature_method($method);
 
 1131                $server->add_signature_method($method);
 
 1133                $server->add_signature_method($method);
 
 1135                $server->add_signature_method($method);
 
 1136                $request = OAuth\OAuthRequest::from_request();
 
 1137                if (isset($request->get_parameters()[
'_new_window']) && !isset($this->messageParameters[
'_new_window'])) {
 
 1138                    $request->unset_parameter(
'_new_window');
 
 1140                $server->verify_request($request);
 
 1142            } 
catch (\Exception $e) {
 
 1143                if (empty($this->reason)) {
 
 1145                    $signature = $request->build_signature($method, $oauthConsumer, 
false);
 
 1146                    if ($this->debugMode) {
 
 1147                        $this->reason = $e->getMessage();
 
 1149                    if (empty($this->reason)) {
 
 1150                        $this->reason = 
'OAuth signature check failed - perhaps an incorrect secret or timestamp.';
 
 1152                    $this->details[] = 
"Shared secret: '{$secret}'";
 
 1153                    $this->details[] = 
'Current timestamp: ' . time();
 
 1154                    $this->details[] = 
"Expected signature: {$signature}";
 
 1155                    $this->details[] = 
"Base string: {$request->base_string}";
 
 1159            $nonce = 
new PlatformNonce($platform, $this->jwt->getClaim(
'nonce'));
 
 1160            $ok = !$nonce->load();
 
 1162                $ok = $nonce->save();
 
 1165                $this->reason = 
'Invalid nonce.';
 
 1166            } elseif (!empty($publicKey) || !empty($jku) || Jwt::$allowJkuHeader) {
 
 1167                $ok = $this->jwt->verify($publicKey, $jku);
 
 1169                    $this->reason = 
'JWT signature check failed - perhaps an invalid public key or timestamp';
 
 1173                $this->reason = 
'Unable to verify JWT signature as neither a public key nor a JSON Web Key URL is specified';
 
 1191    private function parseMessage($strictMode, $disableCookieCheck, $generateWarnings)
 
 1193        if (is_null($this->messageParameters)) {
 
 1194            $this->getRawParameters();
 
 1195            if (isset($this->rawParameters[
'id_token']) || isset($this->rawParameters[
'JWT'])) {  
 
 1197                    $this->jwt = Jwt::getJwtClient();
 
 1198                    if (isset($this->rawParameters[
'id_token'])) {
 
 1199                        $this->ok = $this->jwt->load($this->rawParameters[
'id_token'], $this->rsaKey);
 
 1201                        $this->ok = $this->jwt->load($this->rawParameters[
'JWT'], $this->rsaKey);
 
 1204                        $this->reason = 
'Message does not contain a valid JWT';
 
 1206                        $this->ok = $this->jwt->hasClaim(
'iss') && $this->jwt->hasClaim(
'aud') && $this->jwt->hasClaim(
'nonce') &&
 
 1209                            $iss = $this->jwt->getClaim(
'iss');
 
 1210                            $aud = $this->jwt->getClaim(
'aud');
 
 1212                            $this->ok = !empty($iss) && !empty($aud) && !empty($deploymentId);
 
 1214                                $this->reason = 
'iss, aud and/or deployment_id claim is empty';
 
 1215                            } elseif (is_array($aud)) {
 
 1216                                if ($this->jwt->hasClaim(
'azp')) {
 
 1217                                    $this->ok = !empty($this->jwt->getClaim(
'azp'));
 
 1219                                        $this->reason = 
'azp claim is empty';
 
 1221                                        $this->ok = in_array($this->jwt->getClaim(
'azp'), $aud);
 
 1223                                            $aud = $this->jwt->getClaim(
'azp');
 
 1225                                            $this->reason = 
'azp claim value is not included in aud claim';
 
 1230                                    $this->ok = !empty($aud);
 
 1232                                        $this->reason = 
'First element of aud claim is empty';
 
 1235                            } elseif ($this->jwt->hasClaim(
'azp')) {
 
 1236                                $this->ok = $this->jwt->getClaim(
'azp') === $aud;
 
 1238                                    $this->reason = 
'aud claim does not match the azp claim';
 
 1242                                if ($this instanceof Tool) {
 
 1244                                    $this->platform->platformId = $iss;
 
 1245                                    if (isset($this->rawParameters[
'id_token'])) {
 
 1246                                        $this->ok = !empty($this->rawParameters[
'state']);
 
 1248                                            $state = $this->rawParameters[
'state'];
 
 1249                                            $parts = explode(
'.', $state);
 
 1250                                            if (!empty(session_id()) && (count($parts) > 1) && (session_id() !== $parts[1]) &&
 
 1251                                                ($parts[1] !== 
'platformStorage')) {  
 
 1253                                                session_id($parts[1]);
 
 1255                                                $this->onResetSessionId();
 
 1257                                            $usePlatformStorage = (substr($state, -16) === 
'.platformStorage');
 
 1258                                            if ($usePlatformStorage) {
 
 1259                                                $state = substr($state, 0, -16);
 
 1261                                            $this->onAuthenticate($state, $this->jwt->getClaim(
'nonce'), $usePlatformStorage);
 
 1262                                            if (!$disableCookieCheck) {
 
 1263                                                if (empty($_COOKIE) && !isset($_POST[
'_new_window'])) {  
 
 1265                                                    $_POST[
'_new_window'] = 
'';
 
 1272                                            $this->reason = 
'state parameter is missing';
 
 1275                                            $nonce = 
new PlatformNonce($this->platform, $state);
 
 1276                                            $this->ok = $nonce->load();
 
 1279                                                $nonce = 
new PlatformNonce($platform, $state);
 
 1280                                                $this->ok = $nonce->load();
 
 1284                                                $nonce = 
new PlatformNonce($platform, $state);
 
 1285                                                $this->ok = $nonce->load();
 
 1288                                                $this->ok = $nonce->delete();
 
 1291                                                $this->reason = 
'state parameter is invalid or has expired';
 
 1296                                $this->messageParameters = array();
 
 1298                                    $this->messageParameters[
'oauth_consumer_key'] = $aud;
 
 1299                                    $this->messageParameters[
'oauth_signature_method'] = $this->jwt->getHeader(
'alg');
 
 1300                                    $this->parseClaims($strictMode, $generateWarnings);
 
 1304                            $this->reason = 
'iss, aud, deployment_id and/or nonce claim not found';
 
 1307                } 
catch (\Exception $e) {
 
 1309                    $this->reason = 
'Message does not contain a valid JWT';
 
 1311            } elseif (isset($this->rawParameters[
'error'])) {  
 
 1313                $this->reason = $this->rawParameters[
'error'];
 
 1314                if (!empty($this->rawParameters[
'error_description'])) {
 
 1315                    $this->reason .= 
": {$this->rawParameters['error_description']}";
 
 1318                if ($this instanceof Tool) {
 
 1319                    if (isset($this->rawParameters[
'oauth_consumer_key'])) {
 
 1322                    if (isset($this->rawParameters[
'tool_state'])) {  
 
 1323                        $state = $this->rawParameters[
'tool_state'];
 
 1324                        if (!$disableCookieCheck) {
 
 1325                            $parts = explode(
'.', $state);
 
 1326                            if (empty($_COOKIE) && !isset($_POST[
'_new_window'])) {  
 
 1328                                $_POST[
'_new_window'] = 
'';
 
 1331                            } elseif (!empty(session_id()) && (count($parts) > 1) && (session_id() !== $parts[1])) {  
 
 1333                                session_id($parts[1]);
 
 1335                                $this->onResetSessionId();
 
 1337                            unset($this->rawParameters[
'_new_window']);
 
 1340                        $nonce = 
new PlatformNonce($this->platform, $state);
 
 1341                        $this->ok = $nonce->load();
 
 1343                            $this->reason = 
"Invalid tool_state parameter: '{$state}'";
 
 1347                $this->messageParameters = $this->rawParameters;
 
 1358    private function parseClaims($strictMode, $generateWarnings)
 
 1364            if (!empty($mapping[
'suffix'])) {
 
 1365                $claim .= 
"-{$mapping['suffix']}";
 
 1367            $claim .= 
'/claim/';
 
 1368            if (is_null($mapping[
'group'])) {
 
 1369                $claim = $mapping[
'claim'];
 
 1370            } elseif (empty($mapping[
'group'])) {
 
 1371                $claim .= $mapping[
'claim'];
 
 1373                $claim .= $mapping[
'group'];
 
 1375            if ($this->jwt->hasClaim($claim)) {
 
 1377                if (empty($mapping[
'group'])) {
 
 1378                    unset($payload->{$claim});
 
 1379                    $value = $this->jwt->getClaim($claim);
 
 1381                    $group = $this->jwt->getClaim($claim);
 
 1382                    if (is_array($group) && array_key_exists($mapping[
'claim'], $group)) {
 
 1383                        unset($payload->{$claim}[$mapping[
'claim']]);
 
 1384                        $value = $group[$mapping[
'claim']];
 
 1385                    } elseif (is_object($group) && isset($group->{$mapping[
'claim']})) {
 
 1386                        unset($payload->{$claim}->{$mapping[
'claim']});
 
 1387                        $value = $group->{$mapping[
'claim']};
 
 1390                if (!is_null($value)) {
 
 1391                    if (isset($mapping[
'isArray']) && $mapping[
'isArray']) {
 
 1392                        if (!is_array($value)) {
 
 1393                            $errors[] = 
"'{$claim}' claim must be an array";
 
 1395                            $value = implode(
',', $value);
 
 1397                    } elseif (isset($mapping[
'isObject']) && $mapping[
'isObject']) {
 
 1398                        $value = json_encode($value);
 
 1399                    } elseif (isset($mapping[
'isBoolean']) && $mapping[
'isBoolean']) {
 
 1400                        $value = $value ? 
'true' : 
'false';
 
 1401                    } elseif (isset($mapping[
'isInteger']) && $mapping[
'isInteger']) {
 
 1402                        $value = strval($value);
 
 1403                    } elseif (!is_string($value)) {
 
 1404                        if ($generateWarnings) {
 
 1405                            $this->warnings[] = 
"Value of claim '{$claim}' is not a string: '{$value}'";
 
 1408                            $value = strval($value);
 
 1412                if (!is_null($value) && is_string($value)) {
 
 1413                    $this->messageParameters[$key] = $value;
 
 1417        if (!empty($this->messageParameters[
'lti_message_type']) &&
 
 1419            $this->messageParameters[
'lti_message_type'] = array_search($this->messageParameters[
'lti_message_type'],
 
 1422        if (!empty($this->messageParameters[
'accept_types'])) {
 
 1423            $types = array_map(
'trim', explode(
',', $this->messageParameters[
'accept_types']));
 
 1424            $types = array_filter($types);
 
 1425            $mediaTypes = array();
 
 1426            if (!empty($this->messageParameters[
'accept_media_types'])) {
 
 1427                $mediaTypes = array_map(
'trim', explode(
',', $this->messageParameters[
'accept_media_types']));
 
 1428                $mediaTypes = array_filter($mediaTypes);
 
 1430            if (in_array(Item::TYPE_LTI_LINK, $types)) {
 
 1431                $mediaTypes[] = Item::LTI_LINK_MEDIA_TYPE;
 
 1433            if (in_array(Item::TYPE_LTI_ASSIGNMENT, $types)) {
 
 1434                $mediaTypes[] = Item::LTI_ASSIGNMENT_MEDIA_TYPE;
 
 1436            if (in_array(
'html', $types) && !in_array(
'*/*', $mediaTypes)) {
 
 1437                $mediaTypes[] = 
'text/html';
 
 1439            if (in_array(
'image', $types) && !in_array(
'*/*', $mediaTypes)) {
 
 1440                $mediaTypes[] = 
'image/*';
 
 1442            $mediaTypes = array_unique($mediaTypes);
 
 1443            $this->messageParameters[
'accept_media_types'] = implode(
',', $mediaTypes);
 
 1446        if ($this->jwt->hasClaim($claim)) {
 
 1447            unset($payload->{$claim});
 
 1448            $custom = $this->jwt->getClaim($claim);
 
 1449            if (!is_array($custom) && !is_object($custom)) {
 
 1450                $errors[] = 
"'{$claim}' claim must be an object";
 
 1452                foreach ($custom as $key => $value) {
 
 1453                    $this->messageParameters[
"custom_{$key}"] = $value;
 
 1458        if ($this->jwt->hasClaim($claim)) {
 
 1459            unset($payload->{$claim});
 
 1460            $ext = $this->jwt->getClaim($claim);
 
 1461            if (!is_array($ext) && !is_object($ext)) {
 
 1462                $errors[] = 
"'{$claim}' claim must be an object";
 
 1464                foreach ($ext as $key => $value) {
 
 1465                    $this->messageParameters[
"ext_{$key}"] = $value;
 
 1470        if ($this->jwt->hasClaim($claim)) {
 
 1471            unset($payload->{$claim});
 
 1472            $lti1p1 = $this->jwt->getClaim($claim);
 
 1473            if (!is_array($lti1p1) && !is_object($lti1p1)) {
 
 1474                $errors[] = 
"'{$claim}' claim must be an object";
 
 1476                foreach ($lti1p1 as $key => $value) {
 
 1477                    if (is_null($value)) {
 
 1479                    } elseif (is_object($value)) {
 
 1480                        $value = json_encode($value);
 
 1482                    $this->messageParameters[
"lti1p1_{$key}"] = $value;
 
 1486        $claim = 
'http://www.brightspace.com';
 
 1487        if ($this->jwt->hasClaim($claim)) {
 
 1488            $d2l = $this->jwt->getClaim($claim);
 
 1489            if (is_array($d2l)) {
 
 1490                if (!empty($d2l[
'username'])) {
 
 1491                    $this->messageParameters[
'ext_d2l_username'] = $d2l[
'username'];
 
 1492                    unset($payload->{$claim}[
'username']);
 
 1494            } 
else if (is_object($ext)) {
 
 1495                if (!empty($d2l->username)) {
 
 1496                    $this->messageParameters[
'ext_d2l_username'] = $d2l->username;
 
 1497                    unset($payload->{$claim}->username);
 
 1501        if (!empty($payload)) {
 
 1502            $objVars = get_object_vars($payload);
 
 1503            foreach ($objVars as $attrName => $attrValue) {
 
 1504                if (empty((array) $attrValue)) {
 
 1505                    unset($payload->{$attrName});
 
 1508            $this->messageParameters[
'unmapped_claims'] = json_encode($payload);
 
 1510        if (!empty($errors)) {
 
 1512            $this->reason = 
'Invalid JWT: ' . implode(
', ', $errors);
 
 1521    private function doCallback()
 
 1523        if (array_key_exists($this->messageParameters[
'lti_message_type'], 
Util::$METHOD_NAMES)) {
 
 1526            $callback = 
"on{$this->messageParameters['lti_message_type']}";
 
 1528        if (method_exists($this, $callback)) {
 
 1530        } elseif ($this->ok) {
 
 1532            $this->reason = 
"Message type not supported: {$this->messageParameters['lti_message_type']}";
 
 1548    private function addOAuth1Signature($endpoint, $data, $method, $type, $hash, $timestamp)
 
 1551        if (is_array($data)) {
 
 1553            $params[
'oauth_callback'] = 
'about:blank';
 
 1556        $queryString = parse_url($endpoint, PHP_URL_QUERY);
 
 1557        $queryParams = OAuth\OAuthUtil::parse_parameters($queryString);
 
 1558        $params = array_merge_recursive($queryParams, $params);
 
 1560        if (!is_array($data)) {
 
 1562                if (is_null($data)) {
 
 1565                switch ($this->signatureMethod) {
 
 1567                        $hash = base64_encode(hash(
'sha224', $data, 
true));
 
 1570                        $hash = base64_encode(hash(
'sha256', $data, 
true));
 
 1573                        $hash = base64_encode(hash(
'sha384', $data, 
true));
 
 1576                        $hash = base64_encode(hash(
'sha512', $data, 
true));
 
 1579                        $hash = base64_encode(sha1($data, 
true));
 
 1583            $params[
'oauth_body_hash'] = $hash;
 
 1585        if (!empty($timestamp)) {
 
 1586            $params[
'oauth_timestamp'] = $timestamp;
 
 1590        switch ($this->signatureMethod) {
 
 1592                $hmacMethod = 
new OAuth\OAuthSignatureMethod_HMAC_SHA224();
 
 1595                $hmacMethod = 
new OAuth\OAuthSignatureMethod_HMAC_SHA256();
 
 1598                $hmacMethod = 
new OAuth\OAuthSignatureMethod_HMAC_SHA384();
 
 1601                $hmacMethod = 
new OAuth\OAuthSignatureMethod_HMAC_SHA512();
 
 1604                $hmacMethod = 
new OAuth\OAuthSignatureMethod_HMAC_SHA1();
 
 1608        $secret = $this->secret;
 
 1610            if (($this instanceof Tool) && !empty($this->platform)) {
 
 1611                $key = $this->platform->getKey();
 
 1612                $secret = $this->platform->secret;
 
 1618        $oauthConsumer = 
new OAuth\OAuthConsumer($key, $secret, 
null);
 
 1619        $oauthReq = OAuth\OAuthRequest::from_consumer_and_token($oauthConsumer, 
null, $method, $endpoint, $params);
 
 1620        $oauthReq->sign_request($hmacMethod, $oauthConsumer, 
null);
 
 1621        if (!is_array($data)) {
 
 1622            $header = $oauthReq->to_header();
 
 1624                if (!empty($type)) {
 
 1625                    $header .= 
"\nAccept: {$type}";
 
 1627            } elseif (isset($type)) {
 
 1628                $header .= 
"\nContent-Type: {$type}; charset=UTF-8";
 
 1629                $header .= 
"\nContent-Length: " . strlen($data);
 
 1634            $params = $oauthReq->get_parameters();
 
 1635            foreach ($queryParams as $key => $value) {
 
 1636                if (!is_array($value)) {
 
 1637                    if (!is_array($params[$key])) {
 
 1638                        if ($params[$key] === $value) {
 
 1639                            unset($params[$key]);
 
 1642                        $params[$key] = array_diff($params[$key], array($value));
 
 1645                    foreach ($value as $element) {
 
 1646                        $params[$key] = array_diff($params[$key], array($value));
 
 1651            foreach ($params as $key => $value) {
 
 1652                if (is_array($value)) {
 
 1653                    if (count($value) <= 0) {
 
 1654                        unset($params[$key]);
 
 1655                    } elseif (count($value) === 1) {
 
 1656                        $params[$key] = reset($value);
 
 1676    private function addJWTSignature($endpoint, $data, $method, $type, $nonce, $timestamp)
 
 1679        if (is_array($data)) {
 
 1681            if (empty($nonce)) {
 
 1685            if (!array_key_exists(
'grant_type', $data)) {
 
 1686                $this->messageParameters = $data;
 
 1687                $payload = $this->getMessageClaims();
 
 1688                $privateKey = $this->rsaKey;
 
 1691                if ($this instanceof Platform) {
 
 1695                    $payload[
'iss'] = $this->platformId;
 
 1696                    $payload[
'aud'] = array($this->clientId);
 
 1697                    $payload[
'azp'] = $this->clientId;
 
 1700                    $paramName = 
'id_token';
 
 1702                    if (!empty($this->platform)) {
 
 1703                        $publicKey = $this->platform->rsaKey;
 
 1704                        $payload[
'iss'] = $this->platform->clientId;
 
 1705                        $payload[
'aud'] = array($this->platform->platformId);
 
 1706                        $payload[
'azp'] = $this->platform->platformId;
 
 1711                $payload[
'nonce'] = $nonce;
 
 1713                $authorizationId = 
'';
 
 1714                if ($this instanceof Tool) {
 
 1716                    if (!empty($this->platform)) {
 
 1717                        $sub = $this->platform->clientId;
 
 1718                        $authorizationId = $this->platform->authorizationServerId;
 
 1719                        $publicKey = $this->platform->rsaKey;
 
 1721                    $privateKey = $this->rsaKey;
 
 1725                    $sub = $this->clientId;
 
 1728                    $privateKey = $this->rsaKey;
 
 1733                $payload[
'iss'] = $sub;
 
 1734                $payload[
'sub'] = $sub;
 
 1735                if (empty($authorizationId)) {
 
 1736                    $authorizationId = $endpoint;
 
 1738                $payload[
'aud'] = array($authorizationId);
 
 1739                $payload[
'jti'] = $nonce;
 
 1741                $paramName = 
'client_assertion';
 
 1745            if (empty($timestamp)) {
 
 1746                $timestamp = time();
 
 1748            $payload[
'iat'] = $timestamp;
 
 1749            $payload[
'exp'] = $timestamp + Jwt::$life;
 
 1751                $jwt = Jwt::getJwtClient();
 
 1752                $params[$paramName] = $jwt::sign($payload, $this->signatureMethod, $privateKey, $kid, $jku, $this->encryptionMethod,
 
 1754            } 
catch (\Exception $e) {
 
 1761            if ($this instanceof Tool) {
 
 1762                $platform = $this->platform;
 
 1766            $accessToken = $platform->getAccessToken();
 
 1767            if (empty($accessToken)) {
 
 1768                $accessToken = 
new AccessToken($platform);
 
 1769                $platform->setAccessToken($accessToken);
 
 1771            if (!$accessToken->hasScope()) {  
 
 1772                $accessToken->get();
 
 1774            if (!empty($accessToken->token)) {
 
 1775                $header = 
"Authorization: Bearer {$accessToken->token}";
 
 1777            if (empty($data) && ($method !== 
'DELETE')) {
 
 1778                if (!empty($type)) {
 
 1779                    $header .= 
"\nAccept: {$type}";
 
 1781            } elseif (isset($type)) {
 
 1782                $header .= 
"\nContent-Type: {$type}; charset=UTF-8";
 
 1783                if (!empty($data) && is_string($data)) {
 
 1784                    $header .= 
"\nContent-Length: " . strlen($data);
 
 1800    private static function fullyQualifyClaim($claim, $value)
 
 1804        if (is_object($value)) {
 
 1805            foreach ($value as $c => $v) {
 
 1807                $claims = array_merge($claims, static::fullyQualifyClaim(
"{$claim}/{$c}", $v));
 
 1811            $claims[$claim] = $value;
 
Class to represent a content-item object.
Class to provide a connection to a persistent store for LTI objects.
Class to represent an HTTP message request.
Class to represent an HTTP message request.
Class to represent an OAuth Consumer.
Class to represent an OAuth Data Store.
static $POST_INPUT
Access to POST data.
Class to represent an OAuth server.
Class to represent an OAuth HMAC_SHA1 signature method.
Class to represent an OAuth HMAC_SHA224 signature method.
Class to represent an OAuth HMAC_SHA256 signature method.
Class to represent an OAuth HMAC_SHA384 signature method.
Class to represent an OAuth HMAC_SHA512 signature method.
Class to represent an LTI system.
sendMessage($url, $type, $messageParams, $target='', $userId=null, $hint=null)
Generate a web page containing an auto-submitted form of LTI message parameters.
$warnings
Warnings relating to last request processed.
addSignature($endpoint, $data, $method='POST', $type=null, $nonce='', $hash=null, $timestamp=null)
Add the signature to an array of message parameters or to a header string.
$reason
Error message for last request processed.
getRawParameters()
Get the raw POST parameters.
$debugMode
Whether debug level messages are to be reported.
$name
Local name of platform/tool.
$enableUntil
Timestamp until which the system instance is enabled to accept connection requests.
getMessageClaims($fullyQualified=false)
Get the message claims.
$enabled
Whether the system instance is enabled to accept connection requests.
hasJwt()
Check whether a JWT exists.
signMessage(&$url, $type, $version, $params, $loginHint=null, $ltiMessageHint=null)
Add the signature to an LTI message.
$dataConnector
Data connector object.
verifySignature()
Verify the signature of a message.
$messageParameters
LTI message parameters.
$updated
Timestamp for when the object was last updated.
setSetting($name, $value=null)
Set a setting value.
signParameters($url, $type, $version, $params)
Add the signature to an LTI message.
$rsaKey
RSA key in PEM or JSON format.
$encryptionMethod
Algorithm used for encrypting messages.
$details
Details for error message relating to last request processed.
$jku
Endpoint for public key.
saveSettings()
Save setting values.
$created
Timestamp for when the object was created.
$ok
True if the last request was successful.
$rawParameters
Raw message parameters.
setKey($key)
Set the consumer key.
$enableFrom
Timestamp from which the the system instance is enabled to accept connection requests.
setSettings($settings)
Set an array of all setting values.
signServiceRequest($url, $method, $type, $data=null)
Generates the headers for an LTI service request.
$lastAccess
Timestamp for date of last connection to this system.
useOAuth1()
Determine whether this consumer is using the OAuth 1 security model.
checkMessage()
Verify the required properties of an LTI message.
getRecordId()
Get the system record ID.
getKey()
Get the consumer key.
getSetting($name, $default='')
Get a setting value.
setRecordId($id)
Sets the system record ID.
$requiredScopes
Scopes to request when obtaining an access token.
doServiceRequest($service, $method, $format, $data)
Perform a service request.
getSettings()
Get an array of all setting values.
static parseRoles($roles, $ltiVersion=Util::LTI_VERSION1, $addPrincipalRole=false)
Parse a set of roles to comply with a specified version of LTI.
$jwt
JWT ClientInterface object.
$signatureMethod
Method used for signing messages.
Class to implement utility methods.
static sendForm($url, $params, $target='', $javascript='')
Generate a web page containing an auto-submitted form of parameters.
const LTI_VERSION1P3
LTI version 1.3 for messages.
const JWT_CLAIM_MAPPING
Mapping for standard message parameters to JWT claim.
const MESSAGE_TYPE_MAPPING
Mapping for standard message types.
static getRandomString($length=8)
Generate a random string.
static cloneObject($obj)
Clone an object and any objects it contains.
static $METHOD_NAMES
List of supported message types and associated class methods.
static $LTI_VERSIONS
Permitted LTI versions for messages.
const LTI_VERSION1
LTI version 1 for messages.
static jsonDecode($str, $associative=false)
Decode a JSON string.
static setTestCookie($delete=false)
Set or delete a test cookie.
const JWT_CLAIM_PREFIX
Prefix for standard JWT message claims.
const LTI_VERSION2
LTI version 2 for messages.
Interface to represent an HWT client.