Bound session lifetime and periodically re-validate identity and tenant - #64
Merged
Conversation
…vals Cookies that establish identity and tenant context were either unbounded within a browser session or trusted indefinitely once issued, so revoked access could keep working for as long as the browser stayed open. This introduces a Cratis:AuthProxy:Session section that bounds all three: - Lifetime (default 12h, absolute) caps the authentication ticket. - IdentityRevalidationInterval (default 10m) caps how long resolved identity details are trusted before re-resolution. - TenantRevalidationInterval (default 10m) caps how long a selected tenant is trusted before re-validation. Defaults are chosen so bounded re-validation happens without per-request backend calls; zero or negative intervals opt out. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The authentication ticket previously used the ASP.NET Core default of a 14-day sliding expiration, so an active browser session effectively never re-authenticated and revoked users kept access indefinitely. The ticket lifetime now comes from Session:Lifetime (default 12 hours) with sliding expiration disabled by default, forcing a periodic round-trip to the identity provider while the cookie itself stays session-scoped. The auth, correlation, and nonce cookies also move from SecurePolicy None to SameAsRequest: they are marked Secure whenever the original request is HTTPS (forwarded headers preserve the scheme behind a TLS-terminating ingress) while local HTTP development keeps working. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The .cratis-identity cookie short-circuits identity resolution: while it exists, the services' identity endpoints (and the authorization decision they return) are never consulted again. As a pure session cookie that meant a browser session that never closed also never re-validated, so a user whose access was revoked stayed authorized until they closed the browser. The cookie now carries Max-Age equal to Session:IdentityRevalidationInterval (default 10 minutes), making the browser drop it periodically so identity is re-resolved - including the 403/unauthorized path - without a backend round-trip on every request. A non-positive interval restores the pure session cookie. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A tenant resolved from the .cratis-tenant selection cookie was trusted for the entire browser session - once selected, the tenants endpoint was never consulted again, so a user removed from a tenant kept acting in it until the browser closed. The tenant selection middleware now re-validates a selection-resolved tenant against the configured TenantsEndpoint once per Session:TenantRevalidationInterval (default 10 minutes), caching the positive answer in memory so no per-request backend calls are made. When the endpoint answers authoritatively that the tenant is no longer available, the .cratis-tenant and .cratis-tenants cookies are deleted and the request is replayed without them so the regular selection or no-tenant flow takes over. Transport failures fail open so a transient backend outage cannot lock users out. Explicit selections and single-tenant auto-selection stamp the re-validation window, and non-selection strategies are unaffected since they derive the tenant from the request itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Describe the new Cratis:AuthProxy:Session section with its defaults, the session-scoped and Secure/HttpOnly/SameSite posture of the cookies, and how the selected tenant is periodically re-validated so revoked access takes effect without per-request backend calls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens the cookie/session posture so a browser holding old cookies cannot retain access indefinitely: revoking a user's access now takes effect within minutes without validating against backing services on every request.
Changed
Cratis:AuthProxy:Session:Lifetime); sliding expiration is off by default so activity cannot extend a session indefinitely. The auth cookie remains session-scoped, so closing the browser ends it.SecurePolicy.SameAsRequestinstead ofNone.Added
Cratis:AuthProxy:Sessionconfiguration section:Lifetime,SlidingExpiration,IdentityRevalidationInterval,TenantRevalidationInterval(zero/negative interval opts out), with documentation.All 576 specs pass (28 new covering the option defaults, cookie configuration, identity cookie expiry, and tenant re-validation). Not verified live against a deployed IdP — in-process spec coverage only.
🤖 Generated with Claude Code