Skip to content

Commit

Permalink
Merge pull request #14 from oat-sa/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
ekkinox authored Sep 15, 2021
2 parents 37ad423 + 5f3c42f commit 7a854d7
Show file tree
Hide file tree
Showing 7 changed files with 399 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CHANGELOG
=========

0.4.0
-----

* Added EndAssessment launch message builder
* Updated StartAssessment launch message builder for end_assessment_return claim handling
* Updated documentation

0.3.0
-----

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"require": {
"php": ">=7.2.0",
"ext-json": "*",
"oat-sa/lib-lti1p3-core": "^6.0"
"oat-sa/lib-lti1p3-core": "^6.2"
},
"require-dev": {
"cache/array-adapter": "^1.1",
Expand Down
Binary file modified doc/images/proctoring-workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
106 changes: 106 additions & 0 deletions doc/message/proctoring-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Each step will be detailed below, from both platform and tool perspectives.
- [2 - Tool side: StartProctoring message handling](#2---tool-side-startproctoring-message-handling)
- [3 - Tool side: StartAssessment message generation](#3---tool-side-startassessment-message-generation)
- [4 - Platform side: StartAssessment message handling](#4---platform-side-startassessment-message-handling)
- [5 - Platform side: EndAssessment message generation](#5---platform-side-endassessment-message-generation)
- [6 - Tool side: EndAssessment message handling](#6---tool-side-endassessment-message-handling)

## 1 - Platform side: StartProctoring message generation

Expand Down Expand Up @@ -260,3 +262,107 @@ if (!$result->hasError()) {
```
**Note**: more details about tool originating messages on platform side validation can be found in the [tool originating messages documentation](https://github.com/oat-sa/lib-lti1p3-core/blob/master/doc/message/tool-originating-messages.md#2---platform-side-launch-validation).

## 5 - Platform side: EndAssessment message generation

You can find below required steps to generate an EndAssessment message, needed only if you're acting as a platform and if the tool [indicated the need to send this message](https://www.imsglobal.org/spec/proctoring/v1p0#h.j1m63z4t5l55).

### Create the message

As a platform, you can create a [EndAssessment message](https://www.imsglobal.org/spec/proctoring/v1p0#h.ooq616k28cwm) for a tool within the context of a registration.

Platforms can drive the tool behaviour on proctoring interactions by providing [claims](https://www.imsglobal.org/spec/proctoring/v1p0#h.kg8q94dahtt0) in this message.

You can use the [EndAssessmentLaunchRequestBuilder](../../src/Message/Launch/Builder/EndAssessmentLaunchRequestBuilder.php) to create the message:

```php
<?php

use OAT\Library\Lti1p3Core\Registration\RegistrationRepositoryInterface;
use OAT\Library\Lti1p3Proctoring\Message\Launch\Builder\EndAssessmentLaunchRequestBuilder;

// Create a builder instance
$builder = new EndAssessmentLaunchRequestBuilder();

// Get related registration of the launch
/** @var RegistrationRepositoryInterface $registrationRepository */
$registration = $registrationRepository->find(...);

// Build EndAssessment message
$message = $builder->buildEndAssessmentLaunchRequest(
$registration, // [required] related registration
'loginHint', // [required] login hint that will be used afterwards by the platform to perform authentication
'http://tool.com/end-assessment', // [optional] tool url where to send the EndAssessment message (will use tool default launch url if not provided)
1, // [optional] attempt number (default 1)
null, // [optional] will use the registration default deployment id, but you can pass a specific one
['http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'], // [optional] roles
['myCustomClaim' => 'myCustomValue'] // [optional] supplementary claims if needed
);
```

**Note**: you can also use the `buildEndAssessmentLaunchErrorRequest()` method if you want to notify the tool in an easy way that an error occurred platform side.

### Launch the message

As a result of the build, you get a [LtiMessageInterface](../../src/Message/LtiMessageInterface.php) instance that has to be used in the following ways:

```php
<?php

use OAT\Library\Lti1p3Core\Message\LtiMessageInterface;

/** @var LtiMessageInterface $message */

// Main message properties you can use as you want to offer the launch to the platform users
echo $message->getUrl(); // url of the launch
echo $message->getParameters()->all(); // array of parameters of the launch

// Or use those helpers methods to ease the launch interactions
echo $message->toUrl(); // url with launch parameters as query parameters
echo $message->toHtmlLink('click me'); // HTML link, where href is the output url
echo $message->toHtmlRedirectForm(); // HTML hidden form, with possibility of auto redirection
```

### Implement OpenId Connect launch flow

Like any platform originating message, when the EndAssessment message is launched, an [OIDC flow](https://www.imsglobal.org/spec/security/v1p0/#platform-originating-messages) will start between the tool and the platform.

The underlying core library offers everything you need to securely implement this flow, as documented in the [platform originating messages documentation](https://github.com/oat-sa/lib-lti1p3-core/blob/master/doc/message/platform-originating-messages.md).

## 6 - Tool side: EndAssessment message handling

You can find below required steps to handle a EndAssessment message, needed only if you're acting as a tool.

### Validate the message

As a tool, you'll receive an HTTP request containing the [EndAssessment message](https://www.imsglobal.org/spec/proctoring/v1p0#h.ooq616k28cwm), generated by the platform, received after OIDC flow completion.

You can use the [ToolLaunchValidator](https://github.com/oat-sa/lib-lti1p3-core/blob/master/src/Message/Launch/Validator/ToolLaunchValidator.php) to validate it:

```php
<?php

use OAT\Library\Lti1p3Core\Message\Launch\Validator\Tool\ToolLaunchValidator;
use OAT\Library\Lti1p3Core\Registration\RegistrationRepositoryInterface;
use OAT\Library\Lti1p3Core\Security\Nonce\NonceRepositoryInterface;
use Psr\Http\Message\ServerRequestInterface;

/** @var RegistrationRepositoryInterface $registrationRepository */
$registrationRepository = ...

/** @var NonceRepositoryInterface $nonceRepository */
$nonceRepository = ...

/** @var ServerRequestInterface $request */
$request = ...

// Create the validator
$validator = new ToolLaunchValidator($registrationRepository, $nonceRepository);

// Perform validation
$result = $validator->validatePlatformOriginatingLaunch($request);

if (!$result->hasError()) {
// Your logic to handle the EndAssessment message
}
```
**Note**: more details about platform originating messages on tool side validation can be found in the [platform originating messages documentation](https://github.com/oat-sa/lib-lti1p3-core/blob/master/doc/message/platform-originating-messages.md#4---tool-side-launch-validation).
112 changes: 112 additions & 0 deletions src/Message/Launch/Builder/EndAssessmentLaunchRequestBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2021 (original work) Open Assessment Technologies SA;
*/

declare(strict_types=1);

namespace OAT\Library\Lti1p3Proctoring\Message\Launch\Builder;

use OAT\Library\Lti1p3Core\Exception\LtiException;
use OAT\Library\Lti1p3Core\Exception\LtiExceptionInterface;
use OAT\Library\Lti1p3Core\Message\Launch\Builder\PlatformOriginatingLaunchBuilder;
use OAT\Library\Lti1p3Core\Message\LtiMessageInterface;
use OAT\Library\Lti1p3Core\Message\Payload\LtiMessagePayloadInterface;
use OAT\Library\Lti1p3Core\Registration\RegistrationInterface;
use Throwable;

/**
* @see https://www.imsglobal.org/spec/proctoring/v1p0#h.ooq616k28cwm
*/
class EndAssessmentLaunchRequestBuilder extends PlatformOriginatingLaunchBuilder
{
/**
* @throws LtiExceptionInterface
*/
public function buildEndAssessmentLaunchRequest(
RegistrationInterface $registration,
string $loginHint,
string $endAssessmentUrl = null,
int $attemptNumber = 1,
string $deploymentId = null,
array $roles = ['http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'],
array $optionalClaims = []
): LtiMessageInterface {
try {
$this->builder
->reset()
->withClaim(LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_ATTEMPT_NUMBER, $attemptNumber);

$launchUrl = $endAssessmentUrl ?? $registration->getTool()->getLaunchUrl();

if (null === $launchUrl) {
throw new LtiException('Neither end assessment url nor tool default url were presented');
}

return $this->buildPlatformOriginatingLaunch(
$registration,
LtiMessageInterface::LTI_MESSAGE_TYPE_END_ASSESSMENT,
$launchUrl,
$loginHint,
$deploymentId,
$roles,
$optionalClaims
);

} catch (LtiExceptionInterface $exception) {
throw $exception;
} catch (Throwable $exception) {
throw new LtiException(
sprintf('Cannot create end assessment launch request: %s', $exception->getMessage()),
$exception->getCode(),
$exception
);
}
}

/**
* @throws LtiExceptionInterface
*/
public function buildEndAssessmentLaunchErrorRequest(
RegistrationInterface $registration,
string $loginHint,
string $errorMessage,
string $errorLog = null,
string $endAssessmentUrl = null,
int $attemptNumber = 1,
string $deploymentId = null,
array $roles = ['http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'],
array $optionalClaims = []
): LtiMessageInterface {
return $this->buildEndAssessmentLaunchRequest(
$registration,
$loginHint,
$endAssessmentUrl,
$attemptNumber,
$deploymentId,
$roles,
array_merge(
$optionalClaims,
[
LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_ERROR_MESSAGE => $errorMessage,
LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_ERROR_LOG => $errorLog ?? $errorMessage,
]
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ public function buildStartAssessmentLaunchRequest(
string $sessionData,
int $attemptNumber,
string $deploymentId = null,
array $optionalClaims = []
array $optionalClaims = [],
bool $endAssessmentReturn = false
): LtiMessageInterface {
try {
$this->builder
->withClaim($resourceLinkClaim)
->withClaim(LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_SESSION_DATA, $sessionData)
->withClaim(LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_ATTEMPT_NUMBER, $attemptNumber);
->withClaim(LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_ATTEMPT_NUMBER, $attemptNumber)
->withClaim(LtiMessagePayloadInterface::CLAIM_LTI_PROCTORING_END_ASSESSMENT_RETURN, $endAssessmentReturn);

return $this->buildToolOriginatingLaunch(
$registration,
Expand Down Expand Up @@ -81,7 +83,8 @@ public function buildStartAssessmentLaunchRequestFromPayload(
LtiMessagePayloadInterface $payload,
RegistrationInterface $registration,
string $deploymentId = null,
array $optionalClaims = []
array $optionalClaims = [],
bool $endAssessmentReturn = false
): LtiMessageInterface {
try {

Expand Down Expand Up @@ -116,7 +119,8 @@ public function buildStartAssessmentLaunchRequestFromPayload(
$sessionData,
$attemptNumber,
$deploymentId,
$optionalClaims
$optionalClaims,
$endAssessmentReturn
);

} catch (LtiExceptionInterface $exception) {
Expand Down
Loading

0 comments on commit 7a854d7

Please sign in to comment.