Free & open · no paywall, ever

IntegrAuth Academy

Identity, security and practical AI — free, from zero. Byte-sized lessons, real diagrams, hands-on labs, zero fluff. Two programs, each with its own exam and certificate.

20 tracks 241 lessons 242 hands-on labs 230+ diagrams 100% free

English is hard? Your browser can translate this page into Tamil, Telugu, Kannada, Malayalam or Hindi. Tech words stay in English so you learn the real names.

How?
  • Chrome on phone: ⋮ menu → Translate
  • Chrome on computer: right-click → Translate to …
  • Edge: the translate icon in the address bar
Identity & API Security Track 5 · Protocols & Federation
0/166 lessons read
PROTOCOLS & FEDERATION · LESSON 9

Stronger OAuth — PAR, JAR & FAPI

Maya's bank uses the same login flow from OIDC login step by step. But its requests say "move money". So the request itself needs protection. Your goal: explain what PAR, JAR and FAPI add, and when to use them.

Key points
  • In a normal login, the request travels the front channel in plain sight.
  • PAR sends the request on the back channel. The browser carries only a receipt.
  • JAR signs the request, so the server knows who wrote it.
  • FAPI 2.0 is a strict profile for banking-level flows.
  • Most apps do not need all of FAPI. Code, PKCE and exact redirect URIs are enough.

The weak link

Remember the two lanes. The back channel is private. The front channel runs through Maya's browser in plain sight. The ask travels there too, not only the answer. Each parameter, such as scope, redirect_uri and state, sits in a query string that browser add-ons and proxies can read. PKCE made a stolen code worthless (the birth of a token). But nothing protected the request itself.

A bent request is a real attack. It can change scope=payments:read to payments:write, or swap the redirect_uri for a look-alike. The server can only judge the request that arrives.

Think of it like…

ordering a bank transfer by shouting the details across a crowded hall. PAR is a sealed envelope instead. A courier takes it to the back office. You tell the teller only a ticket number. It means nothing and works once.

PAR: push the request, carry a receipt

Pushed Authorization Requests (RFC 9126) move the ask to the back channel. Before any redirect, the app's server sends the whole request to the bank. It logs in as itself, like a machine login. The bank checks everything right there. It answers with a request_uri. This is a meaningless reference, such as urn:ietf:params:oauth:request_uri:x7f2q. It expires fast and should work only once. The front channel then carries only client_id and that reference.

You can never make the front channel private, but PAR makes it empty. No scope is left to change, no redirect_uri to swap, and a replayed reference is refused.

WITHOUT PAR — the whole ask rides the front channel/authorize?client_id=app&scope=payments:write&redirect_uri=https://app.example/cb&state=…visible to everyone in the lane —and tamperable: was that scope always :write?WITH PAR (RFC 9126) — push the ask down the back channel firstApp serverholds the real requestAuthorization servervalidates it right here1 · POST /par — full request, client-authenticated2 · request_uri — one-time, expires in seconds/authorize?client_id=app&request_uri=urn:ietf:params:oauth:request_uri:x7f2qthe front channel now carries a reference, not the request — nothing to read, nothing to bend
Figure — Same lanes, different cargo. Without PAR, every parameter of the ask is a query string that anyone in the front channel can read and try to rewrite. With PAR, the real request travels the private back channel and is checked before any redirect. The address bar carries only a one-time, meaningless receipt.

JAR: sign the request

PAR moves the request out of reach. JWT-Secured Authorization Requests (RFC 9101) makes it provable. The app puts the request into a JWT called a request object. It signs it with its own private key. The server knows the matching public key (see federation trust). Now the server can check who wrote the request and that nothing changed.

FAPI 2.0: the kit

The OpenID Foundation's FAPI 2.0 Security Profile (final since February 2025) puts the protections in one kit. It requires:

  • PAR, PKCE with S256, and exact redirect URIs.
  • Client login with a private key (private_key_jwt) or mTLS, never a shared secret.
  • Tokens that are sender-constrained with DPoP or mTLS, so a copied token is useless to a thief.

The name began as "Financial-grade API". It is for flows where one changed request moves real money, such as open banking.

Do you need it?

Most apps should not copy the whole profile. For a photo app, the auth-code flow with PKCE and exact redirect URIs over TLS is enough. FAPI is for open banking, payments, health records and brokerage. Use it where a regulator requires it, or where "an attacker edits one request" would make the news.

Go deeper: The four bolts at a glance

1 · PAR

The ask travels the back channel. The front channel carries a one-time request_uri. A replay is refused.

2 · Signed request (JAR)

The request is a JWT signed by the client's key. Shuffled or injected parameters break the signature.

3 · Exact redirect URIs

The registered redirect_uri must match as an exact string. No wildcards and no prefix tricks.

4 · PKCE

Even a code that leaks is useless without the private code_verifier. Here it is required, not optional.

Zara's review: she asks four questions of a budgeting app that connects to a bank. Are requests pushed? Are redirect URIs exact? Are tokens sender-constrained? Does the client log in with a key? One no, and she can name the attack it invites.

Signed request objects are not part of the FAPI 2.0 Security Profile. They live in its separate Message Signing profile. Researchers have also formally analyzed the profile.

Now play it. The lab shows PAR step by step, including a thief who replays the receipt. Then you switch protections on and off against four attacks.

🧪 Interactive lab — enable JavaScript to play with this one.

🧪 Try it free

Exact-match redirect URIs are the cheapest of the four bolts. Find mismatches with Redirect Check. Then inspect the sender-constraining proofs FAPI expects with DPoP Check.