Accept CSRF token in request body as well

This commit is contained in:
Franz Liedke 2019-06-12 22:14:36 +02:00
parent 5d64056e89
commit 7f7484e790
No known key found for this signature in database
GPG Key ID: 9A0231A879B055F4
2 changed files with 62 additions and 2 deletions

View File

@ -39,7 +39,8 @@ class CheckCsrfToken implements Middleware
private function tokensMatch(Request $request): bool
{
$expected = (string) $request->getAttribute('session')->token();
$provided = $request->getHeaderLine('X-CSRF-Token'); // TODO: Use form field, if provided
$provided = $request->getParsedBody()['csrfToken'] ??
$request->getHeaderLine('X-CSRF-Token');
return hash_equals($expected, $provided);
}

View File

@ -97,7 +97,7 @@ class RequireCsrfTokenTest extends TestCase
/**
* @test
*/
public function cookie_auth_succeeds_with_csrf_token()
public function cookie_auth_succeeds_with_csrf_token_in_header()
{
$initial = $this->server->handle(
(new ServerRequest([], [], '/', 'GET'))
@ -155,6 +155,65 @@ class RequireCsrfTokenTest extends TestCase
);
}
/**
* @test
*/
public function cookie_auth_succeeds_with_csrf_token_in_body()
{
$initial = $this->server->handle(
(new ServerRequest([], [], '/', 'GET'))
);
$token = $initial->getHeaderLine('X-CSRF-Token');
$cookies = array_reduce(
$initial->getHeader('Set-Cookie'),
function ($memo, $setCookieString) {
$setCookie = SetCookie::fromSetCookieString($setCookieString);
$memo[$setCookie->getName()] = $setCookie->getValue();
return $memo;
},
[]
);
$auth = $this->server->handle(
(new ServerRequest([], [], '/login', 'POST'))
->withBody(new CallbackStream(function () use ($token) {
return '{"identification": "admin", "password": "password", "csrfToken": "'.$token.'"}';
}))
->withCookieParams($cookies)
->withHeader('Content-Type', 'application/json')
);
$token = $auth->getHeaderLine('X-CSRF-Token');
$cookies = array_reduce(
$auth->getHeader('Set-Cookie'),
function ($memo, $setCookieString) {
$setCookie = SetCookie::fromSetCookieString($setCookieString);
$memo[$setCookie->getName()] = $setCookie->getValue();
return $memo;
},
[]
);
$response = $this->server->handle(
(new ServerRequest([], [], '/api/settings', 'POST'))
->withBody(new CallbackStream(function () use ($token) {
return '{"mail_driver": "log", "csrfToken": "'.$token.'"}';
}))
->withCookieParams($cookies)
->withHeader('Content-Type', 'application/json')
);
// Successful response?
$this->assertEquals(204, $response->getStatusCode());
// Was the setting actually changed in the database?
$this->assertEquals(
'log',
$this->database()->table('settings')->where('key', 'mail_driver')->first()->value
);
}
/**
* @test
*/