So my first question would be: "Why http only? Why not support https?"
Sanity check: XSRF-TOKEN httponly
I'm working on an application that requires that all of my app's cookies be both secure and httponly. For the session cookie that's easy enough but for the xsrf-token it's more difficult. I've updated my VerifyCsrfToken middleware by overriding base classe's addCookieToResponse method and tokensMatch method.
protected function addCookieToResponse($request, $response)
{
$response->headers->setCookie(
new Cookie(
'XSRF-TOKEN',
$request->session()->token(),
time() + 60 * 120,
'/',
null,
true, // Set this to true for secure.
true // Set this to true for httponly.
)
);
return $response;
}
The cookie is being set properly but of course I can't access it in AJAX calls (I'm using AngularJS's $http service in my app.) However the the required information does get included by XHR in the cookie HTTP header. So I'm parsing that string in the request to get the xsrf-token value:
protected function tokensMatch($request)
{
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
$token = $this->encrypter->decrypt($header);
}
// Here's the section I've added. Step 1: Grab the cookie string from the header.
if (! $token && $header = $request->header('cookie')) {
$matchArray = [];
// Step 2: grab the value of the xsrf-token from the cookie string.
if (
preg_match("/XSRF-TOKEN=(.*);/", $header, $matchArray) !== false
&& isset($matchArray[1])
) {
// Step 3: undo the url encoding on the string and then decrypt it.
$token = $this->encrypter->decrypt(urldecode($matchArray[1]));
}
}
// End of section I've added.
return StringUtils::equals($request->session()->token(), $token);
}
From a functional perspective this seems to be working. The XSRF-TOKEN cookie is both httponly and secure, it is getting decrypted accurately and it does match up with the token stored for the session on the server. I'm wondering what people think about using the cookie string in the http header to grab this value. Is there a reason why I shouldn't be using that value? Is there a better way (keeping in mind httponly is a requirement)? Or is this a decent approach?
@DaveBagler yes, making this cookie httponly is pointless and has no benefit. Laravel adds this cookie as a convenience for frameworks like AngularJS that can read and automatically set the X-XSRF-TOKEN header based on the value of this cookie.
You can remove this cookie from the response and use a meta tag (this will require you to add the header value manually using a request interceptor or in run block) or a hidden form field to pass the csrf token back to the server.
Methods are explained here: https://laravel.com/docs/5.2/routing#csrf-protection
Usman.
Please or to participate in this conversation.