← Payment Reference GuidesAPI Security Reference

FAPI: the Financial-grade API Security Profiles

FAPI is the OpenID Foundation's hardened profile of OAuth 2.0 and OpenID Connect for APIs where a stolen token means a stolen payment. This guide covers FAPI 1.0 Baseline and Advanced, the FAPI 2.0 Security Profile and its attacker model, Message Signing and CIBA — what each one requires, the authorization-code flow message by message, which open-banking ecosystems mandate which profile, and a checklist for shipping it.

The building blocks

FAPI 2.0 invents almost nothing. It is a fixed selection of IETF and OpenID specifications, each doing one job:

SpecNameJob in FAPI 2.0
RFC 6749 / 6750OAuth 2.0 and Bearer Token UsageThe authorization code grant; tokens in the Authorization header, never in a query string.
RFC 9126Pushed Authorization Requests (PAR)All authorization parameters go server-to-server with client authentication; the browser carries only client_id and a short-lived request_uri.
RFC 7636PKCES256 challenge, fresh per request and bound to the user agent — the CSRF and code-injection defence.
RFC 9207Issuer Identificationiss in the authorization response; the client checks it against the metadata issuer to stop mix-up attacks (A1a).
RFC 8705OAuth mTLSClient authentication by certificate and certificate-bound access tokens (cnf.x5t#S256); mtls_endpoint_aliases for mixed deployments.
RFC 9449DPoPApplication-layer proof of possession: a per-request JWT signed with the client's key, access tokens bound to cnf.jkt, server nonces, code binding via dpop_jkt.
OIDC Core §9private_key_jwtClient authentication with a signed assertion whose aud is the issuer identifier (as a string, not an array).
RFC 8414 / OIDC DiscoveryAuthorization Server MetadataThe only permitted source of endpoint URLs; the client verifies issuer matches the URL it fetched from.
RFC 9700 (BCP 240)OAuth 2.0 Security Best Current PracticeThe threat catalogue FAPI 2.0 follows: no open redirectors, no 307 redirects with credentials, one-time codes.
RFC 8725JWT Best Current PracticesHow every JWT (assertions, DPoP proofs, request objects, ID tokens) is created and validated.
BCP 195 · RFC 9525TLS recommendations · certificate verificationTLS 1.2 minimum, recommended cipher suites only on server-to-server endpoints, hostname verification.
RFC 9396Rich Authorization Requests (recommended)authorization_details when scope cannot express "pay €120.00 to IBAN … once".
RFC 9101 · JARM · RFC 9701JAR · JWT Secured Authorization Response · JWT introspection responsesOnly with Message Signing: non-repudiable requests, responses and introspection results.

What the authorization server shall do

Paraphrased from the Security Profile's "requirements for authorization servers" (general and authorization-endpoint lists). Shall is normative.

Clients, grants, tokens

  • Publish discovery metadata (RFC 8414 / OIDC Discovery).
  • Reject the resource-owner password grant; support only confidential clients.
  • Issue only sender-constrained access tokens, bound by mTLS (RFC 8705) or DPoP (RFC 9449).
  • Authenticate clients only by mTLS or private_key_jwt; accept the issuer identifier only as a string in the assertion's aud.
  • No refresh-token rotation except in extraordinary circumstances (migration), and then with a time-limited retry on the old token.
  • If DPoP: support authorization-code binding to the DPoP key (dpop_jkt); may use server-provided nonces.
  • Accept JWTs with iat/nbf up to 10 s in the future; reject beyond 60 s.
  • No open redirectors. Least-privilege tokens (should).

Authorization endpoint

  • response_type must be code.
  • Support client-authenticated PAR; reject authorization requests that did not come through PAR; reject unauthenticated PAR.
  • Require PKCE with S256; require redirect_uri in the PAR request.
  • Return iss in the authorization response (RFC 9207).
  • No http redirect URIs except loopback for native apps (RFC 8252); reject a previously used code.
  • Never redirect with HTTP 307 when the request carries credentials; 303 is recommended.
  • request_uriexpires_in under 600 s; enforce one-time use at authorization time, not page load.
  • Support OIDC nonce values up to 64 characters (if OIDC is offered).
  • Show the user who the client is and what it asks for (should).

Clients (TPP / relying party)

  • Support mTLS and/or DPoP token binding, and mTLS and/or private_key_jwt client authentication.
  • Use PAR for every authorization request; send only client_id and request_uri to the authorization endpoint.
  • Fresh PKCE challenge per request, bound to the client and the user agent that started the flow.
  • Check iss in the response against the metadata issuer.
  • Take endpoint URLs only from metadata fetched from an authoritative issuer URL over a secure channel; verify the issuer value matches.
  • Support refresh tokens (and rotation, should the server ever do it); support mtls_endpoint_aliases; support DPoP server nonces.
  • Only start a flow with the user's explicit or implicit consent, protected against CSRF.

Resource servers (the API)

  • Accept access tokens only in the Authorization header (Bearer or DPoP scheme); never in query parameters.
  • Verify validity, integrity, expiry and revocation status of every token.
  • Check that the token's authorization covers the requested resource; otherwise fail per RFC 6750 §3.1.
  • Verify the sender constraint: the presented client certificate matches cnf.x5t#S256, or the DPoP proof matches cnf.jkt (with ath, method and URI).

Cryptography and transport

AreaRequirement
JWS algorithmsPS256, ES256 or EdDSA (Ed25519). Never none; RS256 and HS256 are out. Follow RFC 8725.
Key sizesRSA ≥ 2048 bits; elliptic-curve ≥ 224 bits.
Secrets not handled by usersAccess tokens, refresh tokens, codes: at least 128 bits of entropy.
JWKSServe jwks_uri over TLS only; avoid x5u / jku headers; avoid duplicate kids — and when they occur, verifiers pick the key by alg, use, kty, crv.
TLS, all endpointsTLS 1.2 or later, BCP 195, server certificate check per RFC 9525; DNSSEC should be used.
TLS, server-to-serverWith TLS 1.2 only the IANA recommended cipher suites; MTLS ecosystems should publish their CA trust list.
TLS, browser-facingNo TLS-stripping downgrades (preloaded HSTS); any BCP 195-allowed suite; no CORS on the authorization endpoint.

The numbers to remember

≤ 60 sauthorization code lifetime
< 600 sPAR request_uri expiry
10 s / 60 sfuture iat/nbf: must accept / must reject
≤ 60 minsigned request object nbf age and exp span (Message Signing)
64 charsOIDC nonce servers must support
2048 / 224minimum RSA / EC key bits
128 bitsentropy of tokens and codes
12 monthsto adopt a new BCP 195 / cipher-suite registry revision

Compact version: FAPI cheatsheet on the standards page →

Put it into practice

Next steps

Keep reading

Related articles