Logout
AuthProxy exposes a well-known logout endpoint that ends the current session and returns the user to a validated destination:
GET /.cratis/logout?redirect=<absolute-url>The endpoint is anonymous — it works even when the session is already invalid — and is handled before the authentication challenge stages, so it never bounces the user to a login provider.
Full-chain logout
Section titled “Full-chain logout”A plain cookie logout leaves the user signed in at the identity provider, so the next visit silently re-authenticates. To avoid that, AuthProxy performs a full-chain logout: it ends the session both locally and at the identity provider using OIDC RP-initiated logout.
When the session was established through an OIDC provider, a logout request:
-
Reads the stored
id_tokenand the provider the session was established with from the authentication cookie, and clears the local session (see What it clears). -
Redirects (
302 Found) the browser to that provider’s end-session endpoint (discovered from the provider’s OpenID configuration) with:id_token_hint— the storedid_token, so the provider knows which session to end.post_logout_redirect_uri— AuthProxy’s own callback,/.cratis/logout/callback.
The validated final
redirecttarget is carried across the round-trip in a short-lived, HTTP-only cookie (.cratis-logout) rather than in the URL. -
The identity provider ends its own session and redirects back to
/.cratis/logout/callback. -
The callback clears every AuthProxy cookie again (idempotent) and redirects (
302 Found) to the validated finalredirecttarget.
Register the callback with each OIDC provider.
post_logout_redirect_urimust be allow-listed at the provider, so registerhttps://<your-proxy-host>/.cratis/logout/callbackas a permitted post-logout redirect URI for every OIDC application.
OAuth 2.0 providers (e.g. GitHub)
Section titled “OAuth 2.0 providers (e.g. GitHub)”OAuth 2.0 providers have no standard OIDC end-session endpoint and cannot be force-logged-out via a
redirect. When the session was established through an OAuth provider — or when there is no active OIDC
session, or the provider’s discovery document advertises no end-session endpoint — AuthProxy falls back to
a local-only logout: it clears its own cookies and redirects straight to the validated redirect
target. The user’s session at the OAuth provider is left untouched, so a later visit may still
re-authenticate silently without asking for credentials. This is a limitation of the OAuth providers, not
of AuthProxy.
What it clears
Section titled “What it clears”Both the local logout and the post-logout callback:
- Sign the user out of the authentication cookie (
.Cratis.AuthProxy.Auth.v2), including any chunked variants. - Delete every AuthProxy session cookie:
.cratis-identity.cratis-identity-authorization.cratis-tenant.cratis-tenants.cratis-invite.cratis-invite-state.cratis-registration.cratis-providers
- Delete every transient sign-in handshake cookie the browser sent (
.AspNetCore.Correlation.*,.AspNetCore.OpenIdConnect.Nonce.*) — the leftovers of abandoned handshakes that would otherwise poison the next sign-in. See Failed Sign-ins. - Delete any additional cookies the deployment configured under
Cratis:AuthProxy:Logout:AdditionalCookies— cookies AuthProxy does not issue itself but that must not survive a logout. See Clearing additional cookies.
The .cratis-logout carry cookie is deleted by the callback once the final target has been read from it.
After logout nothing of the session survives, so the next visit to a protected resource lands on the provider-selection page (or the single provider’s login) rather than silently reusing anything local. Whether the identity provider still remembers the user is governed by the full-chain behavior above.
The redirect parameter
Section titled “The redirect parameter”The post-logout destination is supplied as an absolute URL in the redirect query-string parameter,
for example:
/.cratis/logout?redirect=https://cratis.studioBecause the target is absolute, it cannot be validated with the relative-URL check used elsewhere. Instead it is matched against an allow-list of origins so neither the endpoint nor its callback can be turned into an open redirect. The target is validated on both legs of the round-trip. A target is allowed when its origin (scheme + host + port) matches any of:
- The proxy’s own public origin as seen by the browser (derived from the request, honoring
X-Forwarded-Proto). This covers redirecting back to the site the user is already on. - Any configured service frontend (
Cratis:AuthProxy:Services:<name>:Frontend:BaseUrl). - The configured lobby frontend (
Cratis:AuthProxy:Invite:Lobby:Frontend:BaseUrl). - Any origin listed in
Cratis:AuthProxy:Logout:AllowedRedirectOrigins(see below).
Same-site relative URLs (a single leading /, but not //) are always allowed.
If redirect is missing, empty, or fails validation, AuthProxy falls back to the application root (/).
Allowing additional post-logout origins
Section titled “Allowing additional post-logout origins”The implicit origins above cover redirecting back to the app itself, but a deployment often wants to send
the user somewhere else after logout — for example a separate marketing or landing site that is neither
the proxy’s own origin nor a configured frontend. List those origins under
Cratis:AuthProxy:Logout:AllowedRedirectOrigins. Each entry is an absolute origin (scheme + host,
optionally a port) with no path; malformed or non-HTTP(S) entries are ignored.
{ "Cratis": { "AuthProxy": { "Logout": { "AllowedRedirectOrigins": [ "https://cratis.studio" ] } } }}Equivalent environment variables (one indexed key per entry):
Cratis__AuthProxy__Logout__AllowedRedirectOrigins__0=https://cratis.studioWith the example above, GET /.cratis/logout?redirect=https://cratis.studio is permitted even when the
app itself is served from a different host such as https://app.cratis.studio.
Clearing additional cookies
Section titled “Clearing additional cookies”Logout clears every cookie AuthProxy issues — but a deployment often runs sibling authentication
infrastructure whose cookies AuthProxy knows nothing about. The classic case is a separate
oauth2-proxy guarding an admin app whose session cookie
was scoped to the parent domain (e.g. _oauth2_proxy_admin on .cratis.studio): every browser that
ever signed in there sends it on every *.cratis.studio request, and it survives AuthProxy’s logout —
leaving the user half-signed-in from the application’s point of view.
List such cookies under Cratis:AuthProxy:Logout:AdditionalCookies and the session-termination sweep
deletes them too. Each entry has:
Name(required) — the exact cookie name. Matching is by exact name only; there is no prefix or wildcard support.Domain(optional) — the domain the cookie was scoped to, e.g..cratis.studio. When set, the deletion is issued for that domain as well as the request host — necessary because a host-scoped deletion cannot touch a parent-domain cookie. Deleting for a parent domain of the current host is legal, which is exactly what makes this work. Leave it out for a cookie scoped to the request host itself.
Deletions are issued at the root path (Path=/) with the Secure attribute mirroring the request scheme,
so they reliably match how such cookies are typically written.
{ "Cratis": { "AuthProxy": { "Logout": { "AdditionalCookies": [ { "Name": "_oauth2_proxy_admin", "Domain": ".cratis.studio" } ] } } }}Equivalent environment variables (one indexed entry per cookie):
Cratis__AuthProxy__Logout__AdditionalCookies__0__Name=_oauth2_proxy_adminCratis__AuthProxy__Logout__AdditionalCookies__0__Domain=.cratis.studioThe configured cookies are cleared everywhere the session is terminated:
- the logout endpoint (both legs of a full-chain logout), and
- the sign-in sweep that runs when a provider callback completes — so a fresh sign-in also heals a browser still carrying the stale cookie, without requiring the user to log out first.
This is a cleanup mechanism for cookies that linger after the owning deployment has been fixed (for example, until an old parent-domain cookie expires) — it does not log the user out of the system that issued the cookie.
Example
Section titled “Example”A “Log out” control in the application simply navigates the browser to the endpoint:
<a href="/cratis/logout/?redirect=https://cratis.studio">Log out</a>For an OIDC session the browser is taken through the provider’s end-session endpoint and back via the callback; for an OAuth session it lands on the target directly. Either way the user ends up on the target unauthenticated at AuthProxy, and requesting a protected resource then triggers the normal login flow.