Reputation: 1229
I installed L8, Sanctum, and Fortify for authentication. I was able to /login
(used a Pre-request Script
to set the X-XSRF-TOKEN
). I even get the /api/user
successfully. But when I do /logout
, I get "CSRF Token Mismatch" error in Postman. My settings in files are as below:
.env
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:8000
cors.php
'paths' => ['api/*', 'login', 'logout', 'register', 'sanctum/csrf-cookie']
fortify.php
'views' => false
/app/Http/Kernel.php
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
I haven't used HasApiTokens
trait in User
model since this is cookie-based authentication.
In Postman, I am using the below headers for the /logout
route:
Accept:application/json
Referer:localhost:8000
X-XSRF-TOKEN:{{xsrf-token}}
and I am making a POST
request to http://localhost:8000/logout
. Why I am getting "CSRF Token Mismatch" error?
Upvotes: 2
Views: 5244
Reputation: 413
Vendor packages also use the .env
(SESSION_DOMAIN
and SANCTUM_STATEFUL_DOMAINS
), so sometimes there is weird behavior.
Remove these from the .env
if present
# SESSION_DOMAIN=
# SANCTUM_STATEFUL_DOMAINS=
Add these to the .env
. Make sure the URL is in full (scheme, domain and port (when in development))
APP_URL=http://localhost:8000
FRONTEND_URLS=http://localhost:5173,http://localhost:5174,http://localhost:5175,http://localhost:5176
Add these to config/cors.php
return [
'paths' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => explode(',', env('FRONTEND_URLS')),
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
]
Add these to config/sanctum.php
return [
...
'stateful' => explode(
',',
env(
'SANCTUM_STATEFUL_DOMAINS',
sprintf(
'%s%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : '',
env('FRONTEND_URLS')
? implode(
',',
array_map(function ($url) {
return parse_url($url, PHP_URL_HOST);
}, explode(',', env('FRONTEND_URLS')))
)
: ''
)
)
),
...
]
Make sure this line is present in kernel.php
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // <---
...
],
];
Then don't forget to clear the cache both in development and server.
php artisan config:clear
php artisan route:clear
php artisan cache:clear
Upvotes: 0
Reputation: 53
In your App\Http\Middleware\VerifyCsrfToken
middleware, add /api/logout
to the $except
array:
protected $except = [
'/api/logout'
];
Upvotes: 1
Reputation: 324
I'm not sure if you ever solved this, but if not I've just had to solve the very same issue.
The reason it's failing is because the CSRF token is updated for each request so you need to add post-request script to your login request (and any other requests you make).
e.g. you can add a script to the Tests section of the request:
postman.setEnvironmentVariable("xsrf-token", postman.getResponseCookie("XSRF-TOKEN").value);
tests["CSRF token updated"] = true;
The second line is there to ensure the script doesn't report a fail every time.
I also found that it might be necessary to use decodeURIComponent()
on the token value.
Upvotes: 3