ILIAS  release_8 Revision v8.24
Platform.php
Go to the documentation of this file.
1<?php
2
20
23use ILIAS\LTI\ToolProvider\Http\HTTPMessage;
24//use ILIAS\LTIOAuth;
26
36{
37 use System;
38 use ApiHook; //added UK
39
43 public static array $MESSAGE_TYPES = array(
44 'ContentItemSelection',
45 'LtiStartAssessment'
46 );
47
53 public ?string $name = null;
54
60 public ?string $platformId = null;
61
67 public ?string $clientId = null;
68
74 public ?string $deploymentId = null;
75
81 public ?string $authorizationServerId = null;
82
88 public ?string $authenticationUrl = null;
89
95 public ?string $accessTokenUrl = null;
96
102 public ?string $ltiVersion = null;
103
109 public ?string $consumerName = null;
110
116 public ?string $consumerVersion = null;
117
123 public ?object $profile = null;
124
130 public ?object $toolProxy = null;
131
137 public ?string $consumerGuid = null;
138
144 public ?string $cssPath = null;
145
151 private ?AccessToken $accessToken = null;
152
158 public function getAccessToken(): ?AccessToken
159 {
160 return $this->accessToken;
161 }
162
168 {
169 $this->accessToken = $accessToken;
170 }
171
177 public bool $protected = false;
178
185
191 public string $defaultEmail = '';
192
198 public ?HTTPMessage $lastServiceRequest = null;
199
205 {
206 $this->initialize();
207 if (empty($dataConnector)) {
209 }
210 $this->dataConnector = $dataConnector;
211 }
212
216 public function initialize()
217 {
218 $this->id = null;
219 $this->key = null;
220 $this->name = null;
221 $this->secret = null;
222 $this->signatureMethod = 'HMAC-SHA1';
223 $this->encryptionMethod = ''; //changed from null
224 $this->rsaKey = null;
225 $this->kid = null;
226 $this->jku = null;
227 $this->platformId = null;
228 $this->clientId = null;
229 $this->deploymentId = null;
230 $this->ltiVersion = null;
231 $this->consumerName = null;
232 $this->consumerVersion = null;
233 $this->consumerGuid = null;
234 $this->profile = null;
235 $this->toolProxy = null;
236 $this->settings = array();
237 $this->protected = false;
238 $this->enabled = false;
239 $this->enableFrom = null;
240 $this->enableUntil = null;
241 $this->lastAccess = null;
242 $this->idScope = Tool::ID_SCOPE_ID_ONLY;
243 $this->defaultEmail = '';
244 $this->created = null;
245 $this->updated = null;
246 }
247
253 public function initialise()
254 {
255 $this->initialize();
256 }
257
263 public function save(): bool
264 {
265 return $this->dataConnector->savePlatform($this);
266 }
267
273 public function delete(): bool
274 {
275 return $this->dataConnector->deletePlatform($this);
276 }
277
285 public function getId(): ?string
286 {
287 if (!empty($this->key)) {
288 $id = $this->key;
289 } elseif (!empty($this->platformId)) {
291 if (!empty($this->clientId)) {
292 $id .= '/' . $this->clientId;
293 }
294 if (!empty($this->deploymentId)) {
295 $id .= '#' . $this->deploymentId;
296 }
297 } else {
298 $id = null;
299 }
300
301 return $id;
302 }
303
309 public function getFamilyCode(): ?string
310 {
311 $familyCode = '';
312 if (!empty($this->consumerVersion)) {
313 $familyCode = $this->consumerVersion;
314 $pos = strpos($familyCode, '-');
315 if ($pos !== false) {
316 $familyCode = substr($familyCode, 0, $pos);
317 }
318 }
319
320 return $familyCode;
321 }
322
328 public function getDataConnector(): ?DataConnector
329 {
331 }
332
338 public function getIsAvailable(): bool
339 {
340 $ok = $this->enabled;
341
342 $now = time();
343 if ($ok && !is_null($this->enableFrom)) {
344 $ok = $this->enableFrom <= $now;
345 }
346 if ($ok && !is_null($this->enableUntil)) {
347 $ok = $this->enableUntil > $now;
348 }
349
350 return $ok;
351 }
352
358 public function hasToolSettingsService(): bool
359 {
360 $has = !empty($this->getSetting('custom_system_setting_url'));
361 if (!$has) {
363 }
364 return $has;
365 }
366
372 public function getToolSettings(bool $simple = true)
373 {
374 $ok = false;
375 $settings = array();
376 if (!empty($this->getSetting('custom_system_setting_url'))) {
377 $url = $this->getSetting('custom_system_setting_url');
378 $service = new Service\ToolSettings($this, $url, $simple);
379 $settings = $service->get();
380 $this->lastServiceRequest = $service->getHttpMessage();
381 $ok = $settings !== false;
382 }
383 if (!$ok && $this->hasConfiguredApiHook(self::$TOOL_SETTINGS_SERVICE_HOOK, $this->getFamilyCode(), $this)) {
384 $className = $this->getApiHook(self::$TOOL_SETTINGS_SERVICE_HOOK, $this->getFamilyCode());
385 $hook = new $className($this);
386 $settings = $hook->getToolSettings($simple);
387 }
388
389 return $settings;
390 }
391
397 public function setToolSettings(array $settings = array()): bool
398 {
399 $ok = false;
400 if (!empty($this->getSetting('custom_system_setting_url'))) {
401 $url = $this->getSetting('custom_system_setting_url');
402 $service = new Service\ToolSettings($this, $url);
403 $ok = $service->set($settings);
404 $this->lastServiceRequest = $service->getHttpMessage();
405 }
406 if (!$ok && $this->hasConfiguredApiHook(self::$TOOL_SETTINGS_SERVICE_HOOK, $this->getFamilyCode(), $this)) {
407 $className = $this->getApiHook(self::$TOOL_SETTINGS_SERVICE_HOOK, $this->getFamilyCode());
408 $hook = new $className($this);
409 $ok = $hook->setToolSettings($settings);
410 }
411
412 return $ok;
413 }
414
420 public function getTools(): array
421 {
422 return $this->dataConnector->getTools();
423 }
424
430 public function hasAccessTokenService(): bool
431 {
432 $has = !empty($this->getSetting('custom_oauth2_access_token_url'));
433 if (!$has) {
435 }
436 return $has;
437 }
438
444 public function getMessageParameters(): array
445 {
446 if ($this->ok && is_null($this->messageParameters)) {
447 $this->parseMessage();
448 }
449
451 }
452
456 public function handleRequest()
457 {
458 $parameters = Util::getRequestParameters();
459 if ($this->debugMode) {
461 }
462 if ($this->ok) {
463 if (!empty($parameters['client_id'])) { // Authentication request
466 } else { // LTI message
467 $this->getMessageParameters();
469 if ($this->ok && $this->authenticate()) {
470 $this->doCallback();
471 }
472 }
473 }
474 if (!$this->ok) {
475 $this->onError();
476 }
477 if (!$this->ok) {
478 $errorMessage = "Request failed with reason: '{$this->reason}'";
479 if (!empty($this->details)) {
480 $errorMessage .= PHP_EOL . 'Debug information:';
481 foreach ($this->details as $detail) {
482 $errorMessage .= PHP_EOL . " {$detail}";
483 }
484 }
485 Util::logError($errorMessage);
486 }
487 }
488
496 public static function fromConsumerKey(string $key = null, DataConnector $dataConnector = null, bool $autoEnable = false): Platform
497 {
498 $platform = new static($dataConnector);
499 $platform->key = $key;
500 if (!empty($dataConnector)) {
501 $ok = $dataConnector->loadPlatform($platform);
502 if ($ok && $autoEnable) {
503 $platform->enabled = true;
504 }
505 }
506
507 return $platform;
508 }
509
510 //changed; to be erased because of php strict standards
511 // /**
512 // * Load the platform from the database by its platform, client and deployment IDs.
513 // * @param string $platformId The platform ID
514 // * @param string $clientId The client ID
515 // * @param string $deploymentId The deployment ID
516 // * @param DataConnector|null $dataConnector A data connector object
517 // * @param bool $autoEnable True if the platform is to be enabled automatically (optional, default is false)
518 // * @return Platform The platform object
519 // */
520 // public static function fromPlatformId(string $platformId, string $clientId, string $deploymentId, DataConnector $dataConnector = null, bool $autoEnable = false) : Platform
521 // {
522 // $platform = new static($dataConnector);
523 // $platform->platformId = $platformId;
524 // $platform->clientId = $clientId;
525 // $platform->deploymentId = $deploymentId;
526 // if ($dataConnector->loadPlatform($platform)) {
527 // if ($autoEnable) {
528 // $platform->enabled = true;
529 // }
530 // }
531
532 // return $platform;
533 // }
534
535 //changed; to be erased because of php strict standards
536// /**
537// * Load the platform from the database by its record ID.
538// * @param int $id The platform record ID //UK: changed to int
539// * @param DataConnector $dataConnector A data connector object
540// * @return Platform The platform object
541// */
542// public static function fromRecordId(int $id, DataConnector $dataConnector) : Platform
543// {
544// $platform = new static($dataConnector);
545// $platform->setRecordId($id);
546// $dataConnector->loadPlatform($platform);
547//
548// return $platform;
549// }
550
551 ###
552 ### PROTECTED METHODS
553 ###
554
563 protected function onInitiateLogin(string &$url, string &$loginHint, string &$ltiMessageHint, array $params)
564 {
565 $hasSession = !empty(session_id());
566 if (!$hasSession) {
567 session_start();
568 }
569 $_SESSION['ceLTIc_lti_initiated_login'] = array(
570 'messageUrl' => $url,
571 'login_hint' => $loginHint,
572 'lti_message_hint' => $ltiMessageHint,
573 'params' => $params
574 );
575 if (!$hasSession) {
576 session_write_close();
577 }
578 }
579
585 protected function onAuthenticate()
586 {
587 $hasSession = !empty(session_id());
588 if (!$hasSession) {
589 session_start();
590 }
591 if (isset($_SESSION['ceLTIc_lti_initiated_login'])) {
592 $login = $_SESSION['ceLTIc_lti_initiated_login'];
593 $parameters = Util::getRequestParameters();
594 if ($parameters['login_hint'] !== $login['login_hint'] ||
595 (isset($login['lti_message_hint']) && (!isset($parameters['lti_message_hint']) || ($parameters['lti_message_hint'] !== $login['lti_message_hint'])))) {
596 $this->ok = false;
597 $this->messageParameters['error'] = 'access_denied';
598 } else {
599 Tool::$defaultTool->messageUrl = $login['messageUrl'];
600 $this->messageParameters = $login['params'];
601 }
602 unset($_SESSION['ceLTIc_lti_initiated_login']);
603 }
604 if (!$hasSession) {
605 session_write_close();
606 }
607 }
608
612 protected function onContentItem()
613 {
614 $this->reason = 'No onContentItem method found for platform';
615 $this->onError();
616 }
617
621 protected function onLtiStartAssessment()
622 {
623 $this->reason = 'No onLtiStartAssessment method found for platform';
624 $this->onError();
625 }
626
630 protected function onError()
631 {
632 $this->ok = false;
633 }
634
635 ###
636 ### PRIVATE METHODS
637 ###
638
646 private function authenticate(): bool
647 {
648 $this->checkMessage();
649 if ($this->ok) {
650 $this->ok = $this->verifySignature();
651 }
652
653 return $this->ok;
654 }
655
662 {
663 $this->messageParameters = array();
664 $parameters = Util::getRequestParameters();
665 $this->ok = isset($parameters['scope']) && isset($parameters['response_type']) &&
666 isset($parameters['client_id']) && isset($parameters['redirect_uri']) &&
667 isset($parameters['login_hint']) && isset($parameters['nonce']);
668 if (!$this->ok) {
669 $this->messageParameters['error'] = 'invalid_request';
670 }
671 if ($this->ok) {
672 $scopes = explode(' ', $parameters['scope']);
673 $this->ok = in_array('openid', $scopes);
674 if (!$this->ok) {
675 $this->messageParameters['error'] = 'invalid_scope';
676 }
677 }
678 if ($this->ok && ($parameters['response_type'] !== 'id_token')) {
679 $this->ok = false;
680 $this->messageParameters['error'] = 'unsupported_response_type';
681 }
682 if ($this->ok && ($parameters['client_id'] !== $this->clientId)) {
683 $this->ok = false;
684 $this->messageParameters['error'] = 'unauthorized_client';
685 }
686 if ($this->ok) {
687 $this->ok = in_array($parameters['redirect_uri'], Tool::$defaultTool->redirectionUris);
688 if (!$this->ok) {
689 $this->messageParameters['error'] = 'invalid_request';
690 $this->messageParameters['error_description'] = 'Unregistered redirect_uri';
691 }
692 }
693 if ($this->ok) {
694 if (isset($parameters['response_mode'])) {
695 $this->ok = ($parameters['response_mode'] === 'form_post');
696 } else {
697 $this->ok = false;
698 }
699 if (!$this->ok) {
700 $this->messageParameters['error'] = 'invalid_request';
701 $this->messageParameters['error_description'] = 'Invalid response_mode';
702 }
703 }
704 if ($this->ok && (!isset($parameters['prompt']) || ($parameters['prompt'] !== 'none'))) {
705 $this->ok = false;
706 $this->messageParameters['error'] = 'invalid_request';
707 $this->messageParameters['error_description'] = 'Invalid prompt';
708 }
709
710 if ($this->ok) {
711 $this->onAuthenticate();
712 }
713 if ($this->ok) {
714 $this->messageParameters = $this->addSignature(
715 Tool::$defaultTool->messageUrl,
716 $this->messageParameters,
717 'POST',
718 null,
719 $parameters['nonce']
720 );
721 }
722 if (isset($parameters['state'])) {
723 $this->messageParameters['state'] = $parameters['state'];
724 }
725 $html = Util::sendForm($parameters['redirect_uri'], $this->messageParameters);
726 echo $html;
727 exit;
728 }
729}
Class to represent an HTTP message.
Definition: AccessToken.php:33
Class to provide a connection to a persistent store for LTI objects.
static getDataConnector(object $db=null, string $dbTableNamePrefix='', string $type='')
Create data connector object.
Class to represent a platform.
Definition: Platform.php:36
initialise()
Initialise the platform.
Definition: Platform.php:253
string $name
Local name of platform.
Definition: Platform.php:53
string $consumerVersion
Tool consumer version (as reported by last tool consumer connection).
Definition: Platform.php:116
onAuthenticate()
Check the hint and recover the message parameters for an authentication request.
Definition: Platform.php:585
save()
Save the platform to the database.
Definition: Platform.php:263
int $idScope
Default scope to use when generating an Id value for a user.
Definition: Platform.php:184
getId()
Get the platform ID.
Definition: Platform.php:285
string $deploymentId
Deployment ID.
Definition: Platform.php:74
onContentItem()
Process a valid content-item message.
Definition: Platform.php:612
bool $protected
Whether the platform instance is protected by matching the consumer_guid value in incoming requests.
Definition: Platform.php:177
__construct(DataConnector $dataConnector=null)
Class constructor.
Definition: Platform.php:204
string $cssPath
Optional CSS path (as reported by last tool consumer connection).
Definition: Platform.php:144
string $ltiVersion
LTI version (as reported by last platform connection).
Definition: Platform.php:102
getIsAvailable()
Is the platform available to accept launch requests?
Definition: Platform.php:338
string $authorizationServerId
Authorization server ID.
Definition: Platform.php:81
getMessageParameters()
Get the message parameters.
Definition: Platform.php:444
string $clientId
Client ID.
Definition: Platform.php:67
setAccessToken(AccessToken $accessToken)
Set the authorization access token.
Definition: Platform.php:167
hasToolSettingsService()
Check if the Tool Settings service is supported.
Definition: Platform.php:358
object $profile
The platform profile data.
Definition: Platform.php:123
HTTPMessage $lastServiceRequest
HttpMessage object for last service request.
Definition: Platform.php:198
AccessToken $accessToken
Access token to authorize service requests.
Definition: Platform.php:151
string $consumerGuid
Tool consumer GUID (as reported by first tool consumer connection).
Definition: Platform.php:137
getDataConnector()
Get the data connector.
Definition: Platform.php:328
authenticate()
Check the authenticity of the LTI message.
Definition: Platform.php:646
getToolSettings(bool $simple=true)
Get Tool Settings.
Definition: Platform.php:372
string $defaultEmail
Default email address (or email domain) to use when no email address is provided for a user.
Definition: Platform.php:191
hasAccessTokenService()
Check if the Access Token service is supported.
Definition: Platform.php:430
static array $MESSAGE_TYPES
List of supported incoming message types.
Definition: Platform.php:43
getAccessToken()
Get the authorization access token.
Definition: Platform.php:158
string $platformId
Platform ID.
Definition: Platform.php:60
handleAuthenticationRequest()
Process an authentication request.
Definition: Platform.php:661
onLtiStartAssessment()
Process a valid start assessment message.
Definition: Platform.php:621
onInitiateLogin(string &$url, string &$loginHint, string &$ltiMessageHint, array $params)
Save the hint and message parameters when sending an initiate login request.
Definition: Platform.php:563
initialize()
Initialise the platform.
Definition: Platform.php:216
setToolSettings(array $settings=array())
Set Tool Settings.
Definition: Platform.php:397
onError()
Process a response to an invalid message.
Definition: Platform.php:630
string $consumerName
Name of tool consumer (as reported by last tool consumer connection).
Definition: Platform.php:109
string $accessTokenUrl
Access Token service URL.
Definition: Platform.php:95
getFamilyCode()
Get platform family code (as reported by last platform connection).
Definition: Platform.php:309
getTools()
Get an array of defined tools.
Definition: Platform.php:420
handleRequest()
Process an incoming request.
Definition: Platform.php:456
static fromConsumerKey(string $key=null, DataConnector $dataConnector=null, bool $autoEnable=false)
Load the platform from the database by its consumer key.
Definition: Platform.php:496
string $authenticationUrl
Login authentication URL.
Definition: Platform.php:88
object $toolProxy
The tool proxy.
Definition: Platform.php:130
Class to implement the Tool Settings service.
static Tool $defaultTool
Default tool for use with service requests.
Definition: Tool.php:299
const ID_SCOPE_ID_ONLY
Use ID value only.
Definition: Tool.php:51
const LOGLEVEL_DEBUG
Log all messages.
Definition: Util.php:156
static sendForm(string $url, array $params, string $target='')
Generate a web page containing an auto-submitted form of parameters.
Definition: Util.php:466
static logRequest(bool $debugLevel=false)
Log a request received.
Definition: Util.php:375
static int $logLevel
Current logging level.
Definition: Util.php:189
static logError(string $message, bool $showSource=true)
Log an error message.
Definition: Util.php:337
static getRequestParameters()
Return GET and POST request parameters (POST parameters take precedence)
Definition: Util.php:224
getSetting(string $a_keyword, ?string $a_default_value=null)
read one value from settingstable
Definition: class.ilias.php:88
loadPlatform(\ILIAS\LTI\ToolProvider\Platform $platform)
Load platform object.
exit
Definition: login.php:28
$ltiMessageHint
Definition: ltiauth.php:51
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:33
$service
Definition: ltiservices.php:43
$scopes
Definition: ltitoken.php:99
trait ApiHook
Trait to handle API hook registrations.
Definition: ApiHook.php:29
static getApiHook(string $hookName, string $familyCode)
Get the class name for an API hook.
Definition: ApiHook.php:88
static hasConfiguredApiHook(string $hookName, string $familyCode, $sourceObject)
Check if an API hook is registered and configured.
Definition: ApiHook.php:115
static string $ACCESS_TOKEN_SERVICE_HOOK
Access Token service hook name.
Definition: ApiHook.php:63
static string $TOOL_SETTINGS_SERVICE_HOOK
Tool Settings service hook name.
Definition: ApiHook.php:58
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: AccessToken.php:19
array $messageParameters
LTI message parameters.
Definition: System.php:179
ilLTIDataConnector $dataConnector
Data connector object.
Definition: System.php:64
checkMessage()
Verify the required properties of an LTI message.
Definition: System.php:728
bool $enabled
Whether the system instance is enabled to accept connection requests.
Definition: System.php:123
parseMessage()
Parse the message.
Definition: System.php:885
string $key
Consumer key/client ID value.
Definition: System.php:193
addSignature(string $endpoint, $data, string $method='POST', ?string $type=null, ?string $nonce='', ?string $hash=null, ?int $timestamp=null)
Add the signature to an array of message parameters or to a header string.
Definition: System.php:714
doCallback()
Call any callback function for the requested action.
Definition: System.php:1141
int $id
System ID value.
Definition: System.php:186
verifySignature()
Verify the signature of a message.
Definition: System.php:781
array $settings
Setting values (LTI parameters, custom parameters and local parameters).
Definition: System.php:200
$url