$npx -y skills add gdarko/laravel-vue-starter --skill spa-auth-developmentActivate when working on SPA authentication flow, Sanctum cookie-based auth, Vue Router guards, auth store, login/register/password reset pages, or CORS/session configuration. Covers the full auth lifecycle from CSRF cookie to protected API calls.
| 1 | # SPA Authentication Development |
| 2 | |
| 3 | This project uses a decoupled SPA architecture where Vue handles all routing and Laravel serves as a JSON API with Sanctum cookie-based authentication. |
| 4 | |
| 5 | ## Auth Flow |
| 6 | |
| 7 | 1. Vue app calls `GET /sanctum/csrf-cookie` to get XSRF token |
| 8 | 2. User submits login form → `POST /login` (Fortify handles this) |
| 9 | 3. Laravel returns session cookie + user data |
| 10 | 4. All subsequent API calls include the session cookie automatically (`withCredentials: true`) |
| 11 | 5. Protected routes use `auth:sanctum` middleware |
| 12 | |
| 13 | ## Key Files |
| 14 | |
| 15 | ### Backend |
| 16 | - `config/sanctum.php` — Stateful domains, guards, CSRF middleware |
| 17 | - `config/cors.php` — CORS paths (api/*, login, logout, register, etc.) with `supports_credentials: true` |
| 18 | - `config/fortify.php` — Auth features (registration, password reset, email verification) |
| 19 | - `app/Providers/FortifyServiceProvider.php` — Binds Fortify actions and custom LoginResponse |
| 20 | - `app/Http/Responses/LoginResponse.php` — Returns JSON with user data for SPA |
| 21 | - `app/Http/Middleware/ApplyLocale.php` — Sets locale from X-Locale header |
| 22 | - `bootstrap/app.php` — `statefulApi()` middleware, `apply_locale` alias |
| 23 | |
| 24 | ### Frontend |
| 25 | - `stores/auth.js` — Pinia store with login, register, logout, getCurrentUser |
| 26 | - `services/AuthService.ts` — API calls for auth endpoints (login, register, forgot/reset password, etc.) |
| 27 | - `router/index.js` — Navigation guards checking `requiresAuth` and `requiresAbility` route meta |
| 28 | - `plugins/axios.js` — Axios configured with `withCredentials`, X-Locale header, base URL from `window.AppConfig` |
| 29 | |
| 30 | ## CORS Configuration |
| 31 | |
| 32 | For the SPA to work, these `.env` values must match: |
| 33 | |
| 34 | ``` |
| 35 | APP_URL=http://localhost:8000 |
| 36 | SANCTUM_STATEFUL_DOMAINS=localhost:8000 |
| 37 | SESSION_DOMAIN=localhost |
| 38 | ``` |
| 39 | |
| 40 | ## Route Guards |
| 41 | |
| 42 | Routes use meta fields for auth: |
| 43 | - `requiresAuth: true` — Redirects to login if not authenticated |
| 44 | - `requiresAbility: 'ability_name'` — Checks user abilities via Bouncer |
| 45 | - `isPublicAuthPage: true` — Redirects to dashboard if already authenticated |
| 46 | - `isOwner: true` — Owner-only routes |
| 47 | |
| 48 | ## Authorization |
| 49 | |
| 50 | Uses Silber Bouncer with abilities: |
| 51 | - Abilities defined in `resources/app/stub/abilities.js` (CREATE_USER, EDIT_USER, etc.) |
| 52 | - Checked in Vue Router guards and sidebar menu visibility |
| 53 | - Backend uses `Gate::authorize()` in controllers |
| 54 | - Roles seeded in `database/seeders/BouncerSeeder.php` |