Skip to demo content
Step 1 of 11: User requests protected resource
← All demos

Enterprise SAML for Modern Apps

1. User requests protected resource

User navigates to the dashboard. Caddy intercepts and checks auth. oauth2-proxy has no session for this browser, so it starts an OIDC Authorization Code flow: it generates a random state, a nonce, and a PKCE code_verifier, protects them in an encrypted and signed CSRF cookie, and redirects the browser to Logto with code_challenge = BASE64URL(SHA256(code_verifier)).

What the user sees

https://secrets.example.com/dashboard
Demo simulation — do not enter real credentials
Redirecting to login...

What's happening (HTTP)

  1. REQUEST Browser → Caddy
    GET https://secrets.example.com/dashboard
    Cookie: (none)
    No session cookie present
  2. INTERNAL Caddy → oauth2-proxy
    forward_auth subrequest
    Caddy asks auth layer: is this user authenticated?
  3. RESPONSE Caddy → Browser
    302 Found
    Location: https://logto.example.com/oidc/auth?
    client_id=ots-app
    &redirect_uri=https://secrets.example.com/oauth2/callback
    &response_type=code
    &scope=openid profile email
    &state=random-csrf-token
    &nonce=random-nonce
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256
    Set-Cookie: _oauth2_proxy_csrf=encrypted-transaction-data; HttpOnly; Secure; SameSite=Lax; Path=/
    Not authenticated → redirect to Logto with state, nonce, and the S256 PKCE challenge. oauth2-proxy recovers the code_verifier from its protected CSRF cookie on callback.

Legend

Browser request
Server response
Server-to-server
Internal
← All demos
An educational demo, not a reference implementation v0.3.0