I think we change how to get csrf token to support Axios send csrf via cookie (X-XSRF-TOKEN)
I agree and to clarify, Axios and other Http clients like Angulars HttpClientModule automatically check for the XSRF-TOKEN cookie and set the X-XSRF-TOKEN header on outgoing requests. When Passport authenticates a request it checks that the CSRF token was sent with the request and that it matches the one in the decoded token but it fails to check for the XSRF Token, decode it and check its validity.
To solve the problem I have extended Passports TokenGuard with the following minor changes:
protected function validCsrf($token, $request)
{
$isCsrf = false;
$isXsrf = false;
if($csrf = $token['csrf']) {
$isCsrf = hash_equals(
$token['csrf'], (string) $request->header('X-CSRF-TOKEN')
);
if($request->hasHeader('X-XSRF-TOKEN')) {
$isXsrf = $this->encrypter->decrypt($request->header('X-XSRF-TOKEN')) === $csrf;
}
}
return $isCsrf || $isXsrf;
}
@GJordan904 Any chance of making this a pull request? I've run in to this issue too.
Hmm yeah we should be able to match the behavior of the getTokenFromRequest on the VerifyCsrfToken middleware. I'll mark this as a feature request. Feel free to send in a PR to the master branch.
I have written a middleware as my temporary solution.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Cookie\Middleware\EncryptCookies;
class AddCsrfHeader
{
protected $encrypter;
public function __construct(Encrypter $encrypter)
{
$this->encrypter = $encrypter;
}
public function handle($request, Closure $next)
{
if ($header = $request->header('X-XSRF-TOKEN')) {
$token = $this->encrypter->decrypt($header, static::serialized());
$request->headers->set('X-CSRF-TOKEN', $token);
}
return $next($request);
}
public static function serialized()
{
return EncryptCookies::serialized('XSRF-TOKEN');
}
}
Add this middleware to api middleware group
'api' => [
'throttle:60,1',
'bindings',
\App\Http\Middleware\AddCsrfHeader::class,
]
Make its priority higher than authenticate
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\AddCsrfHeader::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
Done!
This has actually already been added in https://github.com/laravel/passport/pull/1069 it seems.
Most helpful comment
@GJordan904 Any chance of making this a pull request? I've run in to this issue too.