The problem JAR solves
With PAR, the printer's request reaches the photo service over a direct, authenticated connection. That protects the request while it travels. Once it arrives, though, the request is a set of form fields in the photo service's storage, and the only evidence of who sent it is the service's own note that the printer authenticated.
For connecting a photo account, that is usually enough. Some requests need assurance that stays with the request itself: proof of who wrote it and that nobody has changed it, which holds wherever the request goes and whoever examines it later.
Protection that ends with the connection
HTTPS protects a message between the two ends of one connection. Those ends are not always the parties you have in mind. A service often ends the encrypted connection at a load balancer or gateway, and the request then passes between internal systems before the part of the service that makes the authorization decision reads it. A request carried by a browser is protected on its way into the browser and on its way out, but not inside it, which is where the problems described in The problem PAR solves arise.
Not every authorization server offers PAR either. Where a request must still travel through the browser, anyone can write one that names the printer, and nobody can tell afterwards which values the printer chose.
The Digital signatures lesson described the alternative with a signed lab result: assurance that travels with the message itself, however many systems it passes through. An authorization request can be treated the same way.
A request that carries its own proof
JWT-Secured Authorization Requests, usually called JAR and published as RFC 9101 in 2021, put the authorization request parameters inside a JWT. Each parameter becomes a claim, and the client signs the whole token with its private key. The result is called a request object. The authorization server verifies the signature with the public key registered for the client, and only then reads the parameters.
A verified signature tells the server two things. The parameters have not changed since the client signed them, because any change would make verification fail. And the request came from whoever holds the client's private key. The client needs a key pair for this, with the public key in its registration, just as for the signed client assertions described in Secrets and signed assertions. It can also encrypt the request object, so that only the authorization server can read the parameters, even if the object passes through a browser.
Because the protection is inside the object, the route matters less. A request object can travel in the browser URL, be published at an address the server fetches, or be pushed to a PAR endpoint. OpenID Connect used request objects before JAR existed, and JAR standardized the idea for OAuth in general.
| Protection | What it covers | What remains afterwards |
|---|---|---|
| HTTPS | One connection between two endpoints. | Nothing that someone else can check later. |
| PAR with client authentication | The route from the client to the authorization server. | The server's own record that the client authenticated. |
| A signed request object | The request itself, along any route. | A signature that anyone with the client's public key can verify. |
Evidence that lasts
That last column matters most when money is involved. Suppose the printer offers Pay by bank for photo books. Instead of typing card details, you choose your bank, Lakeside Bank. When you pay for a 42.50 EUR book this way, the printer asks the bank for authorization to make that payment, and the bank asks you to approve it.
Months later there is a dispute. Perhaps the printer insists it requested a different amount, or the bank's auditors need to show exactly what the printer asked for. If the bank kept the signed request object, it can produce it, and anyone holding the printer's public key can confirm that it verifies. Only the holder of the printer's private key could have created it.
This property is called non-repudiation: the owner of a signing key cannot convincingly deny having signed data that verifies with their public key. It depends on two things: the key must be asymmetric, and the signature must cover the request itself. A request pushed over an authenticated connection falls short. If the printer authenticated with a client secret, the bank holds the same secret. If it authenticated with a signed client assertion, the key is asymmetric, but that signature covers the printer's identity and a moment in time, not the parameters sent beside it. Either way, the bank's record of what was asked for is only the bank's word. A request object signed with a shared secret, which JWT also allows, proves nothing to an outsider either, because the bank could have produced it. And an HTTPS connection leaves nothing behind that anyone else can verify.
Non-repudiation has limits worth stating plainly. A signature proves that the key signed the request, not that a person at the printing company intended it. If the private key was stolen, the signature proves only that the thief had it. And it covers one message at a time, not the whole exchange that followed.
What a signature does not settle
A signature does not stop a request object from being copied. Someone who obtains one can present it again while it remains valid, so request objects usually carry an expiry time and often a unique identifier the server can track. A signature also protects nothing if the server goes on accepting ordinary unsigned requests for the same client, because an attacker would simply send one of those.
And signing the request does nothing for the response. The code and state still return through the browser as plain parameters, with nothing to show where they came from. Protecting them takes a signature from the other side, the authorization server's, which is the subject of the JARM group after this one.