NeahNew/IFRAME_LOGOUT_AUTO_LOGIN_ANALYSIS.md

8.4 KiB

Iframe Logout Auto-Login Issue Analysis

Problem

When you log out from an iframe application, you are automatically logged back into the dashboard without being prompted for credentials.

Flow Trace

Scenario: User Logs Out from Iframe Application

Step 1: Iframe Application Logout

Location: Iframe application (e.g., /parole, /gite, etc.)
Action: User clicks logout in iframe

What happens:
- Iframe app may call Keycloak logout endpoint directly
- OR: Iframe app sends postMessage to parent: { type: 'KEYCLOAK_LOGOUT' }
- OR: Iframe app clears its own session cookies

Step 2A: If Iframe Sends PostMessage (Expected Flow)

Location: components/layout/layout-wrapper.tsx (line 26-106)
OR: app/components/responsive-iframe.tsx (line 110-153)

Action: Dashboard receives logout message

What happens:
1. Sets sessionStorage.setItem('just_logged_out', 'true')
2. Sets document.cookie = 'logout_in_progress=true; path=/; max-age=60'
3. Calls /api/auth/end-sso-session (Admin API)
4. Calls signOut() from NextAuth
5. Redirects to Keycloak logout endpoint
6. Keycloak redirects back to /signin?logout=true

Step 2B: If Iframe Calls Keycloak Logout Directly (Actual Flow - Problem)

Location: Iframe application

Action: Iframe calls Keycloak logout endpoint directly

What happens:
1. Iframe redirects to: ${KEYCLOAK_ISSUER}/protocol/openid-connect/logout
2. Keycloak clears session cookies
3. Keycloak may redirect iframe back to its own logout page
4. Dashboard doesn't know about this logout
5. Dashboard still has NextAuth session (valid for 30 days)

Step 3: Dashboard Detects Session Invalidation

Location: app/api/auth/options.ts (refreshAccessToken function)

When: NextAuth tries to refresh the access token

What happens:
1. Dashboard calls Keycloak token refresh endpoint
2. Keycloak returns: { error: 'invalid_grant', error_description: 'Session not active' }
3. refreshAccessToken detects this error (line 100-108)
4. Returns token with error: "SessionNotActive"
5. JWT callback clears tokens (line 248-256)
6. Session callback returns null (line 272-276)
7. NextAuth treats user as unauthenticated
8. Status becomes "unauthenticated"

Step 4: Sign-In Page Auto-Login (THE PROBLEM)

Location: app/signin/page.tsx (line 47-79)

When: User is redirected to /signin (or status becomes "unauthenticated")

What happens:
1. Component mounts
2. First useEffect (line 16-45) checks for logout flag
   - If logout=true in URL, sets isLogoutRedirect.current = true
   - Removes 'just_logged_out' from sessionStorage
3. Second useEffect (line 47-79) checks authentication status
   - If status === "authenticated" → redirects to home ✅
   - If status === "unauthenticated" → triggers auto-login ❌

THE PROBLEM:
- When iframe logs out directly (not via postMessage), dashboard doesn't set logout flags
- Status becomes "unauthenticated" (because Keycloak session was cleared)
- Sign-in page sees status === "unauthenticated"
- Auto-login logic triggers after 1 second (line 69)
- signIn("keycloak") is called
- Keycloak still has SSO session cookie (if it wasn't fully cleared)
- User is auto-authenticated without credentials ❌

Root Cause Analysis

Problem 1: Missing Logout Flags

When iframe logs out directly (not via postMessage):

  • Dashboard doesn't know about the logout
  • just_logged_out is NOT set in sessionStorage
  • logout_in_progress cookie is NOT set
  • Sign-in page doesn't know this is a logout scenario

Result: Sign-in page treats it as a normal "unauthenticated" state and triggers auto-login.

Problem 2: Auto-Login Logic Timing

Sign-in page auto-login logic (app/signin/page.tsx:66-78):

if (status === "unauthenticated") {
  hasAttemptedLogin.current = true;
  const timer = setTimeout(() => {
    if (!isLogoutRedirect.current) {
      signIn("keycloak", { callbackUrl: "/" });
    }
  }, 1000);
}

The Issue:

  • isLogoutRedirect.current is set in the first useEffect (line 16-45)
  • But it only checks for logout=true in URL or just_logged_out in sessionStorage
  • If iframe logs out directly, neither of these is set
  • After 1 second, auto-login triggers
  • isLogoutRedirect.current is still false (because logout flags weren't set)
  • signIn("keycloak") is called
  • User is auto-authenticated

Even if logout flags are set correctly:

  • Keycloak SSO session cookie (KEYCLOAK_SESSION) may still exist
  • When signIn("keycloak") is called, Keycloak checks for SSO session cookie
  • If cookie exists, Keycloak auto-authenticates without credentials
  • This happens even with prompt=login parameter (if SSO session is still valid)

Why This Happens

Flow 1: Iframe Logs Out via PostMessage (Works Correctly)

1. Iframe sends postMessage → Dashboard receives it
2. Dashboard sets logout flags ✅
3. Dashboard calls logout endpoints ✅
4. Redirects to /signin?logout=true ✅
5. Sign-in page sees logout=true ✅
6. Auto-login is prevented ✅
7. User must click "Se connecter" manually ✅

Flow 2: Iframe Logs Out Directly (THE PROBLEM)

1. Iframe calls Keycloak logout directly
2. Keycloak clears session cookies
3. Dashboard doesn't know about logout ❌
4. NextAuth tries to refresh token
5. Keycloak returns "Session not active"
6. NextAuth marks user as unauthenticated
7. User is redirected to /signin (no logout=true) ❌
8. Sign-in page sees status="unauthenticated" ❌
9. Auto-login triggers after 1 second ❌
10. Keycloak still has SSO session cookie ❌
11. User is auto-authenticated ❌

The Real Issue

The sign-in page auto-login logic is too aggressive:

  1. It triggers auto-login for ANY "unauthenticated" state

  2. It doesn't distinguish between:

    • User never logged in (should auto-login)
    • User logged out (should NOT auto-login)
    • Session expired (should NOT auto-login)
    • Keycloak session invalidated (should NOT auto-login)
  3. The logout detection only works if:

    • logout=true is in URL (from Keycloak redirect)
    • just_logged_out is in sessionStorage (from dashboard logout)
    • But NOT if iframe logs out directly

Solution Requirements

To fix this issue, you need to:

  1. Detect Keycloak Session Invalidation:

    • When NextAuth detects "SessionNotActive" error
    • Set a flag to prevent auto-login
    • Mark this as a logout scenario, not a new login
  2. Improve Logout Detection:

    • Check for Keycloak session cookie existence
    • If session was invalidated (not just expired), prevent auto-login
    • Store logout reason in sessionStorage
  3. Modify Auto-Login Logic:

    • Only auto-login if:
      • User is truly unauthenticated (never logged in)
      • AND no logout flags are set
      • AND no session invalidation detected
    • Don't auto-login if:
      • Logout flags are set
      • Session was invalidated
      • User came from a logout flow
  4. Handle Iframe Direct Logout:

    • Detect when Keycloak session is invalidated
    • Set logout flags automatically
    • Prevent auto-login

Current Code Issues

Issue 1: Auto-Login Logic (app/signin/page.tsx:66-78)

if (status === "unauthenticated") {
  // This triggers for ANY unauthenticated state
  // Doesn't check if session was invalidated
  signIn("keycloak", { callbackUrl: "/" });
}

Issue 2: Logout Detection (app/signin/page.tsx:16-45)

// Only checks for explicit logout flags
// Doesn't detect session invalidation
const logoutParam = searchParams.get('logout');
const fromLogout = sessionStorage.getItem('just_logged_out');

Issue 3: Session Invalidation Detection (app/api/auth/options.ts:248-256)

// Detects session invalidation
// But doesn't set logout flags
// Sign-in page doesn't know session was invalidated
if (refreshedToken.error === "SessionNotActive") {
  return {
    ...refreshedToken,
    accessToken: undefined,
    // Should set a flag here to prevent auto-login
  };
}

Summary

Why you're auto-logged in after iframe logout:

  1. Iframe logs out directly (not via postMessage)
  2. Keycloak session is cleared
  3. Dashboard detects session invalidation
  4. User becomes "unauthenticated"
  5. Sign-in page auto-login logic triggers (after 1 second)
  6. Keycloak still has SSO session cookie
  7. User is auto-authenticated without credentials

The fix requires:

  • Detecting session invalidation and setting logout flags
  • Preventing auto-login when session was invalidated
  • Only auto-login for truly new users (never logged in)