Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

axtg's avatar
Level 5

Sanctum throws "Session store not set on request"

I've been developing a SPA with Sanctum locally, which works. Registration, verification and login. Now I moved to production, and registration and verification still work, but login throws:

Session store not set on request.
"/home/***/webapps/bwf-app/vendor/laravel/framework/src/Illuminate/Http/Request.php"

And that's the bit that confuses me. The get('sanctum/csrf-cookie') sets the cookie and apparently sets it correctly for the post to /api/v1/register to work. But then if I login, I get the error 500. What am I missing?

  • Cors is set to 'api/*'
  • Session driver is set to cookie
  • Session domain is set to '.domain'
  • Sanctum domain is set to a comma-delimited list
0 likes
28 replies
Stetzone's avatar

I was able to resolve this by adding \Illuminate\Session\Middleware\StartSession::class to the api middleware group in Kernel.php

13 likes
dcon138's avatar

To those reading this comment - please read my answer below about overriding the EnsureFrontendRequestsAreStateful middleware - simply adding \Illuminate\Session\Middleware\StartSession::class may make the error message go away, but it is NOT the correct solution to this issue, and may be introducing bugs or security vulnerabilities to your application.

3 likes
rayasabari's avatar

@Stetzon thanks it's works, but I still curious because the last three days it still works without adding that class, just suddenly show the error even though I have no changes in the kernel.php

UPDATE: solved, it's because I access the domain with 'www'

anthonyderek47's avatar

@Stetzon Hello there, I just went through the hassle of creating an account here just to say a massive thank you to you for sharing this solution @stetzon. I hope you're doing well and have an amazing day. Thanks again and God bless! ❤️🙌

khalilm's avatar

I also had this issue with my SPA but what didn't make sense to me is that I could log into my production no issues, but no one else could. But implementing @stetzon 's suggestion fixed the problem.

martinbean's avatar

Just adding the session middleware to your API routes is not not the solution. It’s omitted for a reason: API routes should be stateless (i.e. not rely on state between the server and the client). This includes sessions and cookies.

3 likes
khalilm's avatar

I am not sure I understand. In documentation we are told to add to the Kernel.php file this class: \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,

The documentation also talks about stateful configuration. For token based api's I agree but for Sanctum? Maybe I don't understand all the implications but what IS the solution then?

dcon138's avatar

I have just had a similar issue when running phpunit tests on an API secured by Sanctum's stateful (SPA) approach.

The issue is that in \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful, the actions for this middleware are only applied if the function fromFrontend() returns true.

To solve this issue, simply investigate and understand why fromFrontend()returns false in your case, and rectify this. In my case, i didn't need to dig too deep into this function to see that it uses request headers and such to determine if the request came from your front end, and these were not present since my requests were being sent from phpunit tests. As such, the solution in my case was to extend the middleware, so that if we were running from a phpunit test, fromFrontend() returned true, which I achieved by the following:

//app/http/middleware/EnsureFrontendRequestsAreStateful<dot>php
<?php

namespace App\Http\Middleware;

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful as BaseSanctumMiddleware;

class EnsureFrontendRequestsAreStateful extends BaseSanctumMiddleware
{
    /**
     * Determines if we are running from a phpunit test
     *
     * @return bool
     */
    protected static function isEnvTesting(): bool
    {
        return config('app<dot>env') === 'testing';
    }

    /**
     * Override parent method to make it look like request is from front end if we are running from a phpunit test
     *
     * @inheritDoc
     */
    public static function fromFrontend($request): bool
    {
        return static::isEnvTesting() ? true : parent::fromFrontend($request);
    }
}

With this file created, I simply modified the api middleware group in app/Http/Kernel to use \App\Http\Middleware\EnsureFrontendRequestsAreStateful::class instead of \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class.

Obviously you have a slightly different use case, and you will need to investigate why fromFrontend() is returning false for you, but if for example the issue is only present in certain environments, it may be caused by your configuration of front end domains for sanctum amgonst other things

Note: Please replace <dot> with a literal dot/period character wherever you see it in my comment - laracasts was interpreting these as a link and not allowing me to post since i signed up to this account today :)

Edit: Wanted to add to the above, that it is important to use this approach rather than just manually adding the StartSession middleware as suggested above. As you can see from the handle function in Sanctum's EnsureFrontendRequestsAreStateful class, it runs a pipeline of a few other middlewares on top of just StartSession, including EncryptCookies. There is a possibility that if you directly include StartSession instead of leveraging the full functionality provided by EnsureFrontendRequestsAreStateful, you may be introducing security vulnerabilities

15 likes
khalilm's avatar

Thank you for your thorough explanation. I decided to take your advice and looked deeper into the code and you are right, it is failing at the domain when there is a www. in the URL.

So if my domain is https://xxx.yyy.com it will work. If it is https://www.xxx.yyy.com it will not. To be honest, I was not even 100% sure that is a valid URL as it looks so wrong to me but it takes me to the site.

By adding a $domain = Str::replaceFirst('www.', '', $domain); to the public static function fromFrontend($request) function it works. So I will override the code like you did and post this as a sanctum issue.

Thanks again for taking the time to make a detailed post.

1 like
andy.parinas's avatar

Got this error as well. It was so weird. My application was running perfectly until, I have to move the repo then clone the new repo.

I had to do a composer update, since composer dump-autoload has been throwing error. off course it did update the packages.

After that, when I tessted the application, it keeps throwing that error in the laravel.log. My SPA frontend says I am unauthenticated even after clearing all my cache and coockies and then loggin in.

Have to put the StartSession in the API middleware and it works.

axtg's avatar
axtg
OP
Best Answer
Level 5

I revisited this recently and tested both stateless and stateful using Insomnia (Postman). So I added EnsureFrontendRequestsAreStateful without change, set the sanctum config file and cors config file as per documentation.

Next I created a single api.php route (/user > return auth()->user();) with auth:sanctum middleware applied.

Then in Insomnia I:

Stateless

  1. Request the /user route with a Bearer token in the request.

Stateful

  1. Request /sanctum/csrf-cookie and store the cookie in my Insomnia environment (cookie jar)
  2. Request /login with x-xsrf-token (cookie from step 1) and Referer: http://localhost:8000 in the Request header and user credentials in the body (form-data). I use Laravel Fortify as auth controller.
  3. Request the /user route with the x-xsrf-token and Referer in the Request header

In both cases I get the user associated with the token.

That to me solves my original challenge. Whether code has changed, or my understanding of stateless vs stateful has improved, you should now be able to get it working.

5 likes
mijnnaamisramon's avatar

Don't forget to add the correct .env variables in your production environment (like Laravel Forge). I had the same problem and then I remembered.... in the .env file, add SANCTUM_STATEFUL_DOMAIN= it worked for me then!

1 like
ITwrx's avatar

@mijnnaamisramon Thanks. My problem was that i had left the APP_URL .env variable set to the dev value. Setting it to "https://superapp.com" and now the session store IS set on the request. No mods to app necessary.

fcode's avatar

I am currently having the same issue. I am using Laravel Homestead for my development environment. I tried following this video Laravel Sanctum (Airlock) with Postman but it did not work for me.

My setting

API_URL=http://api.myapi.test
SESSION_DRIVER=cookie
SESSION_DOMAIN=.myapi.test
SANCTUM_STATEFUL_DOMAINS=myapi.test

I tested with a nuxt frontend app and it worked, however, doing the same in Postman throws a Session store not set on request error.

Anyone with ideas on how to deal with this. Almost all the examples I have seen uses localhost. Any way to achieve this using a real URL with Postman?

fcode's avatar

Okay, guys. I finally figured the problem. While the above video did not add a Referer in the header for the login route, adding it solved the issue with Postman. Thanks, @axtg for mentioning it in your latest reply.

2 likes
dvienne's avatar

I have the same issue but I'm sure it's almost nothing in config... but I still can't get it...

Everything is working on dev env with this:

  • API located at localhost:8100
  • Frontend located at localhost:8080

Dev .env:

...
APP_URL=http : // localhost:8100
APP_PORT=8100
...
SANCTUM_STATEFUL_DOMAINS=localhost:8080
SESSION_DOMAIN=localhost
...
SESSION_DRIVER=file

On production, calling the the csrf route on login from the frontend throws a HTPP 500 -> "Session store not set on request"

  • My Laravel API is located at api dot vienne dot dev
  • My frontend is located at www dot vienne dot dev

Prod .env:

...
APP_URL=https://api dot vienne dot dev
...
SANCTUM_STATEFUL_DOMAINS=www dot vienne dot dev,api dot vienne dot dev
SESSION_DOMAIN=dot vienne dot dev
...
SESSION_DRIVER=cookie

(Some URLs had to be changed since I am not able to post links here for the moment)

What did I miss?!?

Thx a lot for the support

dvienne's avatar

Finally working with this .env

...
APP_URL=https://api dot vienne dot dev
...
SANCTUM_STATEFUL_DOMAINS=www dot vienne dot dev,api dot vienne dot dev
SESSION_DOMAIN=dot vienne dot dev
...
SESSION_DRIVER=file
...

Not sure why cookie is not working ... should be bounded to DNS

axtg's avatar
Level 5

If you're going stateless, no cookies are stored, that's a browser thing.

panthro's avatar

For those of you having issues with tests and this error, just do....

$this->withHeaders([
     'referer' => env('SANCTUM_STATEFUL_DOMAINS'),
]);
3 likes
devtiagofranca's avatar

Source: https://stackoverflow.com/a/35393714

/*
If adding your routes inside the web middleware doesn't work for any reason then try adding this to $middleware into Kernel.php
*/
# NOTE API route has no session by default. May be you can add this middleware in 'api' $middlewareGroups
protected $middleware = [
        //...
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
5 likes
toheeb's avatar

If you still have this issue, you don't need to add anything to your api middleware, what you need to do is to add "referer" to your header request without the "http" or "https" part and " \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class" will do the job for you.

Please or to participate in this conversation.