At some point all the different configuration combos got mixed up and overwhelming but it seems "I tamed the horse". So what I got..
Let's get started
Overall
- This example is based on local environment, replicating production domain structure
- Example is based on Lando, changing every
example.lndo.site to your TLD should work
- Both Laravel API and NUXT front-end are on a subdomain of the main TLD
- Laravel API is served locally with Lando, accessable directly from
http://api.example.lndo.site
- SPA (nuxtjs) is server locally with Lando, accessable directly from
http://admin.example.lndo.site
- Using Laravel Sanctum for CSRF handling (
/sanctum/csrf-token)
- Using Laravel Fortify (with it's provided routes) for main login routes
- Using custom controller for "two-part" (2FA logic) login - that must support cookie vars throughout multiple requests
- Don't forget to
php artisan route:cache after doing changes to Laravel routes - I must have burned ~16 hours of debugging last week for not doing it (knowing it now)...
Laravel
Important configuration
// .env
APP_URL='https://api.example.lndo.site'
FRONTEND_URL='https://admin.example.lndo.site'
SANCTUM_STATEFUL_DOMAINS='*.example.lndo.site'
SESSION_DRIVER=cookie
SESSION_DOMAIN='.example.lndo.site'
SESSION_SECURE_COOKIE=true
// config/cors.php
'paths' => ['api/*', 'auth/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
// config/fortify.php
'prefix' => 'auth',
'views' => false,
// config/session.php
'encrypt' => true,
'http_only' => true,
'same_site' => 'lax',
Routes
I created a separate middleware group although it's very similar to web middleware group:
// app/Http/Kernel.php
protected $middlewareGroups = [
// added custom route group
'mw-group-name' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
]
]
// app/Providers/RouteServiceProvider.php
public function boot()
{
// added custom routes
Route::middleware('mw-group-name')
->prefix('auth')
->group(base_path('routes/auth.php'));
});
}
// app/routes/auth.php
// Here id added the routes that needed to have session storage
// while not authenticated that "stays alive" for multiple requests
Writing to session
// app/Http/Controllers/SomeController.php
// On the first request/function I put variables to session and SAVE
$request->session()->put('some_var_value_1', $someVarValue1);
$request->session()->put('some_var_value_2', $someVarValue2);
$request->session()->save();
// On the next request/function I get the variables from session
$request->session()->get('some_var_value_1');
$request->session()->get('some_var_value_2');
SPA (nuxt) conf
// nuxt.config.js
axios: {
baseUrl: process.env.API_URL || 'http://api.example.lndo.site',
credentials: true,
headers: {
accept: 'application/json',
},
},
auth: {
redirects: {
login: '/login',
logout: '/login',
home: '/',
},
strategies: {
cookie: {
endpoints: {
csrf: {
url: '/sanctum/csrf-cookie',
},
login: {
url: '/auth/login',
},
logout: {
url: '/auth/logout',
},
register: {
url: '/auth/register',
},
user: {
url: '/api/me',
},
},
},
},
},
SPA (nuxtjs) request flow
// components/SomeComponent.vue
<script>
export default {
methods: {
async doRequest() {
await this.$axios.get('/sanctum/csrf-cookie')
await this.$axios
.post('/auth/custom-start', {
some_var: this.someUserInput,
})
// Here I'm putting some vars to cookie for later use
.then((response) => {
// do front-end stuff
})
await this.$axios.get('/sanctum/csrf-cookie')
await this.$axios
.post('/auth/custom-process')
// Here I'm using cookie vars in the back-end controller, sent with
//request as a encrypted cookie
.then((response) => {
// do front-end stuff
})
},
},
}
</script>
The end.
I really hope it helps some future troubleshooter save some time. Feel free to ask more specifics. Cheers.