Auth
Authentication is OIDC via Ricochet/Keycloak: /auth/login, /auth/callback,
/auth/logout. OIDC secrets are provided by secretspec.
Backend flow
- The frontend links to
/auth/login, which sits behindOidcLoginLayer; axum-oidc redirects the browser to Keycloak via the Ricochet relay. The OAuthstatecarries a CSRF token plus the app callback ({APP_URL}/auth/callback). - Keycloak authenticates the user; the relay forwards the code to
/auth/callback, served byaxum_oidc::handle_oidc_redirect. - The callback exchanges the code for tokens and stores them in a server-side
session (Valkey, via
tower-sessions). OidcAuthLayerestablishes the claims on each request;sync_user_middlewareupserts a localuserkeyed on the OIDC subject and exposes it asSyncedUser.- The frontend reads
/auth/status.
Logout (GET /auth/logout) flushes the local session and returns to the app
root. The Keycloak SSO session is left intact, so re-login does not re-prompt for
credentials.
Sessions
Server-side sessions are backed by Valkey (tower-sessions-redis-store over
fred), connected via VALKEY_URL. Only the session token set
lives in Valkey user identity stays in Postgres, re-derived from the token
subject per request via sync_user_middleware.
Files
src/core/auth/oidc.rs:GroupClaims, theSessionWrapperbridge fromtower-sessionsto axum-oidc’s session contract, the relaystategenerator, and the discoveredOidcClientbuilder.src/core/auth/middleware.rs:SyncedUserand its extractors, plussync_user_middleware.src/domain/auth/handlers.rs:GET /auth/status, the/auth/loginand/auth/logouthandlers, and the demo page.src/server.rs: mounts the session layer,OidcAuthLayer,sync_user_middleware, and CORS.
Config
Secrets are loaded through the secretspec Rust SDK
(declare_secrets! against the repo-root secretspec.toml), using the read-only
env provider.