Handshake timeline
Each step has one purpose: authorize safely, exchange tokens in backend, and validate identity before app-session binding.
Authorization redirect request
Client frontend redirects to `/api/oauth/authorize` with `client_id`, exact `redirect_uri`, `response_type=code`, `state`, and PKCE fields when required.
User authentication and consent
ZKAuth Identity authenticates the user, validates consent context, and returns a short-lived single-use authorization code to the registered callback.
Backend token exchange
Client backend validates state and exchanges the code at `/api/oauth/token` with `client_id`, `client_secret`, and `code_verifier` when PKCE is used.
JWT verification and local session bind
Backend verifies RS256 signature via JWKS, enforces `iss/aud/exp`, maps `sub` to local user identity, then issues app-specific session state.