I finally noticed where I had a mistake
My session table didn't have an user_id because I was using UUID for my users, and session table wasn't properly configured for such UUID
Fixed session migration (notice that session table included in the create_users_table migration in laravel 12)
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignUuid('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
EDIT
I also wanna to leave the important configuration places you need to check if you're getting errors
Config settings to check:
1. Check your SPA (e.g. VueJS app) and API (e.g. Laravel) are on the same top level domain
For example:
api - localhost:8000
spa - localhost:5173
(notice: localhost = 127.0.0.1:8000 is a top-level domain)
2. Ensure to properly configure .env
APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:5173
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost
3. In your bootstrap/app.php in the withMiddleware
$middleware->statefulApi();
4. Ensure config/cors.php is properly configured
Notice: If you don't have this file run: php artisan config:publish cors
'paths' => ['*'], // optionally config this line (see usual config below)
'allowed_methods' => ['*'], // EXAMINE THIS LINE
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], // v
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true, // AND EXAMINE THIS LINE (throws CORS error if false)
usually you can see this kind of config for paths in config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie', '/login', '/logout'],
5. Session and SESSION_DRIVER
In your .env file:
If your SESSION_DRIVER=database (it's a default value and you don't need to touch it) check user_id is set after registration/login
Reminder:
- You don't need to call the /sanctum/csrf-cookie in logout, because after yout logged in or registered the frontend should already have the token
- Authentication routes (login, register, logout) should be in routes/api.php not routes/web.php
1. Check your axiosClient (if you're using one, or chec your axios are using proper settings)
Example of my src/axios.js
import axios from 'axios'
import router from '@/router/index.js'
const axiosClient = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL, // check how to configure this line below
withCredentials: true, // THIS LINE IS IMPORTANT
withXSRFToken: true, // THIS LINE IS ALSO IMPORTANT
})
axiosClient.interceptors.response.use( (response) =>{
return response;
}, error => {
if (error.response && error.response.status === 401){
router.push({name: 'Login'})
}
throw error;
})
export default axiosClient
in your .env (notice: its a SPA's .env file, not an API's) check your have your API base URL, for example
VITE_API_BASE_URL=http://localhost:8000
2. Check your routes are sending the GET /sanctum/csrf-cookie request before **POST, PUT, PATCH, DELETE
example: login request
const form = reactive({
email: '',
password: '',
})
const errorMessage = ref('')
function submit() {
// THIS LINE IS IMPORTANT
axiosClient.get('/sanctum/csrf-cookie').then(response => {
axiosClient.post('/login', form)
.then(response => {
router.push({name: 'Home'})
})
.catch(error => {
errorMessage.value = error.response.data.message;
})
});
}
Reminder:
- You shouldn't call /sanctum/csrf-cookie for EVERY POST, PUT, PATCH, DELETE requests
Remember this: You only need to call the endpoint once at the start of the session.
Hope it'll provide clear understanding where you can find your error