Financial-Grade API Security: OAuth Profile Review

If I had to boil this down to one point, it’s this: Baseline fits lower-risk read access, Advanced fits high-risk payments, and FAPI 2.0 is the better fit for most new builds.
Standard OAuth 2.0 was not made for bank data and payment flows. That’s why FAPI adds tighter rules around client login, request protection, token replay, and authorization responses. In this review, I compare FAPI 1.0 Baseline, FAPI 1.0 Advanced, and the FAPI 2.0 Security Profile using those four checks.
Here’s the short version:
-
FAPI 1.0 Baseline
- Best for read-only financial APIs
- Requires mTLS or
private_key_jwt - Requires PKCE with
S256 - Still allows bearer tokens
- Does not require signed request objects
- FAPI 1.0 Advanced
- FAPI 2.0 Security Profile
A date matters here too: CFPB Section 1033 deadlines start in 2026 for large U.S. institutions. So this is not just a standards question. It affects your security model, build effort, and long-term upkeep.
FAPI 1.0 Baseline vs Advanced vs 2.0: Security Profile Comparison
High-security & interoperable OAuth 2: What’s the latest? | FAPI 2.0 (OSW 2025)
sbb-itb-e766981
Quick Comparison
| Profile | Main use case | Client auth | Request protection | Token replay protection | Response protection |
|---|---|---|---|---|---|
| FAPI 1.0 Baseline | Read-only APIs | mTLS or private_key_jwt |
TLS + state; no JAR requirement |
Bearer tokens allowed | Basic OAuth/OIDC checks |
| FAPI 1.0 Advanced | Read-write APIs, payments | mTLS or private_key_jwt |
JAR required | mTLS-bound tokens required | JARM or ID Token signature |
| FAPI 2.0 Security Profile | New builds, browser/mobile + server mixes | mTLS or private_key_jwt |
PAR required | mTLS or DPoP required | iss parameter; JARM in Message Signing |
My takeaway: if you need the lowest setup effort, Baseline is the entry point. If you need the highest assurance for money movement, Advanced still matters. If you want a cleaner path for modern apps, FAPI 2.0 gives you the same end goal with fewer moving parts in the browser.
Let me walk through where each profile fits, what it blocks, and what it costs to run.
1. FAPI 1.0 Baseline Profile
FAPI 1.0 Baseline is aimed at read-only financial APIs [1][7]. It strengthens plain OAuth 2.0 in a few big ways. Still, it doesn't close every gap, and those gaps can matter when the risk level is higher.
Client Authentication
Baseline requires asymmetric client authentication at the token endpoint. In practice, that means using Mutual TLS (mTLS) or private_key_jwt [6][3]. Weaker options like client_secret_basic and client_secret_post should be turned off [6].
It also requires PKCE for all authorization code clients, with S256 as the only accepted method [6][3]. That's a big step up from loose OAuth setups where PKCE is optional or unevenly applied.
Token Binding Posture
Baseline still allows bearer tokens [2]. That's the catch. If a token is stolen, it can be replayed until it expires unless the platform adds sender-constraining.
mTLS can help here too. It can bind access tokens to the client certificate through the cnf claim [6][9]. That makes token replay much harder, since the token is tied to the client that holds the certificate.
Request and Response Integrity
Baseline leans on TLS 1.2+ and the OAuth state parameter [3][7]. But signed request objects (JAR) are not required at this level [1][7]. So authorization parameters still move through front-channel URLs, which leaves them open to exposure in browser history and logs, or to tampering during redirect flows [6].
Redirect URIs must be pre-registered, must use https, and allow only loopback exceptions for native clients [3]. That's good discipline, but it doesn't remove the front-channel URL issue.
| Control | FAPI 1.0 Baseline |
|---|---|
| Client authentication | mTLS or private_key_jwt required [6][3] |
| Token type | Bearer tokens allowed [2] |
| Request integrity | TLS + state parameter [3][7] |
| Signed request objects | Not required [1][7] |
| PKCE | Mandatory (S256 only) [6][3] |
| Front-channel risk | High - parameters remain exposed in the URL [6] |
Advanced closes the remaining front-channel and token replay gaps.
2. FAPI 1.0 Advanced Profile
Advanced keeps Baseline’s client authentication and PKCE rules, then fixes Baseline’s last two weak spots: exposed authorization parameters and bearer-token replay.
This is the profile used for read-write financial APIs, including payments and other high-stakes transactions. It’s required by UK Open Banking, Australia’s CDR, Brazil Open Banking, and Colombian rules.
Client Authentication
Advanced requires confidential clients to authenticate with either private_key_jwt or mTLS (tls_client_auth) [10]. Public clients are not allowed [11].
You also need RSA 2048-bit keys or approved elliptic-curve keys [10]. In practice, the split is pretty straightforward: mTLS works well in closed ecosystems that already have PKI in place, while private_key_jwt is a better fit for mixed client fleets where you don’t want to change the network layer.
Token Binding Posture
Advanced requires sender-constrained access tokens that are bound to the client through mTLS certificate-bound tokens under RFC 8705 [1][6].
Here’s the plain-English version: the resource server compares the token’s certificate thumbprint with the client certificate presented during TLS. If they don’t match, the token can’t be used [6]. So if someone steals the token by itself, that still isn’t enough.
That’s a big deal for financial APIs. mTLS pulls double duty here because it covers both client authentication and token binding with one setup.
Request and Response Integrity
JAR is mandatory. That means all authorization parameters go inside a signed JWT instead of sitting in the URL. Request objects also need nbf and exp claims, and the expiration time can’t be more than 60 minutes after nbf [5].
On the response side, JARM (JWT Secured Authorization Response Mode) signs the authorization response to stop code injection and response tampering. If JARM isn’t used, the ID Token can act as a detached signature [1][5].
| Control | FAPI 1.0 Advanced |
|---|---|
| Client authentication | private_key_jwt or mTLS required |
| Public clients | Disallowed |
| Token type | Sender-constrained (mTLS certificate-bound) |
| Signed request objects (JAR) | Mandatory |
| Response integrity | JARM or ID Token as detached signature |
FAPI 2.0 Security Profile pushes these controls further with a cleaner profile model.
3. FAPI 2.0 Security Profile
FAPI 2.0 became a Final standard on February 22, 2025 [5]. One big shift from FAPI 1.0 is that it cuts back on optional choices, which makes implementations more consistent from one deployment to the next. Colombia's SFC and Australia's CDR have both moved in this direction for open finance and other high-stakes data-sharing use cases [1]. In practice, FAPI 2.0 keeps the main protections from Advanced, but applies them in a more uniform way.
Client Authentication
Confidential clients must authenticate with either private_key_jwt or mTLS [5]. The cryptography rules are also tight: RSA keys must be at least 2,048 bits, elliptic curve keys at least 224 bits, and the supported algorithms are limited to PS256, ES256, and EdDSA (Ed25519) [5].
There’s also a useful implementation note here: do not rotate refresh tokens for sender-constrained confidential clients. According to the standard, that adds complexity without improving security [5]. In plain terms, it creates more moving parts but doesn’t give you extra protection.
Token Binding Posture
FAPI 2.0 is the first profile in this comparison to require sender-constrained access tokens across the board [5]. It does that with either mTLS certificate-bound tokens or DPoP [5].
A simple way to think about it:
- Use mTLS for server-to-server flows
- Use DPoP for browser or mobile clients where transport-layer mTLS is hard to deploy
That split is practical. Back-end systems can usually handle certificates cleanly, while browser and mobile apps often need something lighter.
Request and Response Integrity
PAR is mandatory in FAPI 2.0. The client sends the authorization parameters directly to the authorization server, receives a request_uri, and then passes only that reference through the browser [5]. That keeps the browser from carrying the full request payload, which cuts down exposure and makes request handling more predictable.
FAPI 2.0 also requires PKCE with S256, allows only code as the response_type, and sets a hard maximum of 60 seconds for authorization codes [5]. That's a tight window by design.
On the response side, the FAPI 2.0 Security Profile uses the iss parameter for mix-up protection [5]. For non-repudiation, the FAPI 2.0 Message Signing profile adds mandatory JAR and JARM [4].
| Control | FAPI 2.0 Security Profile |
|---|---|
| Client authentication | private_key_jwt or mTLS required |
| Authorization requests | PAR mandatory; front-channel requests rejected |
| Response type | code only |
| PKCE | Mandatory (S256) |
| Token binding | mTLS or DPoP (sender-constrained) |
| Response integrity | iss parameter; JARM via Message Signing |
| Authorization code lifetime | 60 seconds maximum [5] |
These controls line up neatly with key platform layers: client authentication, authorization requests, token binding, and response handling.
How Each Control Fits Into Platform Design
The main design call is simple: where does each control live in the stack? The answer matters because the same control does a different job depending on whether it sits at the authorization server, gateway, client, or resource server.
Client authentication is enforced at the Authorization Server. Sender-constraining is enforced at the API Gateway and Resource Server.
PAR and JAR are enforced at the Authorization Server. JARM is enforced at the client. In FAPI 2.0, PAR handles core request integrity, while JAR and JARM sit under the separate Message Signing profile.
Use mTLS when you control transport end to end. Use DPoP when client certificates don't make it through intermediaries in a dependable way.
Here’s where each control fits in practice:
| Control | Threat Addressed | Enforcing Component | Ops Burden | Best Use Case |
|---|---|---|---|---|
private_key_jwt (Client Auth) |
Client impersonation | Authorization Server | Medium (JWKS management) | All FAPI confidential clients |
| mTLS (Sender-Constraining) | Token theft and replay | API Gateway / Resource Server | High (PKI & TLS propagation) | High-security server-to-server integrations |
| DPoP (Sender-Constraining) | Token theft and replay | Resource Server | Medium (request signature) | Browser or mobile apps with complex network paths |
| PAR (Request Integrity) | Request tampering | Authorization Server | Low | FAPI 2.0 core |
PKCE (S256) |
Authorization code injection/leakage | Authorization Server | Low | FAPI 2.0 core flows |
| JAR (Signed Request) | Request tampering | Authorization Server | Medium | FAPI 1.0 Advanced; Message Signing profile |
| JARM (Signed Response) | Response injection, IdP mix-up | Client | Medium (JWT verification) | FAPI 1.0 Advanced; Message Signing profile |
One more thing that gets missed in planning: token size. Large access tokens, especially certificate-bound tokens or tokens packed with scopes, can blow past the standard 8 KB header limit and cause HTTP 431 errors. It’s worth measuring header size during load testing [8].
Pros, Cons, and Which Profile to Choose
Now that the control-level comparison is done, the choice comes down to risk, client type, and deployment limits. At its core, this decision hinges on four controls: client auth, signed requests, token binding, and response protection.
| Profile | Strengths | Weaknesses |
|---|---|---|
| FAPI 1.0 Baseline | Best for read-only access and easiest to deploy | Bearer tokens allowed; no mandatory sender-constraining; no non-repudiation |
| FAPI 1.0 Advanced | Highest assurance for high-value read/write operations; adds signed requests and responses; aligns with UK, Brazil, and Australia requirements | High complexity; Hybrid Flow is awkward for modern SPAs; sender-constraining depends on mTLS |
| FAPI 2.0 Security Profile | Same security goals with less implementation overhead; less front-channel exposure; DPoP works better for browser and mobile clients; formal threat model | Requires a PAR-capable authorization server; non-repudiation handled in a separate Message Signing profile |
Policy matters, but architecture still has the last word. PAR, for example, still means authorization-server upgrades.
Choose based on the job you're trying to do:
- Read-only data, fast rollout → FAPI 1.0 Baseline - a good fit when you need authorization-server hardening for lower-risk access
- High-value transactions or UK, Brazil, or Australia requirements → FAPI 1.0 Advanced - stronger auth, plus signed request and response handling
- New deployments or browser/mobile clients → FAPI 2.0 - authorization-server PAR plus sender-constrained tokens for mixed client environments. Colombia's Superintendencia Financiera (SFC) mandated it in February 2024 via External Circular 004 2024, and Australia's CDR is targeting it as a mandatory security uplift for existing participants [1]
If your partners have a hard time with tight TLS integration, DPoP under FAPI 2.0 cuts that friction at the application layer while still sender-constraining tokens. On the other hand, mTLS makes more sense for closed server-to-server ecosystems that already have PKI in place.
The practical move is to match the profile to the weakest part of your stack: read-only access, client diversity, or PKI maturity.
FAQs
Which FAPI profile should I choose?
For modern, high-security setups, FAPI 2.0 is the recommended choice. It fits a broad range of use cases and works well for high-value scenarios, including financial services and sensitive data protection.
For existing systems, FAPI 1.0 gives you two paths:
- Baseline for moderate-risk APIs
- Advanced for high-risk scenarios
Choose Advanced if you need non-repudiation or sender-constrained access tokens.
When should I use mTLS vs. DPoP?
Use mTLS for backend-to-backend communication when you can manage certificate lifecycles and keep end-to-end TLS termination in place. It ties tokens to the transport layer and avoids changes in the application itself.
Use DPoP for browser-based clients, mobile apps, or setups where TLS ends at a load balancer or gateway. It works at the application layer through HTTP headers, so it doesn’t need end-to-end TLS.
Do I need PAR, JAR, and JARM?
It depends on your security profile and implementation risk level. PAR is required in FAPI 2.0 because it moves authorization request parameters out of the browser and into a secure backchannel, which helps prevent authorization request tampering.
JAR protects the integrity of the request, while JARM protects response parameters by placing them in a signed or encrypted JWT. In high-stakes financial settings, these controls matter because they cut down the risk of parameter injection and response tampering.



