JWT Secured Authorization Response Mode (JARM) — Versola Docs
VersolaVersola/docs
versola.kzGitHub

JWT Secured Authorization Response Mode (JARM)

response_mode=jwt — authorization responses returned as a signed JWT

Specification: Financial-grade API: JWT Secured Authorization Response Mode for OAuth 2.0 (JARM)

JARM moves every authorization response parameter — success or error — into a single signed response JWT, so a client can tell a response this server produced from one an attacker assembled on the redirect.

Response Modes

  • query.jwt (§2.1) — code-flow responses, signed JWT in the query string
  • fragment.jwt (§2.1) — responses carrying an id_token, signed JWT in the fragment
  • jwt shorthand (§2.3.4) — resolves to query.jwt or fragment.jwt per the response type, mirroring how plain query/fragment already resolve
  • response_mode persisted with the authorization conversation — a response built after /authorize accepted the parameter honors the mode the request actually started under, rather than re-deriving it from state that may have changed
  • Signed error responses (§4.3) — a rejected or failed authorization also returns a signed response JWT, not only a successful one

Response JWT

  • iss, aud, exp claims (§2.1) — issuer identifier, the requesting client, and a 5-minute expiry
  • Every response parameter carried as a claim, state included; iss is not also sent as a bare parameter alongside the signed copy
  • Signed with the tenant’s own active signing key — §2.2 leaves the algorithm choice to the server
  • authorization_signed_response_alg per-client override (§2.2 names this a “MAY”) — not implemented; every client under a tenant is signed with that tenant’s one active key, and a client resolves the algorithm actually used from authorization_signing_alg_values_supported in discovery, or from the JWT’s own alg/kid header, rather than by registering a preference
  • Encrypted response (nested JWE, §2.3) — not supported; JARM responses are signed only, never encrypted

Authorization Server Metadata

  • authorization_signing_alg_values_supported (§4) — derived from the deployment’s actual signable keys, so it cannot drift away from what a response is ever signed with
  • response_modes_supported advertises jwt, query.jwt, fragment.jwt alongside the plain query/fragment

State Protection (s_hash)

s_hash is not part of JARM itself; it comes from FAPI 1.0 Advanced §5.2.2, which requires it wherever an ID Token is returned as a detached signature alongside a state value. It is documented here because both were built together — JARM protects the redirect, s_hash protects the state inside the token riding alongside it.

  • s_hash claim included in the ID Token whenever the authorization request carried a state value (FAPI 1.0 Advanced §5.2.2-4) — left-most half of the hash of state, using the same digest as the ID Token’s own signing algorithm, the identical construction OIDC Core §3.3.2.11 uses for c_hash
  • Computed on both the hybrid-flow authorization response and the redeemed conversation’s ID Token