/** * TokenStorage - Service de gestion du stockage des tokens * T0169: Service simple pour stocker, récupérer et supprimer les tokens d'authentification * * 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) * - Refresh Token: Stocké dans un cookie httpOnly par le backend (pas accessible via JavaScript) * * 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). * * 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. */ const ACCESS_TOKEN_KEY = 'veza_access_token'; const REFRESH_TOKEN_KEY = 'veza_refresh_token'; /** * Réinitialise le stockage (utile pour les tests) * @internal */ export function _resetTokenMemory(): void { // No-op: tokens are in httpOnly cookies, not accessible from JS } /** * Classe TokenStorage pour gérer le stockage des tokens * 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. */ export class TokenStorage { /** * Stocke les tokens d'authentification * 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. * * @param accessToken - Token d'accès JWT (ignoré, dans cookie httpOnly) * @param refreshToken - Token de rafraîchissement (ignoré, dans cookie httpOnly) */ 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) } } /** * 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. * * @returns null (token est dans cookie httpOnly, non accessible) */ static getAccessToken(): string | null { // Token is in httpOnly cookie, not accessible from JavaScript return null; } /** * 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. * * @returns null (token est dans cookie httpOnly, non accessible) */ static getRefreshToken(): string | null { // Token is in httpOnly cookie, not accessible from JavaScript return null; } /** * 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. */ static clearTokens(): void { // 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 } /** * Vérifie si des tokens sont présents * 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. * * @returns false (ne peut pas vérifier les cookies httpOnly depuis JS) */ static hasTokens(): boolean { // Cannot check httpOnly cookies from JavaScript return false; } }