how does your api know which session it is? are you sending the sanctum token or cookie?
Why am I getting a 419 response from a Laravel 8 CsrfMiddleware protected end point?
I've recently created a new Laravel 8 project following the instructions at the Laravel 8 . x sanctum docs page.
Now, according to this guide, CSRF protection should be used, meaning a call to <app_url>/sanctum/csrf-cookie, which will return an encrypted XSRF-TOKEN cookie . The value of this cookie should then be used to set the X-XSRF-TOKEN request header before every request .
My situation: I'm running Laravel locally in a Docker container and intend to use it as an API only; that is, I will have a Vue SPA talking to my Laravel backend. But for now, I'm testing the API using Insomnia. I expect this to work, it is essentially no different from an SPA .
I have one test route that is, by default, protected by CSRF middleware because it's in the api.php file:
Route::prefix('v1')->group(function () {
/**
* get the health of the endpoint,
* can be used to see if API is up and running
*/
Route::post('health', function (Request $request) {
return ['healthy' => true];
});˜
}
I can successfully call the /sanctum/csrf-cookie endpoint and receive the XSRF-COOKIE, so far so good. When I attempt to call the api/v1/health endpoint, I always get a 419 response.
A few relevant settings:
.env
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
SESSION_LIFETIME=480
cors.php
'paths' => ['*'], // ['api/*']
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => ['*'],
'max_age' => 0,
'supports_credentials' => true,
sanctum.php
'stateful' => explode(',', env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:80,localhost:3000,localhost:8080,localhost:8085,127.0.0.1,127.0.0.1:8000,127.0.0.1:8085,::1'
)),
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
I've tried:
- Disabling encryption of cookies in all relevant files
- Entirely omitting the session domain from
.env(so it becomes null insession.php) - Setting session domain to empty (SESSION_DOMAIN=) in
.env - Setting X-CSRF-TOKEN header instead of X-XSRF-TOKEN header
Nothing seems to have any effect. Relevant request headers for the api/v1/health endpoint:
X-XSRF-TOKEN=<XSRF-TOKEN-COOKIE-VALUE>
Accept=application/json
Stack trace:
{
"message": "CSRF token mismatch.",
"exception": "Symfony\Component\HttpKernel\Exception\HttpException",
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
"line": 372,
"trace": [
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
"line": 317,
"function": "prepareException",
"class": "Illuminate\Foundation\Exceptions\Handler",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
"line": 51,
"function": "render",
"class": "Illuminate\Foundation\Exceptions\Handler",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 172,
"function": "handleException",
"class": "Illuminate\Routing\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php",
"line": 121,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php",
"line": 63,
"function": "handleStatefulRequest",
"class": "Illuminate\Session\Middleware\StartSession",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Session\Middleware\StartSession",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php",
"line": 37,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php",
"line": 67,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Cookie\Middleware\EncryptCookies",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/sanctum/src/Http/Middleware/EnsureFrontendRequestsAreStateful.php",
"line": 26,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 149,
"function": "Laravel\Sanctum\Http\Middleware\{closure}",
"class": "Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 103,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/sanctum/src/Http/Middleware/EnsureFrontendRequestsAreStateful.php",
"line": 34,
"function": "then",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 103,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
"line": 695,
"function": "then",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
"line": 670,
"function": "runRouteWithinStack",
"class": "Illuminate\Routing\Router",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
"line": 636,
"function": "runRoute",
"class": "Illuminate\Routing\Router",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
"line": 625,
"function": "dispatchToRoute",
"class": "Illuminate\Routing\Router",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
"line": 166,
"function": "dispatch",
"class": "Illuminate\Routing\Router",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 128,
"function": "Illuminate\Foundation\Http\{closure}",
"class": "Illuminate\Foundation\Http\Kernel",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
"line": 21,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Foundation\Http\Middleware\TransformsRequest",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
"line": 21,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Foundation\Http\Middleware\TransformsRequest",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
"line": 27,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Foundation\Http\Middleware\ValidatePostSize",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php",
"line": 86,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance",
"type": "->"
},
{
"file": "/var/www/vendor/fruitcake/laravel-cors/src/HandleCors.php",
"line": 57,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Fruitcake\Cors\HandleCors",
"type": "->"
},
{
"file": "/var/www/vendor/fideloper/proxy/src/TrustProxies.php",
"line": 57,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Fideloper\Proxy\TrustProxies",
"type": "->"
},
{
"file": "/var/www/vendor/spatie/laravel-http-logger/src/Middlewares/HttpLogger.php",
"line": 28,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 167,
"function": "handle",
"class": "Spatie\HttpLogger\Middlewares\HttpLogger",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 103,
"function": "Illuminate\Pipeline\{closure}",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
"line": 141,
"function": "then",
"class": "Illuminate\Pipeline\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
"line": 110,
"function": "sendRequestThroughRouter",
"class": "Illuminate\Foundation\Http\Kernel",
"type": "->"
},
{
"file": "/var/www/public/index.php",
"line": 52,
"function": "handle",
"class": "Illuminate\Foundation\Http\Kernel",
"type": "->"
}
]
}
Any idea what is going on here?
Please or to participate in this conversation.