-
Notifications
You must be signed in to change notification settings - Fork 416
[FEATURE] LTI: Add AGS consumer services and deep linking content selection #11835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release_11
Are you sure you want to change the base?
Changes from all commits
41d8725
e6d13e9
df58abf
7e4da05
35e90a9
0723440
089b001
bd46d97
06728aa
b6fdc47
ac965ac
d0ae088
6cf5502
59ca25d
1a72920
019aa21
471e2f8
a62b2ae
b826a58
4584211
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -110,6 +110,50 @@ private function getClientIdFromProviderUrl(string $providerUrl): string | |||||
| return $res; | ||||||
| } | ||||||
|
|
||||||
| protected function startDeepLinkingCmd() | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| { | ||||||
| global $DIC; | ||||||
| $provider = $this->object->getProvider(); | ||||||
|
|
||||||
| $platform_client_id = $provider->getClientId(); | ||||||
| $deployment_id = $provider->getId(); | ||||||
| $user_id = ilObjLTIConsumer::getDeepLinkingUserIdentifier($provider, $DIC->user()); // or whatever you used as login_hint | ||||||
|
|
||||||
| $lti_message_hint = json_encode([ | ||||||
| 'deployment_id' => $deployment_id, | ||||||
| ]); | ||||||
| $state = bin2hex(random_bytes(16)); | ||||||
|
|
||||||
|
|
||||||
| $params = [ | ||||||
| 'login_hint' => $user_id, | ||||||
| 'iss' => ilObjLTIConsumer::getPlattformId(), | ||||||
| 'lti_message_hint' => $lti_message_hint, | ||||||
| 'target_link_uri' => $provider->getContentItemUrl(), | ||||||
| 'id' => $platform_client_id, // Instead of client_id due to ILIAS redirection system | ||||||
| 'lti_deployment_id' => $deployment_id, | ||||||
| 'state' => $state, | ||||||
| ]; | ||||||
|
|
||||||
|
|
||||||
| $join = (str_contains($provider->getInitiateLogin(), '?')) ? '&' : '?'; | ||||||
| $url = $provider->getInitiateLogin() . $join . http_build_query($params); | ||||||
| $urlSafe = htmlspecialchars($url, ENT_QUOTES); | ||||||
| echo <<<HTML | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are using the HTTP component in other newly introduced code to handle HTTP responses, so please check if if could also be used here to build/send the response and close the connection. You should consider using the HTTP component wherever possible when sending HTTP responses to the client, even in the existing code not touched by this PR: |
||||||
| <!doctype html> | ||||||
| <html> | ||||||
| <body onload="window.location.href='{$urlSafe}'"> | ||||||
| <noscript> | ||||||
| <p>Continue to deep linking...</p> | ||||||
| <a href="{$urlSafe}">Continue</a> | ||||||
| </noscript> | ||||||
| </body> | ||||||
| </html> | ||||||
| HTML; | ||||||
| exit; | ||||||
|
|
||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @throws ilMDServicesException | ||||||
| */ | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -129,7 +129,8 @@ protected function getLoginLTI13Form(): ?string | |
| return null; | ||
| } else { | ||
| $this->initCmixUser(); | ||
| $params = $this->getLaunchParametersLTI13($loginData['redirect_uri'], $this->object->getProvider()->getClientId(), $this->object->getProvider()->getId(), $loginData['nonce']); | ||
| $targetLinkUri = $loginData['target_link_uri'] ?? $this->getTargetLinkUri(); | ||
| $params = $this->getLaunchParametersLTI13($targetLinkUri, $this->object->getProvider()->getClientId(), $this->object->getProvider()->getId(), $loginData['nonce']); | ||
| if (isset($loginData['state'])) { | ||
| $params['state'] = $loginData['state']; | ||
| } | ||
|
|
@@ -256,7 +257,7 @@ protected function getStartButtonTxt13(): string | |
| $output = '<form id="lti_launch_form" name="lti_launch_form" action="' . $this->object->getProvider()->getInitiateLogin() . '" method="post" target="' . $target . '" encType="application/x-www-form-urlencoded">'; | ||
|
|
||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'iss', ilObjLTIConsumer::getIliasHttpPath()) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'target_link_uri', $this->object->getProvider()->getProviderUrl()) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'target_link_uri', htmlspecialchars($this->getTargetLinkUri(), ENT_QUOTES)) . "\n"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we use a |
||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'login_hint', $user_ident) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'lti_message_hint', $ltiMessageHint) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'client_id', $this->object->getProvider()->getClientId()) . "\n"; | ||
|
|
@@ -292,7 +293,7 @@ protected function getEmbeddedAutoStartFormular(): string | |
| ilSession::set('lti_message_hint', $ltiMessageHint); | ||
| $output = '<form id="lti_launch_form" name="lti_launch_form" action="' . $this->object->getProvider()->getInitiateLogin() . '" method="post" target="' . $target . '" encType="application/x-www-form-urlencoded">'; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'iss', ilObjLTIConsumer::getIliasHttpPath()) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'target_link_uri', $this->object->getProvider()->getProviderUrl()) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'target_link_uri', htmlspecialchars($this->getTargetLinkUri(), ENT_QUOTES)) . "\n"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we use a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it ensured that all the existing values here surrounding the new lines are already trustworthy (checked, escaped)? |
||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'login_hint', $user_ident) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'lti_message_hint', $ltiMessageHint) . "\n"; | ||
| $output .= sprintf('<input type="hidden" name="%s" value="%s" />', 'client_id', $this->object->getProvider()->getClientId()) . "\n"; | ||
|
|
@@ -404,6 +405,18 @@ protected function getLaunchParametersLTI13(string $endpoint, string $clientId, | |
| ); | ||
| } | ||
|
|
||
| private function getTargetLinkUri(): string | ||
| { | ||
| foreach (explode(';', $this->object->getCustomParams()) as $param) { | ||
| $parts = explode('=', $param, 2); | ||
| if (count($parts) === 2 && trim($parts[0]) === 'target_link_uri') { | ||
| return trim($parts[1]); | ||
| } | ||
| } | ||
|
|
||
| return $this->object->getProvider()->getProviderUrl(); | ||
| } | ||
|
|
||
| public static function isEmbeddedLaunchRequest(): bool | ||
| { | ||
| global $DIC; /* @var \ILIAS\DI\Container $DIC */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a contradiction to the explicitly used PHP type.