NeahNew/LOGIN_LOGOUT_FILES_AUDIT.md
2026-01-04 10:32:31 +01:00

647 lines
23 KiB
Markdown

# Audit Complet des Fichiers Login/Logout - Analyse des Cookies
## 📋 Vue d'ensemble
Ce document liste **TOUS** les fichiers de code impliqués dans le processus de **login** et **logout** du dashboard Next.js avec NextAuth et Keycloak, avec une analyse approfondie de la gestion des cookies.
---
## 🔐 FICHIERS CORE - Configuration NextAuth
### 1. **`app/api/auth/[...nextauth]/route.ts`**
**Rôle** : Route handler NextAuth pour tous les endpoints d'authentification
**Cookies gérés** :
- `next-auth.session-token` (ou variantes sécurisées) - Cookie principal de session NextAuth
- `next-auth.csrf-token` - Token CSRF pour la sécurité
- `next-auth.state` - État OAuth pour le flow Keycloak
- `next-auth.callback-url` - URL de callback après authentification
**Fonctions** :
- Gère `GET/POST /api/auth/signin` → Redirige vers Keycloak
- Gère `GET/POST /api/auth/signout` → Déconnecte et nettoie les cookies
- Gère `GET /api/auth/session` → Lit le cookie de session
- Gère `GET /api/auth/callback/keycloak` → Reçoit le code OAuth de Keycloak
- Gère `GET /api/auth/csrf` → Génère le token CSRF
- Gère `GET /api/auth/providers` → Liste les providers disponibles
**Cookies créés/supprimés** :
- **Login** : Crée `next-auth.session-token` (HttpOnly, Secure, SameSite=Lax)
- **Logout** : Supprime `next-auth.session-token` via `signOut()`
---
### 2. **`app/api/auth/options.ts`** ⭐ **FICHIER CRITIQUE**
**Rôle** : Configuration principale de NextAuth avec Keycloak
**Cookies gérés** :
- Tous les cookies NextAuth (via configuration implicite)
- Les tokens Keycloak sont stockés dans le JWT (pas de cookies séparés)
**Fonctions clés** :
#### `refreshAccessToken(token)` (lignes 83-139)
- **Cookies utilisés** : Aucun directement, mais utilise `refreshToken` du JWT
- **Comportement** :
- Appelle Keycloak `/token` endpoint pour rafraîchir
- Détecte si la session Keycloak est invalide (erreur `invalid_grant`)
- Retourne `error: "SessionNotActive"` si session Keycloak expirée
#### `jwt` callback (lignes 196-282)
- **Cookies utilisés** : Lit `next-auth.session-token` (décrypté par NextAuth)
- **Comportement** :
- **Initial login** : Stocke `accessToken`, `refreshToken`, `idToken` dans le JWT
- **Subsequent requests** : Vérifie expiration, rafraîchit si nécessaire
- **Token expired** : Appelle `refreshAccessToken()`
- **Session invalidated** : Retourne token avec `error: "SessionNotActive"`
#### `session` callback (lignes 283-324)
- **Cookies utilisés** : Lit le JWT depuis `next-auth.session-token`
- **Comportement** :
- Si `token.error === "SessionNotActive"` → Retourne `null` (force logout)
- Sinon, construit la session avec les données utilisateur
**Configuration cookies** :
```typescript
session: {
strategy: "jwt",
maxAge: 4 * 60 * 60, // 4 heures
}
// Les cookies sont gérés automatiquement par NextAuth
// Pas de configuration explicite des cookies dans ce fichier
```
**Paramètres OAuth** :
```typescript
authorization: {
params: {
scope: "openid profile email roles",
prompt: "login" // Force le prompt de login même si SSO existe
}
}
```
---
## 🚪 FICHIERS PAGES - Interface Utilisateur
### 3. **`app/signin/page.tsx`** ⭐ **FICHIER CRITIQUE**
**Rôle** : Page de connexion avec logique complexe de détection de logout
**Cookies analysés** :
- `next-auth.session-token` (ou variantes) - Vérifie si cookie existe mais invalide
- `logout_in_progress` - Cookie temporaire (60s) pour marquer logout en cours
- Cookies Keycloak (via `document.cookie`)
**Fonctions clés** :
#### Détection de logout/session invalide (lignes 17-67)
```typescript
// Vérifie les cookies NextAuth
const hasInvalidSessionCookie = document.cookie
.split(';')
.some(c => c.trim().startsWith('next-auth.session-token=') ||
c.trim().startsWith('__Secure-next-auth.session-token=') ||
c.trim().startsWith('__Host-next-auth.session-token='));
// Si cookie existe mais status = unauthenticated → Session invalidée
if (status === 'unauthenticated' && hasInvalidSessionCookie) {
sessionStorage.setItem('session_invalidated', 'true');
// Empêche auto-login
}
```
#### Auto-login (lignes 69-124)
- **Condition** : Seulement si **PAS** de cookie de session existant
- **Comportement** : Appelle `signIn("keycloak")` après 1 seconde
- **Protection** : Ne s'exécute pas si `logout_in_progress` ou `session_invalidated`
#### Initialisation storage (lignes 126-158)
- Appelle `/api/storage/init` après authentification réussie
- Force reload pour mettre à jour la session
**Cookies créés/supprimés** :
- **Aucun cookie créé directement** (NextAuth gère ça)
- **Supprime** : `sessionStorage` items (`just_logged_out`, `session_invalidated`)
---
### 4. **`app/signout/page.tsx`**
**Rôle** : Page de déconnexion (simple wrapper)
**Cookies** : Aucune manipulation directe, délègue à `SignOutHandler`
---
## 🔧 FICHIERS COMPOSANTS - Logique Métier
### 5. **`components/auth/signout-handler.tsx`** ⭐ **FICHIER CRITIQUE**
**Rôle** : Gère la déconnexion complète (NextAuth + Keycloak)
**Cookies manipulés** :
#### Cookies NextAuth (ligne 23)
```typescript
clearAuthCookies(); // Supprime next-auth.session-token
```
#### Cookies Keycloak (ligne 25)
```typescript
clearKeycloakCookies(); // Tente de supprimer KEYCLOAK_SESSION, etc.
```
#### Cookie de flag (ligne 16)
```typescript
document.cookie = 'logout_in_progress=true; path=/; max-age=60';
```
**Flow de logout** :
1. Marque logout en cours (`sessionStorage` + cookie)
2. **Supprime cookies NextAuth** (`clearAuthCookies()`)
3. **Tente de supprimer cookies Keycloak** (`clearKeycloakCookies()`)
4. Appelle `/api/auth/end-sso-session` (Admin API Keycloak)
5. Appelle `signOut()` NextAuth (supprime cookie serveur)
6. Redirige vers Keycloak logout endpoint avec `id_token_hint`
7. Keycloak redirige vers `/signin?logout=true`
**Cookies supprimés** :
- `next-auth.session-token` (et variantes)
- `KEYCLOAK_SESSION`, `KEYCLOAK_IDENTITY`, `AUTH_SESSION_ID` (si même domaine)
- `logout_in_progress` (expire après 60s)
---
### 6. **`components/main-nav.tsx`** (lignes 364-446)
**Rôle** : Bouton de déconnexion dans la navigation
**Cookies** : Même logique que `signout-handler.tsx`
- Appelle `clearAuthCookies()` et `clearKeycloakCookies()`
- Crée cookie `logout_in_progress`
- Même flow que `SignOutHandler`
---
### 7. **`components/layout/layout-wrapper.tsx`** ⭐ **FICHIER CRITIQUE**
**Rôle** : Écoute les messages de logout depuis les iframes
**Cookies manipulés** :
- Même pattern que `signout-handler.tsx`
- Gère les logout déclenchés par les iframes via `postMessage`
**Fonction clé** (lignes 23-112) :
```typescript
const handleMessage = async (event: MessageEvent) => {
if (event.data.type === 'KEYCLOAK_LOGOUT' || event.data.type === 'LOGOUT') {
// Même flow que signout-handler.tsx
clearAuthCookies();
clearKeycloakCookies();
// ... logout complet
}
};
```
**Cookies** : Identique à `signout-handler.tsx`
---
### 8. **`components/auth/auth-check.tsx`**
**Rôle** : Guard d'authentification côté client
**Cookies** : Aucune manipulation directe
- Utilise `useSession()` qui lit `next-auth.session-token`
- Redirige vers `/signin` si `status === "unauthenticated"`
---
### 9. **`components/providers.tsx`**
**Rôle** : Wrapper `SessionProvider` pour NextAuth
**Cookies** : Aucune manipulation, fournit le contexte de session
---
## 🛠️ FICHIERS UTILITAIRES - Gestion Sessions/Cookies
### 10. **`lib/session.ts`** ⭐ **FICHIER CRITIQUE**
**Rôle** : Utilitaires pour gérer les cookies et sessions
#### `clearAuthCookies()` (lignes 93-108)
**Cookies supprimés** :
```typescript
// Supprime SEULEMENT les cookies de session, PAS les cookies OAuth
if (cookieName.startsWith('next-auth.session-token') ||
cookieName.startsWith('__Secure-next-auth.session-token') ||
cookieName.startsWith('__Host-next-auth.session-token')) {
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}
```
**Important** : Ne supprime **PAS** :
- `next-auth.csrf-token` (nécessaire pour OAuth)
- `next-auth.state` (nécessaire pour OAuth flow)
- `next-auth.callback-url`
#### `clearKeycloakCookies()` (lignes 115-154)
**Cookies Keycloak tentés de supprimer** :
```typescript
const keycloakCookieNames = [
'KEYCLOAK_SESSION',
'KEYCLOAK_SESSION_LEGACY',
'KEYCLOAK_IDENTITY',
'KEYCLOAK_IDENTITY_LEGACY',
'AUTH_SESSION_ID',
'KC_RESTART',
'KC_RESTART_LEGACY'
];
```
**Limitation** : Ces cookies sont sur le domaine Keycloak, donc **ne peuvent pas être supprimés** depuis le domaine du dashboard (même origine). Cette fonction tente plusieurs combinaisons domain/path mais échouera si Keycloak est sur un domaine différent.
#### `invalidateServiceTokens()` (lignes 53-91)
**Cookies** : Aucun, invalide les tokens de services externes (RocketChat, Leantime)
---
### 11. **`lib/keycloak.ts`**
**Rôle** : Client Admin Keycloak pour gestion serveur
**Cookies** : Aucune manipulation directe
- Utilisé par `/api/auth/end-sso-session` pour terminer la session SSO
---
## 🌐 FICHIERS API - Endpoints Serveur
### 12. **`app/api/auth/end-sso-session/route.ts`** ⭐ **FICHIER CRITIQUE**
**Rôle** : Termine la session SSO Keycloak via Admin API
**Cookies** : Aucune manipulation directe
- Utilise Keycloak Admin API pour logout utilisateur
- **Important** : Termine la session **realm-wide**, pas seulement client
**Flow** :
1. Lit `next-auth.session-token` via `getServerSession()`
2. Extrait `idToken` de la session
3. Décode `idToken` pour obtenir `userId`
4. Appelle `adminClient.users.logout({ id: userId })`
5. Keycloak supprime **toutes** les sessions de l'utilisateur
**Impact cookies** :
- Keycloak supprime ses cookies côté serveur
- Les cookies Keycloak deviennent invalides (mais restent dans le navigateur jusqu'à expiration)
---
### 13. **`app/api/auth/refresh-keycloak-session/route.ts`**
**Rôle** : Rafraîchit la session Keycloak (si existe)
**Cookies** : Lit `next-auth.session-token` via `getServerSession()`
---
## 📄 FICHIERS LAYOUT - Structure Application
### 14. **`app/layout.tsx`**
**Rôle** : Layout racine avec vérification de session serveur
**Cookies** : Lit `next-auth.session-token` via `getServerSession(authOptions)`
- Passe `isAuthenticated` à `LayoutWrapper`
- Détermine si c'est la page signin
---
### 15. **`app/components/responsive-iframe.tsx`** (lignes 109-153)
**Rôle** : Composant iframe avec écoute de messages logout
**Cookies** : Aucune manipulation directe
- Écoute `postMessage` depuis iframes
- Déclenche logout si message `KEYCLOAK_LOGOUT` reçu
- **Note** : Logique similaire à `layout-wrapper.tsx` mais dans le composant iframe
---
## 📝 FICHIERS TYPES - Définitions TypeScript
### 16. **`types/next-auth.d.ts`**
**Rôle** : Extensions TypeScript pour NextAuth
**Cookies** : Aucune manipulation, définit les types de session/JWT
---
## 🔍 ANALYSE DÉTAILLÉE DES COOKIES
### Cookies NextAuth
#### 1. **`next-auth.session-token`** (ou variantes sécurisées)
- **Domaine** : Domaine du dashboard
- **Path** : `/`
- **HttpOnly** : `true` (sécurité)
- **Secure** : `true` (si HTTPS)
- **SameSite** : `Lax` (par défaut)
- **Contenu** : JWT encrypté contenant :
- `accessToken` (Keycloak)
- `refreshToken` (Keycloak)
- `idToken` (Keycloak)
- Données utilisateur (id, email, roles, etc.)
- **Durée** : 4 heures (configuré dans `options.ts`)
- **Créé** : Lors de `signIn()` réussi
- **Supprimé** : Lors de `signOut()` ou expiration
- **Variantes** :
- `__Secure-next-auth.session-token` (si HTTPS)
- `__Host-next-auth.session-token` (si domaine racine)
#### 2. **`next-auth.csrf-token`**
- **Domaine** : Domaine du dashboard
- **Path** : `/`
- **HttpOnly** : `true`
- **Secure** : `true` (si HTTPS)
- **SameSite** : `Lax`
- **Contenu** : Token CSRF pour protection OAuth
- **Durée** : Session (supprimé à la fermeture du navigateur)
- **Créé** : Lors de la première requête OAuth
- **Supprimé** : À la fermeture du navigateur
- **Important** : **N'EST PAS supprimé** par `clearAuthCookies()` (nécessaire pour OAuth)
#### 3. **`next-auth.state`**
- **Domaine** : Domaine du dashboard
- **Path** : `/`
- **HttpOnly** : `true`
- **Secure** : `true` (si HTTPS)
- **SameSite** : `Lax`
- **Contenu** : État OAuth pour validation du callback
- **Durée** : Court (pendant le flow OAuth)
- **Créé** : Lors de `signIn()` (début flow OAuth)
- **Supprimé** : Après validation du callback OAuth
- **Important** : **N'EST PAS supprimé** par `clearAuthCookies()` (nécessaire pour OAuth)
#### 4. **`next-auth.callback-url`**
- **Domaine** : Domaine du dashboard
- **Path** : `/`
- **HttpOnly** : `true`
- **Secure** : `true` (si HTTPS)
- **SameSite** : `Lax`
- **Contenu** : URL de redirection après authentification
- **Durée** : Court (pendant le flow OAuth)
- **Créé** : Lors de `signIn()` avec `callbackUrl`
- **Supprimé** : Après redirection
### Cookies Keycloak
#### 1. **`KEYCLOAK_SESSION`**
- **Domaine** : Domaine Keycloak (peut être différent du dashboard)
- **Path** : `/` ou `/realms/{realm}`
- **HttpOnly** : `true`
- **Secure** : `true` (si HTTPS)
- **SameSite** : `Lax` ou `None` (pour cross-site)
- **Contenu** : Identifiant de session SSO Keycloak
- **Durée** : Configuré dans Keycloak (typiquement 30 min - quelques heures)
- **Créé** : Lors de l'authentification Keycloak
- **Supprimé** : Lors de logout Keycloak ou expiration
- **Problème** : **Ne peut pas être supprimé** depuis le dashboard si domaine différent
#### 2. **`KEYCLOAK_IDENTITY`**
- **Domaine** : Domaine Keycloak
- **Path** : `/` ou `/realms/{realm}`
- **HttpOnly** : `true`
- **Secure** : `true`
- **SameSite** : `Lax` ou `None`
- **Contenu** : Identité utilisateur Keycloak
- **Durée** : Même que `KEYCLOAK_SESSION`
- **Créé** : Lors de l'authentification Keycloak
- **Supprimé** : Lors de logout Keycloak ou expiration
#### 3. **`AUTH_SESSION_ID`**
- **Domaine** : Domaine Keycloak
- **Path** : `/` ou `/realms/{realm}`
- **HttpOnly** : `true`
- **Secure** : `true`
- **SameSite** : `Lax` ou `None`
- **Contenu** : ID de session d'authentification
- **Durée** : Court (pendant le flow d'authentification)
- **Créé** : Lors du début du flow d'authentification
- **Supprimé** : Après authentification réussie ou échec
### Cookies Custom
#### 1. **`logout_in_progress`**
- **Domaine** : Domaine du dashboard
- **Path** : `/`
- **HttpOnly** : `false` (accessible via JavaScript)
- **Secure** : `false`
- **SameSite** : Non défini
- **Contenu** : `"true"`
- **Durée** : 60 secondes (`max-age=60`)
- **Créé** : Lors de `signOut()` (dans `signout-handler.tsx`, `main-nav.tsx`, `layout-wrapper.tsx`)
- **Supprimé** : Expire après 60s ou manuellement
- **Usage** : Empêche l'auto-login après logout
---
## 🔄 FLOW COMPLET DE LOGIN
### Étape 1 : Utilisateur accède à `/signin`
**Fichier** : `app/signin/page.tsx`
**Cookies** :
- Vérifie si `next-auth.session-token` existe
- Si existe mais `status === "unauthenticated"` → Session invalidée
- Si n'existe pas → Nouvel utilisateur, déclenche auto-login
### Étape 2 : Auto-login déclenché
**Fichier** : `app/signin/page.tsx` (ligne 118)
**Action** : `signIn("keycloak", { callbackUrl: "/" })`
**Cookies créés** :
- `next-auth.csrf-token` (par NextAuth)
- `next-auth.state` (par NextAuth)
- `next-auth.callback-url` (par NextAuth)
### Étape 3 : Redirection vers Keycloak
**Fichier** : `app/api/auth/[...nextauth]/route.ts` → NextAuth interne
**URL** : `${KEYCLOAK_ISSUER}/protocol/openid-connect/auth?...&prompt=login`
**Cookies Keycloak créés** :
- `AUTH_SESSION_ID` (par Keycloak)
### Étape 4 : Authentification Keycloak
**Fichier** : Keycloak serveur
**Cookies Keycloak créés** :
- `KEYCLOAK_SESSION` (session SSO)
- `KEYCLOAK_IDENTITY` (identité utilisateur)
### Étape 5 : Callback OAuth
**Fichier** : `app/api/auth/callback/keycloak` (géré par NextAuth)
**Cookies** :
- `next-auth.state` vérifié et supprimé
- `next-auth.callback-url` lu et utilisé
### Étape 6 : JWT Callback
**Fichier** : `app/api/auth/options.ts``jwt` callback (ligne 196)
**Cookies** :
- Lit `next-auth.session-token` (décrypté)
- Stocke tokens Keycloak dans le JWT
- **Crée** `next-auth.session-token` (nouveau JWT avec tokens)
### Étape 7 : Session Callback
**Fichier** : `app/api/auth/options.ts``session` callback (ligne 283)
**Cookies** : Lit `next-auth.session-token` pour construire la session
### Étape 8 : Redirection vers `/`
**Fichier** : `app/signin/page.tsx` (ligne 72)
**Cookies** : `next-auth.session-token` maintenant présent
### Étape 9 : Initialisation Storage
**Fichier** : `app/signin/page.tsx` (lignes 126-158)
**Action** : Appelle `/api/storage/init`
**Cookies** : Utilise `next-auth.session-token` (via `getServerSession()`)
---
## 🔄 FLOW COMPLET DE LOGOUT
### Étape 1 : Utilisateur clique "Déconnexion"
**Fichiers** :
- `components/main-nav.tsx` (ligne 364)
- OU `components/auth/signout-handler.tsx` (ligne 11)
- OU `components/layout/layout-wrapper.tsx` (ligne 32) si message iframe
**Cookies créés** :
- `logout_in_progress=true; path=/; max-age=60` (ligne 16/369/38)
- `sessionStorage.setItem('just_logged_out', 'true')` (ligne 14/367/37)
### Étape 2 : Suppression cookies NextAuth
**Fichier** : `lib/session.ts``clearAuthCookies()` (ligne 93)
**Cookies supprimés** :
- `next-auth.session-token` (et variantes)
- **PAS** `next-auth.csrf-token` (nécessaire pour OAuth)
- **PAS** `next-auth.state` (nécessaire pour OAuth)
### Étape 3 : Tentative suppression cookies Keycloak
**Fichier** : `lib/session.ts``clearKeycloakCookies()` (ligne 115)
**Cookies tentés de supprimer** :
- `KEYCLOAK_SESSION`, `KEYCLOAK_IDENTITY`, etc.
- **Limitation** : Échoue si Keycloak sur domaine différent
### Étape 4 : Fin de session SSO via Admin API
**Fichier** : `app/api/auth/end-sso-session/route.ts` (ligne 15)
**Action** : `adminClient.users.logout({ id: userId })`
**Cookies** :
- Keycloak supprime **toutes** les sessions côté serveur
- Les cookies Keycloak deviennent invalides (mais restent dans le navigateur)
### Étape 5 : SignOut NextAuth
**Fichier** : `components/auth/signout-handler.tsx` (ligne 52)
**Action** : `signOut({ callbackUrl: "/signin?logout=true", redirect: false })`
**Cookies supprimés** :
- `next-auth.session-token` (supprimé côté serveur)
### Étape 6 : Redirection vers Keycloak Logout
**Fichier** : `components/auth/signout-handler.tsx` (ligne 58)
**URL** : `${KEYCLOAK_ISSUER}/protocol/openid-connect/logout?...&id_token_hint=...&kc_action=LOGOUT`
**Cookies Keycloak** :
- Keycloak supprime ses cookies (si même domaine ou cross-domain configuré)
### Étape 7 : Redirection vers `/signin?logout=true`
**Fichier** : Keycloak → `app/signin/page.tsx`
**Cookies** :
- `next-auth.session-token` : Supprimé
- `KEYCLOAK_SESSION` : Peut encore exister (si domaine différent)
- `logout_in_progress` : Existe encore (60s)
### Étape 8 : Détection logout dans signin
**Fichier** : `app/signin/page.tsx` (lignes 17-67)
**Cookies vérifiés** :
- `logout_in_progress` (ligne 19)
- `next-auth.session-token` (ligne 25-29)
- `sessionStorage.getItem('just_logged_out')` (ligne 20)
**Comportement** :
- Si `logout=true` dans URL → Affiche message "Vous avez été déconnecté"
- Si cookie session existe mais invalide → Empêche auto-login
- Si pas de cookie session → Auto-login après 1s (nouvel utilisateur)
---
## ⚠️ PROBLÈMES IDENTIFIÉS
### Problème 1 : Cookies Keycloak non supprimables
**Fichier** : `lib/session.ts``clearKeycloakCookies()`
**Cause** : Cookies Keycloak sur domaine différent
**Impact** : Les cookies Keycloak persistent après logout dashboard
**Solution actuelle** : Appel à Keycloak logout endpoint avec `id_token_hint`
### Problème 2 : Session SSO Keycloak peut persister
**Fichier** : `app/api/auth/options.ts` (ligne 154)
**Cause** : `prompt=login` force le prompt, mais si SSO session existe, Keycloak peut auto-authentifier
**Impact** : Utilisateur peut être reconnecté automatiquement sans credentials
**Solution actuelle** : `prompt=login` + appel Admin API pour terminer session SSO
### Problème 3 : Détection session invalide complexe
**Fichier** : `app/signin/page.tsx` (lignes 17-67)
**Cause** : Logique complexe pour détecter si session invalidée vs nouvel utilisateur
**Impact** : Auto-login peut se déclencher incorrectement
**Solution actuelle** : Vérification multiple (cookies, sessionStorage, URL params)
### Problème 4 : Race condition logout/login
**Fichier** : `app/signin/page.tsx` (lignes 69-124)
**Cause** : Auto-login avec délai de 1s peut se déclencher pendant logout
**Impact** : Utilisateur peut être reconnecté immédiatement après logout
**Solution actuelle** : Flags `logout_in_progress` et `session_invalidated`
---
## 📊 RÉSUMÉ DES FICHIERS PAR CATÉGORIE
### Configuration Core (2 fichiers)
1. `app/api/auth/[...nextauth]/route.ts`
2. `app/api/auth/options.ts`
### Pages (2 fichiers)
3. `app/signin/page.tsx`
4. `app/signout/page.tsx`
### Composants Auth (4 fichiers)
5. `components/auth/signout-handler.tsx`
6. `components/auth/auth-check.tsx`
7. `components/auth/signin-form.tsx` (si existe)
8. `components/auth/login-card.tsx` (si existe)
### Composants Layout (2 fichiers)
9. `components/layout/layout-wrapper.tsx`
10. `components/providers.tsx`
### Navigation (1 fichier)
11. `components/main-nav.tsx`
### Utilitaires (2 fichiers)
12. `lib/session.ts`
13. `lib/keycloak.ts`
### API Routes (2 fichiers)
14. `app/api/auth/end-sso-session/route.ts`
15. `app/api/auth/refresh-keycloak-session/route.ts`
### Layout Root (1 fichier)
16. `app/layout.tsx`
### Iframe (1 fichier)
17. `app/components/responsive-iframe.tsx`
### Types (1 fichier)
18. `types/next-auth.d.ts`
**Total : 18 fichiers principaux**
---
## 🎯 FICHIERS CRITIQUES (⭐)
Les fichiers marqués ⭐ sont **critiques** pour le flow login/logout :
1. **`app/api/auth/options.ts`** - Configuration NextAuth, callbacks JWT/session
2. **`app/signin/page.tsx`** - Logique complexe de détection logout/auto-login
3. **`components/auth/signout-handler.tsx`** - Flow complet de logout
4. **`lib/session.ts`** - Gestion des cookies (suppression)
5. **`components/layout/layout-wrapper.tsx`** - Écoute logout depuis iframes
6. **`components/main-nav.tsx`** - Bouton logout
7. **`app/api/auth/end-sso-session/route.ts`** - Termine session SSO Keycloak
---
## 📝 NOTES IMPORTANTES
1. **Cookies NextAuth** : Gérés automatiquement par NextAuth, pas besoin de manipulation manuelle sauf pour suppression
2. **Cookies Keycloak** : Ne peuvent pas être supprimés depuis le dashboard si domaine différent (limitation navigateur)
3. **Session SSO** : Doit être terminée via Admin API Keycloak pour être complètement supprimée
4. **Auto-login** : Logique complexe pour distinguer nouvel utilisateur vs session invalidée
5. **Iframe logout** : Communication via `postMessage` pour synchroniser logout
---
**Document créé le** : $(date)
**Dernière mise à jour** : Analyse complète du workflow login/logout avec focus sur les cookies