6.9 KiB
SSO Flow Analysis - Confirmed Issues
Browser Console Evidence
Based on the browser console error provided, here's what's happening:
Confirmed Flow
-
User logs out from Keycloak directly (external application)
- Keycloak invalidates all tokens and session
-
User accesses Dashboard
- NextAuth session still exists (30-day expiration)
- JWT contains old, now-invalid tokens
- Token expiration check:
Date.now() < token.accessTokenExpires * 1000 - If token hasn't expired by timestamp → JWT callback returns old token
- Problem: Token is invalid in Keycloak, but NextAuth doesn't validate it
-
User navigates to iframe application
ResponsiveIframecomponent mounts- Calls
GET /api/auth/refresh-keycloak-session - Refresh endpoint uses old
refreshTokenfrom session - Keycloak responds:
{ error: 'invalid_grant', error_description: 'Token is not active' } - Returns 401 with
SessionInvalidatederror
-
Redirect to Signin
ResponsiveIframedetectsSessionInvalidated- Redirects:
window.location.href = '/signin' - User lands on signin page
-
Signin Process Starts
app/signin/page.tsxdetects unauthenticated status- Triggers:
signIn("keycloak", { callbackUrl: "/" }) - User authenticates with Keycloak
- Gets NEW tokens from Keycloak
- NextAuth callback stores new tokens in JWT
-
Storage Initialization Fails ⚠️ CONFIRMED ISSUE
- Signin page detects session available
- Calls:
POST /api/storage/init - Storage endpoint tries to call:
createUserFolderStructure(session.user.id) - Error:
createUserFolderStructure is not a function - Storage initialization fails
- Signin page shows "Échec de l'initialisation"
- Impact: User might not be fully signed in, or session might not be complete
-
User Returns to Iframe (After Signin)
- Navigates to iframe application again
ResponsiveIframecomponent mounts- Calls refresh endpoint again
- If storage init failed: Session might not be fully established
- If new session not ready: Might still use old tokens
- Refresh fails again → Redirects to signin → Loop
Confirmed Issues
Issue 1: Storage Initialization Failure ✅ CONFIRMED
Error: createUserFolderStructure is not a function
Location: app/api/storage/init/route.ts:16
Impact on SSO Flow:
- Storage initialization is part of signin process
- If it fails, signin might not complete properly
- Session might not be fully established
- When user tries to access iframe, refresh endpoint might fail because:
- Session not complete
- Or still using old tokens if new session wasn't saved
Evidence from Browser:
Failed to initialize storage: "{\"error\":\"Failed to initialize storage\",\"details\":\"(0 , _lib_s3__WEBPACK_IMPORTED_MODULE_3__.createUserFolderStructure) is not a function\"}"
Issue 2: Stale Token in NextAuth JWT ✅ CONFIRMED
Problem: When Keycloak session is invalidated externally:
- NextAuth JWT still contains old tokens
- JWT callback only checks expiration timestamp
- Doesn't validate with Keycloak that token is still valid
- Returns stale token until expiration timestamp is reached
Evidence from Terminal:
Failed to refresh Keycloak session: { error: 'invalid_grant', error_description: 'Token is not active' }
GET /api/auth/refresh-keycloak-session 401
Issue 3: Race Condition After Re-authentication ✅ CONFIRMED
Problem: After user signs in again:
- New session is created
- But refresh endpoint might be called before:
- JWT callback has run with new account
- New tokens are stored in JWT
- Session cookie is updated in browser
- Result: Refresh endpoint still uses old tokens
Evidence: Multiple failed refresh attempts after signin
Complete Flow Diagram (Confirmed)
1. User logs out from Keycloak (external)
↓
2. Keycloak invalidates:
- Session cookies ✅
- Refresh token ✅
- Access token ✅
↓
3. User accesses Dashboard
- NextAuth JWT has old tokens (not expired by timestamp)
- JWT callback returns old token (doesn't validate with Keycloak)
↓
4. User navigates to iframe
- ResponsiveIframe calls refresh endpoint
- Uses old refreshToken from session
↓
5. Keycloak rejects: "Token is not active"
↓
6. Refresh endpoint returns 401 SessionInvalidated
↓
7. Redirect to /signin
↓
8. User authenticates with Keycloak
- Gets NEW tokens
- NextAuth stores new tokens in JWT
↓
9. Storage initialization called
- ⚠️ FAILS: createUserFolderStructure not found
- Signin process incomplete
↓
10. User navigates to iframe again
- Refresh endpoint called
- ⚠️ Might still use old tokens (if new session not ready)
- OR: Session incomplete due to storage init failure
- Fails again → Redirects to signin
↓
11. LOOP or stuck state
Root Causes (Confirmed)
-
No Proactive Token Validation
- NextAuth only checks expiration timestamps
- Doesn't validate tokens with Keycloak
- Stale tokens remain in JWT until timestamp expiration
-
Storage Initialization Failure
- Missing function:
createUserFolderStructure - Prevents complete signin initialization
- May cause session to be incomplete
- Missing function:
-
Race Condition
- Refresh endpoint called before new session fully established
- Browser might send old session cookie
- JWT callback might not have run yet with new account
-
No Session Invalidation on External Logout
- When Keycloak session invalidated externally
- NextAuth doesn't know about it
- Continues using invalid tokens
Impact on User Experience
What User Sees:
- Logs out from Keycloak (external app)
- Accesses Dashboard → Still logged in (NextAuth session valid)
- Tries to access iframe application
- Gets redirected to signin
- Signs in again
- Storage initialization fails (error message)
- Tries to access iframe again
- Gets redirected to signin again
- Stuck in loop or keeps getting disconnected
Recommendations
Immediate Fixes Needed
-
Fix Storage Initialization
- Export
createUserFolderStructurefromlib/s3.ts - Or remove storage init from signin flow if not critical
- Prevents signin from failing
- Export
-
Proactive Token Validation
- Before using tokens, validate with Keycloak
- Use Keycloak's userinfo endpoint to check token validity
- Clear session if token invalid
-
Session Invalidation on Refresh Failure
- When refresh fails with invalid_grant
- Immediately clear NextAuth session cookie
- Force complete re-authentication
-
Delay Refresh After Signin
- After redirect from signin, wait for session to be established
- Check session status before calling refresh endpoint
- Add retry logic with backoff
Analysis Date: 2024
Status: Issues Confirmed
Evidence: Browser console + Terminal logs