Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/lti/LTI_Message_Launch.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,19 @@ public static function from_cache($launch_id, Database $database, Cache $cache =
* Validates all aspects of an incoming LTI message launch and caches the launch if successful.
*
* @param array|string $request An array of post request parameters. If not set will default to $_POST.
* @param boolean $insecurelyBypassStateValidation If true, the caller is responsible for securing against CSRF.
*
* @throws LTI_Exception Will throw an LTI_Exception if validation fails.
* @return LTI_Message_Launch Will return $this if validation is successful.
*/
public function validate(array $request = null) {
public function validate(array $request = null, $insecurelyBypassStateValidation = false) {

if ($request === null) {
$request = $_POST;
}
$this->request = $request;

return $this->validate_state()
return $this->validate_state($insecurelyBypassStateValidation)
->validate_jwt_format()
->validate_nonce()
->validate_registration()
Expand Down Expand Up @@ -242,7 +243,13 @@ private function cache_launch_data() {
return $this;
}

private function validate_state() {
/**
* @param boolean $insecurelyBypassStateValidation If true, the caller is responsible for securing against CSRF.
*/
private function validate_state($insecurelyBypassStateValidation = false) {
if ($insecurelyBypassStateValidation) {
return $this;
}
// Check State for OIDC.
$expectedState = $this->cookie->get_cookie('lti1p3_' . $this->request['state']);
if (empty($expectedState) || $expectedState !== $this->request['state']) {
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/LTI_Message_Launch_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ public function testValidateStateWithInvalidStateThrowsException()
)->validate();
}

public function testValidateStateWithInvalidStateThrowsNoStateNotFoundExceptionIfUserBypassesStateValidation()
{
$this->setExpectedException(LTI_JWT_Exception::class, 'Missing id_token');
/** @var Cookie|\PHPUnit_Framework_MockObject_MockObject $cookie */
$cookie = $this->getMockBuilder(Cookie::class)
->setMethods(['get_cookie'])
->getMock();

$cookie->expects($this->never())->method('get_cookie');

LTI_Message_Launch::newInstance(
new DummyDatabase(),
null,
$cookie
)->validate(null, true);
}

public function testValidateState()
{
$state = uniqid();
Expand Down