Skip to main content

Authentication Flow

This document describes the complete authentication flow architecture implemented in the CIVITAS Core v2 platform using modern OAuth2/OIDC standards with Keycloak as the identity provider.

Overview

The authentication system implements a secure OAuth2/OIDC flow with Keycloak integration, JWT-based session management, and comprehensive route protection. The architecture follows the Backend-For-Frontend (BFF) pattern with security-by-design principles, ensuring that sensitive tokens never reach the client-side while providing a seamless user experience across the platform.

JWT Token Architecture (Backend-For-Frontend Pattern)

The system employs a secure Backend-For-Frontend (BFF) architecture with two distinct types of JWT tokens:

  • Keycloak JWT Access Token: The actual access token issued by Keycloak, used for authenticating API calls to backend services. This JWT contains user claims and permissions for resource access. These tokens are never exposed to client-side JavaScript.
  • NextAuth Session JWT: A separate JWT created by NextAuth that wraps the Keycloak tokens (access_token, refresh_token) plus session metadata. This JWT is stored in the HTTP-only session cookie and acts as an opaque session identifier from the client's perspective.

Security Model

Client-Side Access:

  • Client receives session data (user info, authentication status) but no tokens (access token or refresh token)
  • Session cookie acts as an opaque identifier - client cannot decrypt or access tokens within it
  • All token operations happen exclusively server-side

Server-Side Access:

  • Server-side code can access tokens through NextAuth's JWT callback system
  • API routes and server components can retrieve tokens for backend authentication
  • Token refresh happens automatically server-side without client involvement

When making authenticated API calls to backend services, tokens are accessed server-side only and never transmitted to the client.

Authentication Flow Sequence Diagram

Flow Description

1. Initial Access Attempt

When a user attempts to access a protected resource, the platform's middleware layer intercepts the request and validates the user's authentication status. If no valid session exists, the user is automatically redirected to the login interface, ensuring that protected resources remain secure while providing a smooth user experience.

2. Login Initiation

The login interface presents users with authentication options, prominently featuring Keycloak integration. This centralized approach ensures consistent authentication across all platform components and leverages identity management capabilities.

3. OAuth2/OIDC Flow

The platform implements the standard OAuth2 Authorization Code flow with OIDC extensions, providing robust security through:

  • Authorization Code Exchange: Prevents token exposure in browser history
  • State Parameter Validation: Protects against CSRF attacks
  • PKCE Support: Enhances security for public clients
  • Scope-based Access Control: Enables fine-grained permission management

4. Token Exchange and Management

Upon successful authentication, the system securely exchanges the authorization code for access tokens, refresh tokens, and identity tokens. This server-to-server communication ensures that sensitive credentials never traverse the client-side environment.

5. Session Architecture

The platform employs a hybrid session management approach:

  • JWT-based Storage: Enables stateless authentication and horizontal scaling
  • Secure Cookie Delivery: HTTP-only, secure cookies prevent XSS attacks
  • Token Encapsulation: NextAuth embeds access and refresh tokens in its own signed JWT payload, which is then stored in an HTTP-only cookie

Token Refresh Mechanism

The system uses an event-based token refresh approach where tokens are refreshed when the jwt() callback is invoked during requests. When an access token expires, the JWT callback triggers a refresh request to Keycloak's token endpoint. After successful token refresh, NextAuth re-issues the session cookie with the updated token to maintain session continuity. If the refresh fails, the session receives a "RefreshTokenError" and the user must re-authenticate.

Automatic Session Refresh

The platform implements a proactive session refresh system to prevent unexpected logouts:

Proactive Refresh: Client-side session provider configured with 4-minute intervals automatically refreshes tokens before expiration, ensuring seamless user experience.

Activity-Based Refresh: User interaction monitoring detects activity (mouse, keyboard, scroll, touch) and triggers session refresh when users are active, resetting refresh timers based on activity patterns.

Retry Logic: Token refresh mechanism includes retry system with maximum 3 attempts and automatic counter reset on successful refresh, preventing infinite loops while ensuring reliability.

Implementation Features:

  • Invisible session management component that activates activity detection across the application
  • Activity detection with 2-minute cooldown between refresh attempts
  • Enhanced token callback with retry counter and attempt limits

This ensures users remain logged in as long as they stay active, with tokens refreshed proactively before expiration.

6. Route Protection and Access Control

A comprehensive middleware system ensures that:

  • All protected routes require valid authentication
  • Public endpoints remain accessible without authentication
  • Session validation occurs transparently for each request
  • Invalid or expired sessions trigger automatic re-authentication

7. Ongoing Session Management

Authenticated users enjoy seamless access to protected resources through persistent session cookies. The system validates sessions on each request while maintaining optimal performance through efficient token validation mechanisms.

Logout Flow

The platform implements a secure dual logout mechanism that terminates both the NextAuth session and the Keycloak session simultaneously, preventing silent re-authentication and ensuring complete session cleanup.

Logout Sequence Diagram

Implementation Details

NextAuth Events Callback: The logout process uses NextAuth's signOut event handler in auth.config.ts to automatically trigger Keycloak logout when the local session is destroyed.

ID Token Hint: The stored ID token (id_token_hint) is sent to Keycloak's logout endpoint, enabling automatic session termination without user confirmation dialogs.

Simultaneous Execution: Both logout processes happen in parallel - NextAuth destroys the local session while the event handler terminates the Keycloak session server-side.

Security Aspects

  • Complete Session Termination: Both application and identity provider sessions are properly destroyed
  • Prevention of Silent Re-authentication: Keycloak cannot automatically log users back in on subsequent authentication attempts
  • Seamless User Experience: No logout confirmation pages or intermediate redirects
  • Server-side Security: Logout requests are made server-to-server, never exposing tokens to the client

Key Components

Middleware Layer

The middleware component intercepts all requests and applies authentication policies. It handles route protection by distinguishing between public paths (login, API authentication endpoints) and protected routes that require valid user sessions. The middleware applies authentication to all routes except API endpoints, static assets, images, and files with extensions.

Authorization Logic

The system implements authorization checks that verify user authentication status and determine access permissions. When users are not authenticated, they are redirected to the login interface, while authenticated users can access protected resources.

JWT Token Management

The platform uses JWT callbacks to handle token lifecycle:

  • Stores access tokens, refresh tokens, ID tokens, and expiration information within JWT payloads
  • Manages token persistence and retrieval for session validation
  • Handles token-based authentication across requests
  • ID tokens enable seamless logout by providing id_token_hint to Keycloak
  • Session maximum age: 30 days
  • Token expiration check includes 60-second buffer before actual expiry
  • Access tokens are refreshed automatically when expired

Session Management (BFF Pattern)

Session handling creates and maintains user sessions by:

  • Never exposing access tokens to client applications - tokens remain server-side only
  • Managing secure HTTP-only cookie storage that acts as opaque session identifiers
  • Coordinating session creation with JWT token management while maintaining client-side security
  • Dual logout mechanism through NextAuth events to terminate both local and Keycloak sessions
  • Providing server-side token access utilities for API routes and server components when backend authentication is needed