NeahNew/SSO_FLOW_CONFIRMED.md
2026-01-02 14:32:36 +01:00

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

  1. User logs out from Keycloak directly (external application)

    • Keycloak invalidates all tokens and session
  2. 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
  3. User navigates to iframe application

    • ResponsiveIframe component mounts
    • Calls GET /api/auth/refresh-keycloak-session
    • Refresh endpoint uses old refreshToken from session
    • Keycloak responds: { error: 'invalid_grant', error_description: 'Token is not active' }
    • Returns 401 with SessionInvalidated error
  4. Redirect to Signin

    • ResponsiveIframe detects SessionInvalidated
    • Redirects: window.location.href = '/signin'
    • User lands on signin page
  5. Signin Process Starts

    • app/signin/page.tsx detects unauthenticated status
    • Triggers: signIn("keycloak", { callbackUrl: "/" })
    • User authenticates with Keycloak
    • Gets NEW tokens from Keycloak
    • NextAuth callback stores new tokens in JWT
  6. 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
  7. User Returns to Iframe (After Signin)

    • Navigates to iframe application again
    • ResponsiveIframe component 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)

  1. No Proactive Token Validation

    • NextAuth only checks expiration timestamps
    • Doesn't validate tokens with Keycloak
    • Stale tokens remain in JWT until timestamp expiration
  2. Storage Initialization Failure

    • Missing function: createUserFolderStructure
    • Prevents complete signin initialization
    • May cause session to be incomplete
  3. 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
  4. 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:

  1. Logs out from Keycloak (external app)
  2. Accesses Dashboard → Still logged in (NextAuth session valid)
  3. Tries to access iframe application
  4. Gets redirected to signin
  5. Signs in again
  6. Storage initialization fails (error message)
  7. Tries to access iframe again
  8. Gets redirected to signin again
  9. Stuck in loop or keeps getting disconnected

Recommendations

Immediate Fixes Needed

  1. Fix Storage Initialization

    • Export createUserFolderStructure from lib/s3.ts
    • Or remove storage init from signin flow if not critical
    • Prevents signin from failing
  2. Proactive Token Validation

    • Before using tokens, validate with Keycloak
    • Use Keycloak's userinfo endpoint to check token validity
    • Clear session if token invalid
  3. Session Invalidation on Refresh Failure

    • When refresh fails with invalid_grant
    • Immediately clear NextAuth session cookie
    • Force complete re-authentication
  4. 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