NeahNew/AUTHENTICATION_FIXES.md
2026-01-01 17:40:16 +01:00

6.5 KiB

Authentication Flow Fixes

Issues Fixed

1. Logout Loop Issue

Problem:

  • User couldn't log out - infinite redirect loop
  • Sign-in page auto-triggered Keycloak login even when user was already authenticated
  • Keycloak session cookies weren't cleared, causing immediate re-authentication

Root Cause:

  • /signin page had useEffect(() => { signIn("keycloak") }, []) that always triggered login
  • No check for existing authentication status
  • Keycloak logout endpoint was never called, leaving Keycloak cookies valid

Fix Applied:

  1. Sign-in page (app/signin/page.tsx):

    • Added check for existing session before triggering login
    • If user is already authenticated, redirect to home
    • Only trigger Keycloak login if status is "unauthenticated"
  2. Sign-out handler (components/auth/signout-handler.tsx):

    • Now properly calls Keycloak logout endpoint
    • Uses ID token for proper logout
    • Clears both NextAuth and Keycloak cookies
  3. Main navigation logout (components/main-nav.tsx):

    • Fixed to use idToken instead of accessToken for Keycloak logout
    • Proper logout flow with Keycloak endpoint

2. Iframe Applications Logging Out

Problem:

  • Iframe applications were logging out even when user was still authenticated in dashboard
  • Desynchronization between NextAuth session and Keycloak session

Root Cause:

  • Sign-out only cleared NextAuth cookies
  • Keycloak session cookies remained valid but could expire independently
  • Iframe apps rely on Keycloak cookies for SSO
  • When Keycloak cookies expired/invalidated, iframes logged out but dashboard stayed logged in

Fix Applied:

  1. ID Token Storage (app/api/auth/options.ts):

    • Now stores idToken from Keycloak in JWT
    • Exposes idToken in session object
    • Preserves ID token during token refresh
  2. Proper Keycloak Logout:

    • Sign-out now calls Keycloak logout endpoint with id_token_hint
    • This properly invalidates Keycloak session and clears Keycloak cookies
    • Ensures synchronization between dashboard and iframe apps
  3. Type Definitions (types/next-auth.d.ts):

    • Added idToken to Session and JWT interfaces
    • Type-safe access to ID token

Changes Made

Files Modified

  1. app/api/auth/options.ts

    • Added idToken to JWT interface
    • Store account.id_token in JWT during initial authentication
    • Expose idToken in session callback
    • Preserve idToken during token refresh
  2. app/signin/page.tsx

    • Added session status check
    • Prevent auto-login if already authenticated
    • Redirect authenticated users to home
  3. components/auth/signout-handler.tsx

    • Call Keycloak logout endpoint with ID token
    • Proper logout flow that clears both NextAuth and Keycloak sessions
  4. components/main-nav.tsx

    • Fixed logout button to use idToken instead of accessToken
    • Proper Keycloak logout flow
  5. types/next-auth.d.ts

    • Added idToken?: string to Session interface
    • Added idToken?: string to JWT interface (both modules)

How It Works Now

Sign-In Flow (Fixed)

1. User navigates to /signin
2. Check session status:
   - If authenticated → Redirect to /
   - If unauthenticated → Trigger Keycloak login
3. After Keycloak authentication:
   - Store tokens (access, refresh, ID token)
   - Initialize storage
   - Redirect to dashboard

Sign-Out Flow (Fixed)

1. User clicks logout
2. Sign out from NextAuth (clears NextAuth cookies)
3. Call Keycloak logout endpoint:
   - URL: ${KEYCLOAK_ISSUER}/protocol/openid-connect/logout
   - Parameters:
     * post_logout_redirect_uri: /signin
     * id_token_hint: <ID token from session>
4. Keycloak clears its session and cookies
5. Redirect to /signin (no auto-login loop)

Iframe SSO (Fixed)

1. User authenticates in dashboard
2. Keycloak sets session cookies
3. Iframe apps read Keycloak cookies
4. When user logs out:
   - Keycloak logout endpoint is called
   - Keycloak cookies are cleared
   - Iframe apps lose access (synchronized logout)

Environment Variables Required

Ensure these are set:

# Required for logout
NEXT_PUBLIC_KEYCLOAK_ISSUER=https://keycloak.example.com/realms/neah

# Already required for authentication
KEYCLOAK_CLIENT_ID=neah-dashboard
KEYCLOAK_CLIENT_SECRET=<secret>
KEYCLOAK_ISSUER=https://keycloak.example.com/realms/neah
NEXTAUTH_URL=https://dashboard.example.com
NEXTAUTH_SECRET=<secret>

Important: NEXT_PUBLIC_KEYCLOAK_ISSUER must be set for client-side logout to work.


Testing Checklist

Logout Flow

  • Click logout button
  • Should redirect to Keycloak logout
  • Should redirect back to /signin
  • Should NOT auto-login (no loop)
  • Should be able to manually log in again

Sign-In Flow

  • Navigate to /signin when not authenticated
  • Should trigger Keycloak login
  • Navigate to /signin when already authenticated
  • Should redirect to / (no auto-login trigger)

Iframe SSO

  • Log in to dashboard
  • Open iframe application
  • Should be automatically authenticated
  • Log out from dashboard
  • Iframe application should also lose authentication
  • Refresh iframe - should require login

Additional Notes

ID Token vs Access Token

  • Access Token: Used for API calls to Keycloak-protected resources
  • ID Token: Used for user identification and logout
  • Refresh Token: Used to get new access tokens

The ID token is required for proper Keycloak logout. It tells Keycloak which session to invalidate.

The fix ensures that:

  1. NextAuth cookies are cleared (dashboard logout)
  2. Keycloak cookies are cleared (via logout endpoint)
  3. Both happen in sequence, maintaining synchronization

Token Refresh

During token refresh, the ID token is preserved (Keycloak doesn't issue new ID tokens on refresh). This ensures logout continues to work even after token refreshes.


Troubleshooting

If logout still loops:

  1. Check browser console for errors
  2. Verify NEXT_PUBLIC_KEYCLOAK_ISSUER is set correctly
  3. Check that Keycloak logout endpoint is accessible
  4. Verify ID token is present in session: console.log(session?.idToken)

If iframes still log out independently:

  1. Check Keycloak cookie domain configuration
  2. Verify iframe apps are configured to use same Keycloak realm
  3. Check browser cookie settings (third-party cookies may be blocked)
  4. Verify Keycloak session timeout settings

Date: 2024
Status: Fixed
Version: 1.0