Skip to content

Add ability to bypass state validation, for Platform Storage use-case #7

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
@@ -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()
@@ -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']) {
17 changes: 17 additions & 0 deletions tests/unit/LTI_Message_Launch_Test.php
Original file line number Diff line number Diff line change
@@ -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();