DTR OAuth extension · draft
Try the demo →
Interactive OAuth explainer

Deferred Token Response

Let authorization take the time it needs.

A user approves a transfer. The bank still needs to review it. What should the application do while it waits?

Deferred Token Response (DTR) lets an OAuth authorization server respond with “not yet.” Instead of an access token, the client receives a code it can use to check back later — access is granted only once the authorization server approves the request and issues a token.

Explore both sides of that exchange: make a request, act on the other side of it, and watch the client receive the result.

DTR is an evolving OAuth proposal. This sandbox demonstrates selected behavior; the specification defines the full protocol. Read the draft for requirements and security considerations.
Read the specification →
The problem

Some authorization decisions take longer than a request

An application may have everything it needs to ask for access before the authorization server has everything it needs to grant it. A fraud analyst might need to review a transfer, a document owner might need to approve a service, or an automated check might still be running.

A token request normally ends with a token response or an error. DTR adds a defined way to keep that authorization decision pending: the server returns a deferral code, and the client checks for the eventual result.

The authorization server decides whether a particular request needs to wait. The same client can receive an immediate token for one request and a deferred response for another.

Fraud review

A separate reviewer checks a sensitive request after the user has consented.

Document approval

A resource owner grants a service access through an internal review process.

Agent authorization

An agent requests access that needs an additional approval before it can proceed.

Long-running checks

Identity verification or other policy checks finish after the original token request.

Try it

Three reasons a token might need to wait

Each scenario shows the client on the left, the authorization server on the right, and their request logs below. Start with the sample values, then change one thing and compare the result.

Document access that remembers approval

A service requests access to a document using its own credentials. The document owner approves through a separate console. Once approved, later requests for the same document receive a token immediately.

Try this: Request the planning document and approve it. Request it again, then switch to a different document. Watch which requests are deferred.
Try document access →

Human interaction after an identity assertion

A client presents an identity assertion on Alice’s behalf. The authorization server still requires an additional approval and returns a link where that interaction can happen.

Try this: Mint the sample assertion, send the token request, and open the interaction page. Approve or deny the request and watch the client learn the outcome.
Try identity assertion →
The mechanism

Request. Wait. Collect the result.

  1. The client opts in.

    It includes completion_mode=deferred in its token request to signal that it can handle a deferred response.

  2. The server defers the decision.

    It returns authorization_pending, a deferral_code, an expiry, and a minimum polling interval. No access token has been issued.

  3. The client checks back.

    It sends the deferral code to the token endpoint. The server reports whether the request is still pending or needs an external interaction.

  4. The request resolves.

    Approval allows the client to collect the token response. Denial or expiry ends the attempt without a token.

Client Authorization Server POST /token completion_mode=deferred 400 authorization_pending deferral_code, expires_in, interval ↻ Poll at the permitted interval while pending — repeats until resolved POST /token — deferred grant + deferral_code 400 pending response POST /token — deferred grant + deferral_code 200 OK access_token + token metadata

These examples use polling. The deferral code identifies a pending request; it does not grant access to the protected resource.


Background

The OAuth terms used here

OAuth lets an application obtain limited access to a protected resource. These are the terms you will see in the demos:

TermMeaning
ClientThe application or service asking for access.
Authorization serverThe system that evaluates the request and issues an access token when access is granted.
Resource serverThe API or service that accepts the token and provides access to the protected resource.
Resource ownerThe person or organization with authority over the resource — sometimes a single end user, sometimes an organization acting through an internal review process.
Access tokenA credential the client presents to a resource server.
Grant typeThe mechanism the client uses to request a token, such as an authorization code or client credentials.
Deferral codeA code the client uses to retrieve the outcome of a pending token request. It is not an access token.

DTR extends the token response process. The original grant still establishes the basis for the request; DTR handles what happens when the decision needs more time.

Further reading: OAuth overview · OAuth 2.1 draft

On the wire

Follow a deferred token request

The examples below show the polling path. Client authentication and other grant-specific requirements still apply; they are omitted from these short examples.

  1. Tell the server the client can wait

    The client includes deferred in the space-separated completion_mode parameter. Without that opt-in, the server must not defer the token response using DTR.

    POST /token HTTP/1.1
    Host: server.example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code
    &code=example_authorization_code
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &completion_mode=deferred

    Opting in does not force a delay. The server can still return a token immediately. For grants with an earlier request step — the authorization request in the Authorization Code flow, for example — the client can also include this same opt-in there.

  2. Receive a deferral code

    If the server needs more time, it returns an HTTP 400 OAuth error response with authorization_pending and the information needed to continue.

    HTTP/1.1 400 Bad Request
    Content-Type: application/json
    Cache-Control: no-store
    
    {
      "error": "authorization_pending",
      "deferral_code": "example_deferral_code",
      "expires_in": 10800,
      "interval": 60
    }
    ParameterMeaning
    deferral_codeThe opaque code used in later polls for this request. It must be handled according to the draft’s client-binding and security requirements.
    expires_inSeconds until the deferral code expires. This is separate from an access token’s lifetime.
    intervalThe minimum number of seconds between consecutive polls for this deferral code.
    interaction_uriA location where an external actor can act on the request. Optional in the initial deferred response; required with interaction_required.

    The HTTP error format does not mean the authorization request has been denied. Here, it means the result is still pending.

  3. Poll for the outcome

    The client sends the deferral code to the token endpoint using the deferred grant type, respecting the server’s polling interval. The server responds with a variety of error codes depending on the state of the request.

    POST /token HTTP/1.1
    Host: server.example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=urn:ietf:params:oauth:grant-type:deferred
    &deferral_code=example_deferral_code
    HTTP/1.1 400 Bad Request
    Content-Type: application/json
    Cache-Control: no-store
    
    {
      "error": "authorization_pending"
    }
    • authorization_pending Continue polling at the permitted interval. The server has not returned a final result.
    • interaction_required Present the supplied interaction_uri to the appropriate actor and continue polling at the permitted interval.
    • slow_down Increase the polling interval by at least five seconds before continuing.
    • expired_token Stop polling this code. Start a new flow if access is still needed.
    • access_denied Stop polling. The request was denied or cancelled.
    • invalid_grant Stop polling this code. It may be unknown, invalid for this client, or already redeemed.

    Pending authorization responses and polling errors are different concepts. A pending request can change state while the client waits; slow_down tells the client to change its polling behavior. Denial, expiry, and invalid-grant responses end this polling attempt.

  4. Collect the token response

    Once authorization is approved, a successful poll returns the token response the original grant would have produced.

    HTTP/1.1 200 OK
    Content-Type: application/json
    Cache-Control: no-store
    
    {
      "access_token": "example_access_token",
      "token_type": "Bearer",
      "expires_in": 3600
    }

    The deferral code is single-use. After it has been redeemed for a token response, another poll with that code returns invalid_grant.

The full draft also covers callback notifications, cancellation, and sender-constraining with DPoP. These short examples focus on polling.
Read the full protocol and security considerations →
Related work

How does this relate to Device Authorization and CIBA?

Other OAuth and OpenID Connect flows also support waiting for an external action. The distinction is where that waiting fits into the flow.

Device Authorization is a dedicated grant in which a user authorizes a device through a separate interaction. CIBA is a backchannel authentication flow in which the client identifies a user to authenticate.

DTR lets the authorization server defer a token response within an opted-in grant flow. It does not require a particular user-interaction pattern: a request may wait for the user, a separate reviewer, or an internal process.


See the decision happen

Start with fraud review: approve a transfer as the user, then decide its outcome as the reviewer. Watch the client receive its token.

Try fraud review →