contexa-identity

State Management

Post-authentication state management strategy. Choose between Session (server memory/Redis) or OAuth2 (JWT Stateless). Each authentication method can be independently configured with a different state.

Overview

Configure state by calling .session() or .oauth2() after an authentication method in the DSL. The AbstractFlowRegistrar.StateSetter applies the state to the most recently added flow.

registry
    .form(f -> f.loginPage("/login"))
    .session(Customizer.withDefaults())      // form -> Session

    .rest(r -> r.loginProcessingUrl("/api/auth"))
    .oauth2(Customizer.withDefaults())        // rest -> OAuth2

    .mfa(m -> m.primaryAuthentication(...).passkey(...))
    .session(Customizer.withDefaults())        // mfa -> Session

    .build();

Session vs OAuth2 Comparison

CategorySessionOAuth2
State StorageServer memory by default, with optional shared Redis-backed storage in distributed deploymentsJWT token (Stateless)
Suitable ForTraditional web apps, SSRSPA, API, Microservices
ScalabilityWorks with in-memory session state by default; Redis-backed sharing is optional for multi-instance deploymentsStateless (easy horizontal scaling)
Built-in SecuritySession fixation protection (sessionFixation().changeSessionId())JWT + OIDC + Zero Trust Filter
CSRFRequired (cookie-based)Not required (token-based)
LogoutSession invalidation + cookie deletionAuthorization invalidation via CompositeLogoutHandler and DeviceAwareOAuth2AuthorizationService

Session-Based

Configured via .session(Customizer.withDefaults()). Suitable for traditional web applications and server-side rendering.

Auto-Applied

  • sessionFixation().changeSessionId() — Session fixation attack protection
  • Session invalidation + cookie deletion on logout
  • CompositeLogoutHandler integration (Strategy pattern)

Additional Configuration via rawHttp

.form(f -> f
    .rawHttp(http -> http.sessionManagement(s -> s
        .maximumSessions(1)
        .maxSessionsPreventsLogin(true)))
)
.session(Customizer.withDefaults())

OAuth2-Based

Configured via .oauth2(Customizer.withDefaults()). Suitable for SPA, microservices, and API servers.

Auto-Applied

  • Resource Server: JWT authentication converter, authentication failure/access denied handlers, SessionCreationPolicy.STATELESS
  • Authorization Server: AuthorizationService, ClientRepository, token endpoint, authenticated_user grant type, OIDC support
  • OAuth2 CSRF: Controlled by the spring.auth.oauth2-csrf configuration

authenticated_user Grant Type

A custom grant type that issues OAuth2 tokens to users who have completed Identity authentication (Form, REST, MFA). It bridges traditional authentication with OAuth2 token issuance.


  authenticated_user Grant Flow
  ===============================

  [Form/REST/MFA Authentication Complete]
           |
           v
  [AuthenticatedUserGrantAuthenticationProvider]
           |
           +-- Client Verification
           +-- User Lookup (UserRepository)
           +-- Scope Resolution
           +-- Access Token Generation (JWT)
           +-- Refresh Token Generation (optional)
           +-- Authorization Persistence (transactional)
           |
           v
  [JWT Token Issuance Complete]

Configuration Properties

Core settings from AuthContextProperties (spring.auth.*).

Core Settings (spring.auth.*)

PropertyTypeDefaultDescription
state-typeenumOAUTH2Authentication state type (OAUTH2, SESSION)
token-transport-typeenumHEADERToken transport method (HEADER, COOKIE, HEADER_COOKIE)
token-issuerenumINTERNALToken issuer (INTERNAL, AUTHORIZATION_SERVER)
factor-selection-typeenumSELECTMFA factor selection strategy
access-token-validitylong (ms)3600000 (1h)Access token validity period
refresh-token-validitylong (ms)604800000 (7d)Refresh token validity period
refresh-rotate-thresholdlong (ms)43200000 (12h)Refresh-token rotation threshold
enable-refresh-tokenbooleantrueEnable refresh token
allow-multiple-loginsbooleanfalseAllow concurrent multiple logins
max-concurrent-loginsint3Maximum concurrent login count
cookie-securebooleantrueCookie Secure flag
token-persistenceString"memory"Preferred token persistence mode exposed to generated login and MFA pages / SDK
token-prefixString"Bearer "Token prefix
roles-claimString"roles"JWT roles claim
scopes-claimString"scopes"JWT scopes claim
oauth2-csrfbooleanfalseOAuth2 CSRF protection

TokenTransportType Details

ValueaccessTokenrefreshToken
HEADERHTTP HeaderHTTP Header
COOKIECookieCookie
HEADER_COOKIE (recommended)HTTP HeaderCookie

OAuth2 Settings (spring.auth.oauth2.*)

PropertyDefaultDescription
client-iddefault-clientOAuth2 client ID
client-secret173f8245-5f7d-4623-a612-aa0c68f6da4aClient secret
issuer-urihttp://localhost:9000Token issuer URI
token-endpoint/oauth2/tokenAuthorization Server token endpoint
scopereadDefault requested scope
redirect-urihttp://localhost:8080Client redirect URI
authorized-uriUnsetOptional pre-authorized redirect URI
jwk-key-store-pathUnsetJWK keystore path
jwk-key-store-passwordUnsetKeystore password
jwk-key-aliasUnsetKey alias
jwk-key-passwordUnsetKey password

MFA Settings (spring.auth.mfa.*)

PropertyDefaultDescription
session-timeout-ms600000 (10min)MFA session timeout
challenge-timeout-ms300000 (5min)Challenge timeout
inactivity-timeout900000 (15min)Inactive MFA session timeout
cache-ttl300000 (5min)Cached MFA state TTL
session-refresh-interval-ms30000 (30s)Interval for refreshing active MFA session state
state-machine-timeout-ms10000 (10s)State machine execution timeout
max-retry-attempts5Maximum retry attempts
account-lockout-duration-ms900000 (15min)Account lockout duration
minimum-delay-ms500Minimum delay between sensitive MFA operations
otp-token-validity-seconds300OTP validity period (seconds)
otp-token-length6OTP code length
sms-resend-interval-seconds60Minimum interval between SMS resends
email-resend-interval-seconds120Minimum interval between email resends
device-remember-duration-ms2592000000 (30d)Device trust retention period
state-machine-pool-size100State machine worker pool size
state-machine-cache-ttl-ms300000 (5min)Cached state machine state TTL
circuit-breaker-failure-threshold5Circuit breaker failure threshold
circuit-breaker-timeout-seconds30Circuit breaker timeout
detailed-logging-enabledfalseEnable verbose MFA debug logging
metrics-enabledtrueEnable MFA metrics
audit-logging-enabledtrueEnable MFA audit logging
session-storage-typehttp-sessionPreferred MFA session storage type
auto-select-repositoryfalseAutomatically choose the session repository
repository-priorityredis,memory,http-sessionRepository selection priority order
fallback-repository-typehttp-sessionFallback repository type

MFA Nested Settings

PrefixDescriptionRepresentative Defaults
spring.auth.mfa.http-session.*HTTP-session-backed MFA storage optionsenabled=true, session-attribute-name=MFA_SESSION_ID
spring.auth.mfa.redis.*Redis-backed MFA storage options for distributed deploymentskey-prefix=mfa:session:, cookie-name=MFA_SID, same-site=Strict
spring.auth.mfa.memory.*In-memory MFA storage tuningcleanup-interval-minutes=5, max-sessions=10000
spring.auth.mfa.sms-factor.*SMS factor delivery settingsprovider=default, template-id=mfa_sms_template, enabled=true
spring.auth.mfa.email-factor.*Email factor delivery settingsfrom-address=noreply@company.com, template-id=mfa_email_template, enabled=true

application.yml Example

spring:
  auth:
    state-type: OAUTH2
    token-transport-type: header_cookie
    access-token-validity: 3600000
    enable-refresh-token: true
    oauth2:
      client-id: my-client
      issuer-uri: https://auth.example.com
      jwk-key-store-path: classpath:keystore.jks
    mfa:
      session-timeout-ms: 600000
      otp-token-validity-seconds: 300
      session-storage-type: redis
      redis:
        key-prefix: mfa:session:
        cookie-name: MFA_SID