Skip to content

Authentication

XetaSuite uses Laravel Sanctum in stateful mode (cookies) for SPA authentication. No API tokens are stored client-side.

Terminal window
sequenceDiagram
participant SPA as React SPA
participant Laravel as Laravel Backend
SPA->>Laravel: GET /sanctum/csrf-cookie
Laravel-->>SPA: Set XSRF-TOKEN cookie
SPA->>Laravel: POST /api/v1/auth/login (+ credentials)
Laravel-->>SPA: Set session cookie
SPA->>Laravel: GET /api/v1/user (with cookies)
Laravel-->>SPA: User data + permissions
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:5173,127.0.0.1,xetasuite.test'
)),
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:5173')],
'supports_credentials' => true,
const httpClient = axios.create({
baseURL: import.meta.env.VITE_API_URL || '',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
withCredentials: true, // ⚠️ Required for Sanctum
withXSRFToken: true, // Auto-include X-XSRF-TOKEN header
});
  1. Get CSRF cookie

    await axios.get('/sanctum/csrf-cookie');
  2. Send credentials

    await httpClient.post('/api/v1/auth/login', {
    email: 'admin@xetasuite.test',
    password: 'password',
    remember: true
    });
  3. Fetch user

    const { data } = await httpClient.get('/api/v1/user');
    // data contains: user, roles[], permissions[]
// In React components
const {
hasPermission,
hasRole,
hasAnyPermission,
hasAnyRole,
isOnHeadquarters
} = useAuth();
// Check a permission
if (hasPermission('company.create')) {
// Show create button
}
// Check a role
if (hasRole('admin')) {
// Show admin panel
}
// Check any of the permissions
if (hasAnyPermission(['company.update', 'company.delete'])) {
// Show menu
}
// Check any of the roles
if (hasRole(['admin', 'manager'])) {
// Show user edit button
}
// Check if current user is on headquarters site
if (isOnHeadquarters()) {
// User is on headquarters site
}