2025-12-03 21:56:50 +00:00
|
|
|
/**
|
2026-01-07 09:33:52 +00:00
|
|
|
* TokenStorage - Service de gestion du stockage des tokens
|
2025-12-03 21:56:50 +00:00
|
|
|
* T0169: Service simple pour stocker, récupérer et supprimer les tokens d'authentification
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* SECURITY: Migration vers cookies httpOnly COMPLÉTÉE (Action 5.1.1.2)
|
|
|
|
|
* - Access Token: Stocké dans un cookie httpOnly par le backend (pas accessible via JavaScript)
|
2026-01-07 09:33:52 +00:00
|
|
|
* - Refresh Token: Stocké dans un cookie httpOnly par le backend (pas accessible via JavaScript)
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* IMPORTANT: Les tokens sont maintenant dans des cookies httpOnly set par le backend.
|
|
|
|
|
* JavaScript ne peut pas accéder aux cookies httpOnly, donc cette classe est maintenant
|
|
|
|
|
* principalement une API de compatibilité (no-op).
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* NOTE: Les cookies httpOnly sont automatiquement envoyés avec les requêtes via withCredentials: true.
|
|
|
|
|
* Le backend lit les tokens depuis les cookies, pas depuis localStorage ou les headers Authorization.
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
const ACCESS_TOKEN_KEY = 'veza_access_token';
|
|
|
|
|
const REFRESH_TOKEN_KEY = 'veza_refresh_token';
|
|
|
|
|
|
2026-01-07 09:33:52 +00:00
|
|
|
/**
|
2026-01-16 00:02:03 +00:00
|
|
|
* Réinitialise le stockage (utile pour les tests)
|
2026-01-07 09:33:52 +00:00
|
|
|
* @internal
|
|
|
|
|
*/
|
|
|
|
|
export function _resetTokenMemory(): void {
|
2026-01-16 00:02:03 +00:00
|
|
|
// No-op: tokens are in httpOnly cookies, not accessible from JS
|
2026-01-07 09:33:52 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
/**
|
|
|
|
|
* Classe TokenStorage pour gérer le stockage des tokens
|
2026-01-16 00:02:03 +00:00
|
|
|
* T0169: Service de gestion du stockage tokens
|
|
|
|
|
*
|
|
|
|
|
* SECURITY: Action 5.1.1.2 - Tokens sont maintenant dans des cookies httpOnly
|
|
|
|
|
* Cette classe est maintenant principalement une API de compatibilité (no-op)
|
|
|
|
|
* car les cookies httpOnly ne sont pas accessibles via JavaScript.
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
|
|
|
|
export class TokenStorage {
|
|
|
|
|
/**
|
2026-01-07 09:33:52 +00:00
|
|
|
* Stocke les tokens d'authentification
|
2026-01-16 00:02:03 +00:00
|
|
|
* SECURITY: Action 5.1.1.2 - No-op car les tokens sont dans des cookies httpOnly
|
|
|
|
|
* Le backend sette les cookies httpOnly lors du login/register/refresh.
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* @param accessToken - Token d'accès JWT (ignoré, dans cookie httpOnly)
|
|
|
|
|
* @param refreshToken - Token de rafraîchissement (ignoré, dans cookie httpOnly)
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
2026-01-16 00:02:03 +00:00
|
|
|
static setTokens(_accessToken: string, _refreshToken: string): void {
|
|
|
|
|
// No-op: tokens are set in httpOnly cookies by backend, not accessible to JS
|
|
|
|
|
// Clean up any legacy localStorage tokens if they exist
|
|
|
|
|
try {
|
|
|
|
|
localStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
|
|
|
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
|
|
|
|
} catch {
|
|
|
|
|
// Ignore errors (e.g., in SSR environment)
|
2026-01-07 09:33:52 +00:00
|
|
|
}
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-16 00:02:03 +00:00
|
|
|
* Récupère le token d'accès
|
|
|
|
|
* SECURITY: Action 5.1.1.2 - Retourne null car le token est dans un cookie httpOnly
|
|
|
|
|
* Les cookies httpOnly ne sont pas accessibles via JavaScript.
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* @returns null (token est dans cookie httpOnly, non accessible)
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
|
|
|
|
static getAccessToken(): string | null {
|
2026-01-16 00:02:03 +00:00
|
|
|
// Token is in httpOnly cookie, not accessible from JavaScript
|
|
|
|
|
return null;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-16 00:02:03 +00:00
|
|
|
* Récupère le token de rafraîchissement
|
|
|
|
|
* SECURITY: Action 5.1.1.2 - Retourne null car le token est dans un cookie httpOnly
|
|
|
|
|
* Les cookies httpOnly ne sont pas accessibles via JavaScript.
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* @returns null (token est dans cookie httpOnly, non accessible)
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
|
|
|
|
static getRefreshToken(): string | null {
|
2026-01-16 00:02:03 +00:00
|
|
|
// Token is in httpOnly cookie, not accessible from JavaScript
|
|
|
|
|
return null;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-16 00:02:03 +00:00
|
|
|
* Supprime tous les tokens
|
|
|
|
|
* SECURITY: Action 5.1.1.2 - Nettoie seulement localStorage legacy si présent
|
|
|
|
|
* Les cookies httpOnly sont supprimés par le backend lors du logout.
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
|
|
|
|
static clearTokens(): void {
|
2026-01-16 00:02:03 +00:00
|
|
|
// Clean up any legacy localStorage tokens if they exist
|
|
|
|
|
try {
|
|
|
|
|
localStorage.removeItem(ACCESS_TOKEN_KEY);
|
|
|
|
|
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
|
|
|
|
} catch {
|
|
|
|
|
// Ignore errors (e.g., in SSR environment)
|
|
|
|
|
}
|
|
|
|
|
// Cookies httpOnly are cleared by backend on logout
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-07 09:33:52 +00:00
|
|
|
* Vérifie si des tokens sont présents
|
2026-01-16 00:02:03 +00:00
|
|
|
* SECURITY: Action 5.1.1.2 - Retourne false car on ne peut pas vérifier les cookies httpOnly
|
|
|
|
|
* Les cookies httpOnly ne sont pas accessibles via JavaScript.
|
2026-01-13 18:47:57 +00:00
|
|
|
*
|
2026-01-16 00:02:03 +00:00
|
|
|
* @returns false (ne peut pas vérifier les cookies httpOnly depuis JS)
|
2025-12-03 21:56:50 +00:00
|
|
|
*/
|
|
|
|
|
static hasTokens(): boolean {
|
2026-01-16 00:02:03 +00:00
|
|
|
// Cannot check httpOnly cookies from JavaScript
|
|
|
|
|
return false;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
}
|