Search code examples
laravelsingle-page-applicationlaravel-8laravel-sanctum

Laravel Sanctum throws 401 Unauthenticated when using Postman


I have problem with Laravel Sanctum. My dev environment is located in subdomain. All my API routes are prefixed with /api. Here are my settings:

.env

APP_URL=https://kanban.forgecraft.pl
SESSION_DRIVER=cookie
SESSION_DOMAIN=.kanban.forgecraft.pl
SANCTUM_STATEFUL_DOMAINS=kanban.forgecraft.pl,localhost,127.0.0.1

routes/api.php

Route::namespace('API')->group(function () {
  Route::post('/login', 'UserController@login');
  Route::post('/register', 'UserController@register');
  Route::get('/logout', 'UserController@logout');
  Route::group(['prefix' => '/profile', 'middleware' => 'auth:sanctum'], function () {
    Route::get('/', function () {
        return response()->json(['message' => 'Profile works'], 200);;
    });
  });
});

config/sanctum.php

return [
    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS')),
    'expiration' => null,
    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],
];

config/cors.php

return [
    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,

];

App/Http/Kernel.php

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

Postman:

Firstly I call api/login. Login route returns status 200, XSRF token cookie, and success message. Then I try to call profile route which has to simply return a message. I use pre-request script to get token. [![postman-setting][1]][1]

Pre-request postman script:

pm.sendRequest({
    url: 'https://kanban.forgecraft.pl/sanctum/csrf-cookie',
    method: 'GET'
}, function (error, response, { cookies }) {
    if (!error) {
        pm.environment.set('xsrf-token', cookies.get('XSRF-TOKEN'))
    }
})

It would mean a world to me to help me understand what I've done wrongly. Thank you for any help. [1]: https://i.sstatic.net/mQPQv.png


Solution

  • I dont't know if this tip helps your or not! But I had same problem with sanctum SPA usage.
    I added XSRF-TOKEN & laravel_session cookies and even X-XSRF-TOKEN header, but the server threw 401 error code!
    That was really weird behavior!

    Finally i found the reason on the internet:

    The reason this isn't working is that Sanctum is denying the authenticated request based on the referrer.
    If you're interested in diving into some Sanctum code and figuring out why, open up the EnsureFrontendRequestsAreStateful middleware and check out the fromFrontend method that all requests are piped through.

    Ok! I'm not going to deeply walk through laravel files.Ii just added Referer: [my-url] to the header and problem solved easily.