02 $ ls ~/projects/authforge/flowsHow it works.
Four moving parts do the interesting work — password-safe login, multi-tenant token validation, enterprise federation, and near-zero-config tenant onboarding.
PKCE — the app never sees the password
Sign-in generates a random verifier and its SHA-256 challenge, redirects the browser straight to Keycloak, then swaps a one-time code plus the original verifier for tokens. Web uses a hand-rolled flow (pkce_service_web.dart); mobile uses flutter_appauth. Tokens land in flutter_secure_storage — Keystore / Keychain.
code_challenge=S256public clientflutter_secure_storage
Per-realm JWT validation
The NestJS guard decodes the token's issuer, parses the realm, checks it against a KEYCLOAK_REALMS allowlist, then verifies RS256 + expiry with a JwksClient cached per realm. RolesGuard authorizes on the union of realm-level and client-level roles — raw passport-jwt + jwks-rsa, no Keycloak adapter.
passport-jwtjwks-rsaRolesGuard
SAML federation — tenant-b ← saml-idp
tenant-b brokers to a simulated enterprise SAML IdP (ADFS/Okta-style). On first login, broker mappers create or link the user in tenant-b and assign the viewer role. Flutter and the API never know SAML was involved — they only ever see a standard Keycloak JWT.
identity brokerattribute mappershardcoded-role
A new tenant in ~5 minutes
A tenant is a fully isolated realm. Copy a realm JSON, add its name to KEYCLOAK_REALMS and the Flutter tenant switcher, restart the stack — no code changes. Tokens are realm-scoped: a tenant-a token is rejected by tenant-b.
realm-per-tenantenv-var configisolated users