I have my API that run on this url: https://example.com
, and my vue.js app which runs on this: https://app.example.com
. So I configured as the following the .env
:
SESSION_DOMAIN=.example.com
SANCTUM_STATEFUL_DOMAINS=https://app.example.com
the axios configuration contains the following:
import axios from ‘axios’
const server = axios.create({
baseURL: 'https://example.com'
})
server.defaults.withCredentials = true
server.defaults.withXSRFToken = true
within the file sanctum.php
I setted as guard api
:
'guard' => ['api']
and within kernel.php
I did:
'api' => [
LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class,
IlluminateRoutingMiddlewareThrottleRequests::class.':api',
IlluminateRoutingMiddlewareSubstituteBindings::class,
],
I also added:
IlluminateSessionMiddlewareStartSession::class,
within $middleware
group.
The application flow is the following: when I press the login button I sent a request to:
/sanctum/csrf-cookie
which return 204 and set the cookie, then I perform the login request that return 204, so far everything seems good. At the end, I try to sent a GET request to /user
that is protected as the following:
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', [UserController::class, 'index']);
});
but I get unauthorized
. I spend the whole day try to figur out, tried a lot of solutions but no one has worked.
I get the same result on postman.
UPDATE
config/sanctum.php
<?php
use LaravelSanctumSanctum;
return [
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort()
))),
'guard' => ['web'],
'expiration' => null,
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
'middleware' => [
'authenticate_session' => LaravelSanctumHttpMiddlewareAuthenticateSession::class,
'encrypt_cookies' => AppHttpMiddlewareEncryptCookies::class,
'verify_csrf_token' => AppHttpMiddlewareVerifyCsrfToken::class,
],
];
config.cors.php
<?php
return [
'paths' => [
'api/*',
'login',
'logout',
'register',
'sanctum/csrf-cookie'
],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
config/session.php
<?php
use IlluminateSupportStr;
return [
'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'connection' => env('SESSION_CONNECTION'),
'table' => 'sessions',
'store' => env('SESSION_STORE'),
'lottery' => [2, 100],
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
'path' => '/',
'domain' => env('SESSION_DOMAIN'),
'secure' => env('SESSION_SECURE_COOKIE'),
'http_only' => true,
'same_site' => 'lax',
'partitioned' => false,
];
config/auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => AppModelsUser::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_reset_tokens',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
.env
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
SESSION_DOMAIN=.example.com
SANCTUM_STATEFUL_DOMAINS=https://app.example.com
Notice that both domains are https registered with letsencrypt, I just hided them for privacy reason.
2
Answers
I think you missed setting the
supports_credentials
option totrue
inconfig/cors.php
I can feel your pain, I struggled with it at my time.
I’m using the same practice for my web app. I achieved it with the same steps.
I notice one difference in env. I use:
☝️ Use "." and remove
https://