Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

Pushing an authorization request

You select Connect again. This time the printer does not start by building a URL for your browser. Its backend first sends the authorization request to the photo service directly, and only then involves your browser.

The photo service accepts these requests at its pushed authorization request endpoint, often shortened to PAR endpoint, at https://auth.photos.example/par. The printer has the address from its configuration for the photo service, which also appears in the service's metadata under the name pushed_authorization_request_endpoint. Like every endpoint in these exchanges, it uses HTTPS.

Sending the request

All domains, credentials, and identifiers in these examples are fictional. The printer pushes the same request it used to put in the address bar:

POST /par HTTP/1.1
Host: auth.photos.example
Authorization: Basic cGhvdG8tcHJpbnRlcjpkZW1vLW9ubHktbm90LWEtcmVhbC1zZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

response_type=code
&client_id=photo-printer
&redirect_uri=https%3A%2F%2Fprinter.example%2Foauth%2Fcallback
&scope=photos.read
&state=demo-attempt-7
&code_challenge=qd-75t-gnweZAhIl6REjxxgFnPXGwvqYcxq3vlsaJYQ
&code_challenge_method=S256

The body is form-encoded, as in a token request, and its line breaks are for display only. The parameters are exactly those of the authorization request: the response type, client ID, return address, scope, state, and PKCE challenge. Any extension parameter the printer could send to the authorization endpoint can be pushed in the same way.

The Authorization header is the printer's ordinary client authentication, the same client_secret_basic header it sends to the token endpoint. The rules for authenticating at the token endpoint apply here unchanged, including the method recorded in the printer's registration. A client registered for signed assertions, as described in Secrets and signed assertions, sends a client assertion instead, and its aud is the server's issuer identifier, just as at the token endpoint. PAR's specification originally told servers to accept their token endpoint or PAR endpoint address there as well. The tightened guidance described in that lesson replaces both with the issuer identifier alone.

Notice that client_id still appears in the body, although the header names the printer too. In the body it belongs to the authorization request, which always names its client. In the header it is part of a credential. Both name photo-printer, and a careful server refuses a push in which they disagree.

The body carries an authorization request and nothing else. The specification rules out one authorization parameter by name: request_uri, the reference this endpoint is about to hand out, because a push must not point to another stored request. Token request parameters such as grant_type or code have no meaning here either, since the body is not a token request. The only additions are client authentication parameters, which are used only to authenticate.

A public client can push as well. The printer's phone app would send a similar body under its own client ID, photo-printer-app, with no credential, because it has none to send. It still keeps its parameters out of the browser and gets a short URL, but the service cannot authenticate it at this point any more than it could at the token endpoint.

What the server checks

When the push arrives, the photo service works through it in order:

  1. Authenticate the client as it would at the token endpoint. If the printer's secret was replaced and one server still has the old one, the push fails here with invalid_client, before you have seen a single page.
  2. Refuse a push that contains request_uri.
  3. Validate the parameters as an authorization request. The return address must match one registered for this client, the scope must be one the printer may request, the response type must be allowed, and a PKCE challenge must be present if the service requires one.

This is where the late checks from The problem PAR solves move to the front. The service knows which client is asking and whether its request is acceptable before anyone is sent to a sign-in page. A request that fails is refused in a direct response to the printer, and you are never involved.

A service may postpone a check it cannot perform yet, but it must then perform that check when your browser arrives at the authorization endpoint. Nothing about signing in or consent is decided here either, because you have not been asked anything. Those decisions still happen in your browser, later.

The request URI it returns

When the checks pass, the service stores the request and answers:

HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-cache, no-store

{
  "request_uri": "urn:ietf:params:oauth:request_uri:demo-pushed-request-7",
  "expires_in": 90
}

The status is 201 Created because the service has created something: a stored authorization request. The request_uri refers to it. Despite the name, it is not an address the printer or anyone else can fetch. It is a URN, a uniform resource name: an identifier written in URI syntax that names something without saying where to retrieve it. The urn:ietf:params:oauth:request_uri: prefix is a standard form that servers may use, and the rest is up to the server. A real value must contain a part generated with a cryptographically strong random generator so that nobody can guess it. demo-pushed-request-7 is a readable stand-in.

expires_in gives the reference's lifetime in seconds. Ninety seconds is this example's choice. The specification leaves it to the server and expects it to be short, typically somewhere between a few seconds and ten minutes. The reference is also bound to the client that pushed it, so only photo-printer can use it.

The printer saves the request URI with the pending transaction, next to the PKCE verifier, and sends your browser on at once. The reference is not a secret in the way the verifier is, because your browser is about to carry it. It is simply good for one attempt and a short time.

When you select Connect, the printer backend sends the authorization request parameters directly to the photo service's pushed authorization request endpoint and authenticates as the photo-printer client. The authorization server authenticates the client and validates the request before any user interaction, stores it, and returns a single-use request URI that expires in 90 seconds. The printer redirects your browser to the authorization endpoint with only the client ID and the request URI. The authorization server loads the stored request and checks that it is unexpired, unused, and bound to this client before you sign in and consent. The authorization response returns through your browser with code, state and iss as usual, and the printer exchanges the code at the token endpoint in the usual way. When you select Connect, the printer backend sends the authorization request parameters directly to the photo service's pushed authorization request endpoint and authenticates as the photo-printer client. The authorization server authenticates the client and validates the request before any user interaction, stores it, and returns a single-use request URI that expires in 90 seconds. The printer redirects your browser to the authorization endpoint with only the client ID and the request URI. The authorization server loads the stored request and checks that it is unexpired, unused, and bound to this client before you sign in and consent. The authorization response returns through your browser with code, state and iss as usual, and the printer exchanges the code at the token endpoint in the usual way.
The push happens directly between the printer backend and the photo service. Your browser carries only the client ID and the request URI, and the rest of the flow is unchanged.

From here, the exchange looks almost like the one you already know. The difference is what your browser carries to the authorization endpoint: a client ID and this reference, and nothing else.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2One of the printer's servers still has an old client secret. When does the photo service notice, if that server starts a connection with PAR?

QUESTION 2 OF 2Why does the pushed request include client_id in the body when the Basic header already identifies the printer?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity