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 profile family
| Document | Status | What it profiles |
|---|---|---|
| FAPI 1.0 Part 1: Baseline | Final (Mar 2021) | Read-only APIs. Confidential clients, TLS 1.2+, PKCE, authorization code flow, bearer or bound tokens, the x-fapi-* headers. |
| FAPI 1.0 Part 2: Advanced | Final (Mar 2021) | Read-write APIs. Everything in Baseline plus: signed request objects (JAR) with exp/nbf; hybrid flow code id_token with the ID token as a detached signature (s_hash, c_hash) or JARM; client authentication by mTLS or private_key_jwt; certificate-bound access tokens (RFC 8705); PS256 / ES256 only. |
| FAPI 2.0 Security Profile | Final (Feb 2025) | A single read-write profile: PAR, PKCE S256, response_type=code only, iss in the response, sender-constrained tokens by mTLS or DPoP, mTLS or private_key_jwt client authentication, no refresh-token rotation, metadata-only discovery. OpenID Connect becomes optional. |
| FAPI 2.0 Attacker Model | Final (Feb 2025) | The security goals and attacker capabilities the Security Profile is formally proven against. Normative companion — a derived profile may not weaken a mandatory behaviour without invalidating the proof. |
| FAPI 2.0 Message Signing | Final (Sep 2025) | Non-repudiation on top of the Security Profile: signed pushed authorization requests (JAR), signed authorization responses (JARM), signed introspection responses (RFC 9701), signed ID tokens. Each mechanism is certifiable separately. |
| FAPI-CIBA | Implementer's Draft | Client-Initiated Backchannel Authentication for decoupled flows: poll and ping modes only (push is not allowed), signed backchannel requests, the same client-authentication and token-binding rules. |
| FAPI 2.0 HTTP Signing | Draft | Split out of Message Signing: signing resource requests and responses with HTTP Message Signatures (RFC 9421). Closes the DPoP replay-with-altered-body gap for payment APIs. |
| Grant Management for OAuth 2.0 | Implementer's Draft | Query, update and revoke the grant behind a consent — the standard answer to the consent dashboards open-finance regulations ask for. |
FAPI 1.0 Advanced vs FAPI 2.0 — what changed and why
FAPI 1.0 defended against a list of known attacks with layered mechanisms. FAPI 2.0 starts from the attacker model and keeps only what the proof needs, which made it simpler to implement correctly. The specification's own comparison:
| FAPI 1.0 Advanced | FAPI 2.0 | Why |
|---|---|---|
| JAR (signed request object) | PAR | The request goes server-to-server, so it needs no front-channel integrity protection; better compatibility. |
| JARM or hybrid flow | Only code in the response | The response carries nothing but a single-use code, so there is nothing left worth signing. |
| s_hash + state for CSRF | PKCE | PKCE provides the CSRF protection; state is free for application use. |
| Pre-registered redirect URIs | Redirect URI in the PAR request | With an authenticated PAR, pre-registration is not needed. |
| code id_token or code | code | No ID token in the front channel (privacy), and clients cannot skip the check — PKCE is enforced by the server. |
| ID token as detached signature | PKCE | The ID token is just an ID token again. |
| Possibly encrypted front-channel ID tokens | No front-channel ID tokens | Back channel only, so no encryption needed. |
| nbf / exp in the request object | request_uri with a short lifetime | Prevents pre-generated requests. |
| x-fapi-* headers | Moved to the Implementation & Deployment Advice | Not part of the security core. |
| mTLS-bound tokens | mTLS or DPoP | DPoP is easier to deploy where you do not control the TLS terminator. |
The attacker model
FAPI 2.0 assumes very strong attackers — including some that can read otherwise encrypted traffic — and requires the goals to hold against any combination of them. The attackers are:
| Attacker | Capability | Typical real-world source |
|---|---|---|
| A1 | Web attacker: runs endpoints, participates as a normal user, tampers with its own messages, can make honest users' browsers send known requests (links). | Phishing links, malicious websites, a rogue TPP. |
| A1a | Web attacker that is also a legitimate authorization server in the ecosystem; can replay messages from honest servers and send users to them. | A compromised or malicious bank / IdP in a multi-AS ecosystem — the source of mix-up attacks. |
| A2 | Network attacker: intercepts, blocks and tampers with any message, but cannot break cryptography. | Rogue Wi-Fi, compromised network node. |
| A3a | Reads the front-channel authorization request. | Mobile OS URL handlers, browser history, server-side XSS, TLS-intercepting antivirus. |
| A4 | Reads and tampers with token requests and responses by making the client use a wrong token endpoint. Informative only in FAPI 2.0: discovery from authoritative metadata makes it moot. | Misconfigured endpoints (FAPI 1.0's concern). |
| A5 | Reads resource requests after the resource server processed them. | TLS-terminating proxy logs on the API side. |
Deliberately out of scope: a broken TLS, compromised key distribution (JWKS), compromised user devices and browsers, and the identity proofing, authentication and session management inside clients and authorization servers. An attacker who can read the authorization response is also excluded — with today's browsers such an attacker defeats every redirect-based protocol (the "browser swapping" discussion in the Security Profile).
Related: SCA on the card side →