Search code examples
laravellaravel-sanctumlaravel-11

Session store not set on request Laravel 11


I'm attempting to implement basic authentication functionality for testing purposes. I'm testing via Postman, so before logging in, I make a GET request to /sanctum/csrf-cookie. After that, I hit the /login endpoint and am able to receive data (if this part $request->session()->regenerate(); is commented out). However, if I try to access a protected route, I receive an error. Despite following the documentation closely, I'm encountering an issue when a user attempts to sign in. I receive an error when $request->session()->regenerate(); this is not commented out:

"message": "Session store not set on request."

Here's my bootstrap/app.php:

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        using: function () {
            Route::middleware('api')
                ->prefix('api')
                ->group(function () {
                    // routes/api.php is not included here
                    require base_path('routes/Api/V1/Auth/routes.php');
                });
        },
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->statefulApi();
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

Here's my login:

public function login(object $request)
    {
        // Validate user credentials
        if (!Auth::attempt($request->only(['username', 'password']))) {
            return $this->failedRequest('', 'Invalid email address or password', 400);
        }

        // Regenerate the user's session to prevent session fixation
        $request->session()->regenerate();

        // Sign in user
        Auth::login(Auth::user());

        // Return data
        return $this->successfullRequest(Auth::user(), 'User successfully logged in', 200);
    }

My routes:

Route::group(['prefix' => 'v1/auth'], function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);
    Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
});

If I remove this part, I basically receive Unauthenticated message when I try to hit .../logout

$request->session()->regenerate();

sanctum.php -> stateful:

'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_URL') ? ',' . parse_url(env('FRONTEND_URL'), PHP_URL_HOST) : ''))),

my env file:

APP_URL=http://localhost:5000
FRONTEND_URL=http://localhost:3000

Solution

  • When testing your sanctum SPA authentication via Postman, make sure to include either the Referer or Origin header. Additionally, make sure the domain in the provided header matches a domain provided in the sanctum.stateful config value (e.g. the domain used by your APP_URL .env variable).

    These conditions are required for the statefulApi() middleware to enable the frontend middleware (including sessions).

    You can see the code here for determining if it is a frontend request that enables the frontend middleware.