Refactor flow 3
This commit is contained in:
parent
f27d1e0835
commit
35ce442d4f
224
DEBUG_502_CALLBACK.md
Normal file
224
DEBUG_502_CALLBACK.md
Normal file
@ -0,0 +1,224 @@
|
||||
# Debug Erreur 502 - Callback Keycloak
|
||||
|
||||
## 🔍 Situation Actuelle
|
||||
|
||||
**URL** : `https://hub.slm-lab.net/api/auth/callback/keycloak?...`
|
||||
|
||||
**Logs observés** :
|
||||
- ✅ Profile callback : OK
|
||||
- ✅ JWT callback : OK (rôles extraits depuis access token)
|
||||
- ❌ Session callback : **PAS DE LOGS** (ne s'exécute pas ou échoue silencieusement)
|
||||
- ❌ Erreur 502 Nginx
|
||||
|
||||
## 🎯 Hypothèses
|
||||
|
||||
### Hypothèse 1 : Session callback échoue silencieusement
|
||||
Le session callback pourrait échouer avant d'atteindre les logs, causant une exception non gérée.
|
||||
|
||||
### Hypothèse 2 : Problème avec token.email ou token.name
|
||||
Si `token.email` ou `token.name` sont `undefined` et que le code s'attend à des valeurs, cela pourrait causer une erreur.
|
||||
|
||||
### Hypothèse 3 : Timeout ou problème de mémoire
|
||||
Le callback pourrait prendre trop de temps ou consommer trop de mémoire.
|
||||
|
||||
### Hypothèse 4 : Problème avec NEXTAUTH_URL ou NEXTAUTH_SECRET
|
||||
Configuration manquante ou incorrecte.
|
||||
|
||||
## ✅ Corrections Appliquées
|
||||
|
||||
### 1. Logs détaillés dans session callback
|
||||
- Logs au début et à la fin
|
||||
- Logs de chaque étape
|
||||
- Logs des valeurs de token
|
||||
|
||||
### 2. Try-catch complet
|
||||
- Capture toutes les erreurs
|
||||
- Logs détaillés de l'erreur
|
||||
- Stack trace complète
|
||||
|
||||
### 3. Validation des champs requis
|
||||
- Vérification de `token.sub` (user ID)
|
||||
- Gestion des valeurs `undefined`
|
||||
|
||||
### 4. Events NextAuth
|
||||
- `signIn` event pour tracker l'authentification
|
||||
- `error` event pour capturer les erreurs NextAuth
|
||||
- `signOut` event pour tracking
|
||||
|
||||
## 🔍 Prochaines Étapes d'Investigation
|
||||
|
||||
### Étape 1 : Vérifier les nouveaux logs
|
||||
|
||||
Après redémarrage du serveur, vous devriez voir :
|
||||
|
||||
```
|
||||
=== SESSION CALLBACK START ===
|
||||
Token error: undefined
|
||||
Has accessToken: true
|
||||
Has refreshToken: true
|
||||
Token role: [...]
|
||||
Token sub: ...
|
||||
...
|
||||
=== SESSION CALLBACK END ===
|
||||
```
|
||||
|
||||
**Si vous ne voyez PAS ces logs** :
|
||||
- Le session callback ne s'exécute pas du tout
|
||||
- Il y a une erreur avant d'atteindre le callback
|
||||
- Problème dans NextAuth lui-même
|
||||
|
||||
**Si vous voyez une erreur** :
|
||||
- Les logs détaillés indiqueront exactement où ça échoue
|
||||
|
||||
### Étape 2 : Vérifier les events NextAuth
|
||||
|
||||
Vous devriez voir :
|
||||
```
|
||||
=== NEXTAUTH SIGNIN EVENT ===
|
||||
User: ... ...
|
||||
Account: keycloak
|
||||
Profile: ...
|
||||
```
|
||||
|
||||
**Si vous voyez `=== NEXTAUTH ERROR EVENT ===`** :
|
||||
- L'erreur sera loggée avec détails
|
||||
|
||||
### Étape 3 : Vérifier les variables d'environnement
|
||||
|
||||
**Vérifier dans `.env` ou `.env.local`** :
|
||||
```bash
|
||||
NEXTAUTH_URL=https://hub.slm-lab.net
|
||||
NEXTAUTH_SECRET=... (doit être défini)
|
||||
KEYCLOAK_ISSUER=https://connect.slm-lab.net/realms/cercle
|
||||
KEYCLOAK_CLIENT_ID=...
|
||||
KEYCLOAK_CLIENT_SECRET=...
|
||||
```
|
||||
|
||||
**Commandes pour vérifier** :
|
||||
```bash
|
||||
# Vérifier que les variables sont chargées
|
||||
node -e "console.log(process.env.NEXTAUTH_URL)"
|
||||
node -e "console.log(process.env.NEXTAUTH_SECRET ? 'SET' : 'MISSING')"
|
||||
```
|
||||
|
||||
### Étape 4 : Vérifier les logs Nginx
|
||||
|
||||
**Si Nginx est devant Next.js**, vérifier les logs Nginx :
|
||||
```bash
|
||||
# Logs d'erreur Nginx
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
|
||||
# Logs d'accès Nginx
|
||||
sudo tail -f /var/log/nginx/access.log
|
||||
```
|
||||
|
||||
**Chercher** :
|
||||
- Timeout errors
|
||||
- Connection refused
|
||||
- Upstream errors
|
||||
|
||||
### Étape 5 : Vérifier les logs système
|
||||
|
||||
**Vérifier si Next.js crash** :
|
||||
```bash
|
||||
# Logs système
|
||||
journalctl -u nextjs -f
|
||||
|
||||
# Ou si PM2
|
||||
pm2 logs
|
||||
|
||||
# Ou si systemd
|
||||
systemctl status nextjs
|
||||
```
|
||||
|
||||
## 🛠️ Actions Immédiates
|
||||
|
||||
### 1. Redémarrer le serveur Next.js
|
||||
```bash
|
||||
# Arrêter
|
||||
pm2 stop neah
|
||||
# Ou
|
||||
systemctl stop nextjs
|
||||
|
||||
# Redémarrer
|
||||
pm2 start neah
|
||||
# Ou
|
||||
systemctl start nextjs
|
||||
```
|
||||
|
||||
### 2. Tester à nouveau la connexion
|
||||
|
||||
1. Aller sur `/signin`
|
||||
2. Se connecter avec Keycloak
|
||||
3. Observer les logs dans le terminal
|
||||
|
||||
### 3. Partager les logs complets
|
||||
|
||||
**Ce qu'il faut partager** :
|
||||
- Tous les logs depuis le début de la connexion
|
||||
- Les logs jusqu'à l'erreur 502
|
||||
- Les logs Nginx (si disponibles)
|
||||
- Les logs système (si disponibles)
|
||||
|
||||
## 🔧 Solutions Possibles
|
||||
|
||||
### Solution 1 : Problème avec token.email ou token.name
|
||||
|
||||
**Si les logs montrent** :
|
||||
```
|
||||
Token email: undefined
|
||||
Token name: undefined
|
||||
```
|
||||
|
||||
**Correction** : Le JWT callback doit extraire email et name depuis le profil ou le token d'accès.
|
||||
|
||||
### Solution 2 : Problème avec NEXTAUTH_URL
|
||||
|
||||
**Si NEXTAUTH_URL est incorrect** :
|
||||
- NextAuth ne peut pas construire les URLs de callback
|
||||
- Correction : Vérifier que `NEXTAUTH_URL` correspond à l'URL publique
|
||||
|
||||
### Solution 3 : Problème avec NEXTAUTH_SECRET
|
||||
|
||||
**Si NEXTAUTH_SECRET est manquant** :
|
||||
- NextAuth ne peut pas signer les JWT
|
||||
- Correction : Générer un secret et l'ajouter
|
||||
|
||||
### Solution 4 : Timeout
|
||||
|
||||
**Si le callback prend trop de temps** :
|
||||
- Augmenter les timeouts Nginx
|
||||
- Optimiser le code du callback
|
||||
|
||||
## 📊 Checklist de Debugging
|
||||
|
||||
- [ ] Serveur Next.js redémarré
|
||||
- [ ] Logs `=== SESSION CALLBACK START ===` visibles
|
||||
- [ ] Logs `=== SESSION CALLBACK END ===` visibles
|
||||
- [ ] Pas d'erreur dans les logs
|
||||
- [ ] Variables d'environnement vérifiées
|
||||
- [ ] Logs Nginx vérifiés (si applicable)
|
||||
- [ ] Logs système vérifiés (si applicable)
|
||||
|
||||
## 🎯 Ce qu'on cherche
|
||||
|
||||
**Dans les prochains logs, on cherche** :
|
||||
|
||||
1. **Si on voit `=== SESSION CALLBACK START ===`** :
|
||||
- ✅ Le callback s'exécute
|
||||
- Chercher l'erreur dans les logs suivants
|
||||
|
||||
2. **Si on NE voit PAS `=== SESSION CALLBACK START ===`** :
|
||||
- ❌ Le callback ne s'exécute pas
|
||||
- Problème dans NextAuth avant le callback
|
||||
- Vérifier les events NextAuth
|
||||
|
||||
3. **Si on voit `=== NEXTAUTH ERROR EVENT ===`** :
|
||||
- ✅ NextAuth a capturé une erreur
|
||||
- L'erreur sera loggée avec détails
|
||||
|
||||
---
|
||||
|
||||
**Document créé le** : $(date)
|
||||
**Statut** : En attente des nouveaux logs après redémarrage
|
||||
|
||||
@ -323,6 +323,17 @@ export const authOptions: NextAuthOptions = {
|
||||
token.username = keycloakProfile.preferred_username ?? '';
|
||||
token.first_name = keycloakProfile.given_name ?? '';
|
||||
token.last_name = keycloakProfile.family_name ?? '';
|
||||
// IMPORTANT: Set email and name for session callback
|
||||
token.email = keycloakProfile.email ?? null;
|
||||
token.name = keycloakProfile.name ?? keycloakProfile.preferred_username ?? null;
|
||||
|
||||
console.log('JWT token populated:', {
|
||||
hasSub: !!token.sub,
|
||||
hasEmail: !!token.email,
|
||||
hasName: !!token.name,
|
||||
hasUsername: !!token.username,
|
||||
rolesCount: cleanRoles.length,
|
||||
});
|
||||
|
||||
// Return immediately on initial sign-in - don't try to refresh tokens we just received
|
||||
return token;
|
||||
@ -392,12 +403,16 @@ export const authOptions: NextAuthOptions = {
|
||||
return refreshedToken;
|
||||
},
|
||||
async session({ session, token }) {
|
||||
console.log('=== SESSION CALLBACK ===');
|
||||
try {
|
||||
console.log('=== SESSION CALLBACK START ===');
|
||||
console.log('Token error:', token.error);
|
||||
console.log('Has accessToken:', !!token.accessToken);
|
||||
console.log('Has refreshToken:', !!token.refreshToken);
|
||||
console.log('Token role:', token.role);
|
||||
console.log('Token sub:', token.sub);
|
||||
console.log('Token email:', token.email);
|
||||
console.log('Token name:', token.name);
|
||||
console.log('Token username:', token.username);
|
||||
|
||||
// If session was invalidated or tokens are missing, return null to sign out
|
||||
if (token.error === "SessionNotActive" ||
|
||||
@ -426,9 +441,15 @@ export const authOptions: NextAuthOptions = {
|
||||
const userRoles = Array.isArray(token.role) ? token.role : [];
|
||||
console.log('User roles for session:', userRoles);
|
||||
|
||||
try {
|
||||
// Validate required fields
|
||||
if (!token.sub) {
|
||||
console.error('❌ Missing token.sub (user ID)');
|
||||
throw new Error('Missing user ID in token');
|
||||
}
|
||||
|
||||
console.log('Creating session user object...');
|
||||
session.user = {
|
||||
id: (token.sub ?? '') as string,
|
||||
id: token.sub as string,
|
||||
email: (token.email ?? null) as string | null,
|
||||
name: (token.name ?? null) as string | null,
|
||||
image: null,
|
||||
@ -438,15 +459,31 @@ export const authOptions: NextAuthOptions = {
|
||||
role: userRoles,
|
||||
nextcloudInitialized: false,
|
||||
};
|
||||
|
||||
console.log('Setting session tokens...');
|
||||
session.accessToken = token.accessToken as string | undefined;
|
||||
session.idToken = token.idToken as string | undefined;
|
||||
session.refreshToken = token.refreshToken as string | undefined;
|
||||
|
||||
console.log('✅ Session created successfully');
|
||||
console.log('==============================');
|
||||
console.log('Session user id:', session.user.id);
|
||||
console.log('Session user email:', session.user.email);
|
||||
console.log('Session user roles:', session.user.role);
|
||||
console.log('=== SESSION CALLBACK END ===');
|
||||
return session;
|
||||
} catch (error) {
|
||||
console.error('❌ Error creating session:', error);
|
||||
console.error('❌❌❌ CRITICAL ERROR IN SESSION CALLBACK ❌❌❌');
|
||||
console.error('Error type:', error instanceof Error ? error.constructor.name : typeof error);
|
||||
console.error('Error message:', error instanceof Error ? error.message : String(error));
|
||||
console.error('Error stack:', error instanceof Error ? error.stack : 'No stack trace');
|
||||
console.error('Token state:', {
|
||||
hasSub: !!token.sub,
|
||||
hasEmail: !!token.email,
|
||||
hasAccessToken: !!token.accessToken,
|
||||
hasRefreshToken: !!token.refreshToken,
|
||||
role: token.role,
|
||||
});
|
||||
// Re-throw to let NextAuth handle it
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -456,6 +493,23 @@ export const authOptions: NextAuthOptions = {
|
||||
error: '/signin',
|
||||
},
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
// Add error handling events
|
||||
events: {
|
||||
async signIn({ user, account, profile }) {
|
||||
console.log('=== NEXTAUTH SIGNIN EVENT ===');
|
||||
console.log('User:', user?.id, user?.email);
|
||||
console.log('Account:', account?.provider);
|
||||
console.log('Profile:', profile?.sub);
|
||||
return true;
|
||||
},
|
||||
async signOut() {
|
||||
console.log('=== NEXTAUTH SIGNOUT EVENT ===');
|
||||
},
|
||||
async error({ error }) {
|
||||
console.error('=== NEXTAUTH ERROR EVENT ===');
|
||||
console.error('Error:', error);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// JWT interface is declared in the module declaration above
|
||||
|
||||
Loading…
Reference in New Issue
Block a user