Dear OAuth Working Group,

I would like to propose an idea for discussion around *DPoP nonce handling*,
particularly in OAuth flows using *PAR (Pushed Authorization
Requests)* and *CIBA
(Client-Initiated Backchannel Authentication)*.

The main goal is simple:

*Can the Authorization Server provide a DPoP nonce to the client before the
first DPoP-protected token request, so that the client does not have to
make an initial request that fails with **400 use_dpop_nonce**?*
------------------------------
*1. Current DPoP nonce flow*

When an Authorization Server requires a DPoP nonce, the client may
initially send:

Client → Authorization Server

POST /token
DPoP: <proof without nonce>

The Authorization Server responds:

HTTP/1.1 400 Bad Request
DPoP-Nonce: ABC123

The client then has to retry:

Client → Authorization Server

POST /token
DPoP: <proof containing nonce ABC123>

So the initial flow becomes:

       /token
Client ────────→ AS
       ←────────
       400 + nonce

       /token again
Client ────────→ AS
       ←────────
       Access Token

This is secure and intentional, but it introduces an additional round trip
purely for nonce discovery.
------------------------------
*2. Proposed idea*

I propose that the Authorization Server could *pre-provision a DPoP nonce
through an existing back channel*, such as PAR.

The nonce would simply be:

   - generated by the Authorization Server
   - cryptographically random
   - short-lived
   - usable in a subsequent DPoP proof
   - not necessarily required to be cryptographically bound to the PAR
   request itself

The DPoP key binding would continue to be handled independently through the
existing DPoP mechanisms.
------------------------------
*3. Using PAR as the nonce bootstrap channel*

PAR already provides a direct client-to-AS back channel.

The proposed flow would be:

Client                         Authorization Server
  |                                  |
  |-------- POST /par -------------->|
  |                                  |
  |<------- 201 Created -------------|
  |        request_uri               |
  |        DPoP-Nonce: ABC123        |
  |                                  |
  |                                  |
  |-------- /authorize ------------->|
  |        request_uri               |
  |                                  |
  |<------- authorization code ------|
  |                                  |
  |-------- POST /token ------------>|
  |        DPoP proof                |
  |        nonce = ABC123            |
  |                                  |
  |<------- access token ------------|

The important difference is that the client already has the nonce *before
calling **/token*.

Therefore:

Current:

/token → 400 + nonce → /token again


Proposed:

/par → nonce → /authorize → /token → success

This avoids the initial failed request.
------------------------------
*4. Why PAR is interesting for this*

One challenge with returning the nonce from the normal authorization
response is that the authorization response normally passes through the
browser/user-agent.

For example:

HTTP/1.1 302 Found
Location: https://client.example/callback?code=ABC
DPoP-Nonce: XYZ

The browser receives the response header, but the OAuth client application
cannot necessarily access that header.

Putting the nonce directly into the authorization response parameters would
also introduce additional considerations around URL exposure, logging,
browser history, response modes, etc.

With PAR, however:

Client ←→ AS

is already a direct back-channel interaction.

Therefore, PAR appears to provide a natural place for nonce
pre-provisioning.
------------------------------
*5. Does the nonce need to be bound to PAR?*

My initial assumption is that *the nonce does not necessarily need to be
cryptographically bound to the PAR request*.

The nonce can simply represent:

“This is a fresh value generated by the Authorization Server and currently
accepted for a DPoP proof.”

The security responsibilities would remain separate:

DPoP private key + signature
        ↓
Proof of possession


DPoP nonce
        ↓
Server-controlled freshness

Existing DPoP key-binding mechanisms such as dpop_jkt can continue to
provide the relationship between the authorization request/code and the
DPoP key.

The nonce therefore doesn’t necessarily need to establish the client’s
identity or key ownership.
------------------------------
*6. Possible nonce lifecycle*

A simple model could be:

PAR
 ↓
AS generates nonce N1
 ↓
Client receives N1
 ↓
User authenticates
 ↓
Authorization code
 ↓
Client creates DPoP proof containing N1
 ↓
/token
 ↓
AS validates N1
 ↓
Access token

The nonce could have a short lifetime and/or appropriate replay protections.

For example:

Nonce:
    Random
    Short-lived
    Server-generated
    Valid for DPoP proof

The exact lifetime and reuse rules would obviously need to be defined.
------------------------------
*7. CIBA provides another interesting use case*

A similar concept seems particularly relevant to *CIBA (Client-Initiated
Backchannel Authentication)*.

CIBA already separates the user authentication interaction from the client
through a back channel:

Client
   |
   | Authentication request
   ↓
Authorization Server
   |
   | User authentication
   ↓
User's device
   |
   | Approve
   ↓
Authorization Server
   |
   | Result
   ↓
Client

Unlike the traditional browser-based Authorization Code flow, CIBA already
has a direct communication channel between:

Client ↔ Authorization Server

Therefore, the AS could potentially provide a DPoP nonce as part of the
back-channel authentication transaction.

Conceptually:

Client → AS
        |
        | CIBA request
        ↓
      User authentication
        |
        ↓
AS → Client
    authentication result
    + DPoP nonce
        |
        ↓
Client → /token
        DPoP(nonce)
        |
        ↓
Access Token

Again, the purpose would simply be to eliminate the initial:

/token → 400 use_dpop_nonce

challenge.
------------------------------
*8. PAR and CIBA comparison*

The idea can therefore apply to two different back-channel scenarios:

*Flow*

*Possible nonce bootstrap*

Normal Authorization Code + PAR

AS provides nonce in PAR response

CIBA

AS provides nonce through the back-channel authentication interaction

The common principle is:

Existing secure back channel
          ↓
AS generates DPoP nonce
          ↓
Client receives nonce
          ↓
First token request already contains nonce

------------------------------
*9. Security model*

The proposal does *not* attempt to replace DPoP’s proof-of-possession
mechanism.

The validation would still be approximately:

                 DPoP Proof
                     |
          ┌──────────┴──────────┐
          ↓                     ↓
     Signature valid?       Nonce valid?
          |                     |
          ↓                     ↓
      Key ownership         Freshness
          |                     |
          └──────────┬──────────┘
                     ↓
              Continue OAuth

The nonce is therefore an additional freshness mechanism rather than a
replacement for the DPoP key binding.
------------------------------
*10. Main benefit*

The primary benefit is reducing the number of network requests.
*Current approach*

1. /token
2. 400 + nonce
3. /token again
4. Access token

*Proposed approach*

1. PAR
2. /authorize
3. /token + pre-provisioned nonce
4. Access token

The first token request can already contain a valid DPoP proof.

This could be particularly valuable in high-latency environments and
distributed systems where an additional round trip has a measurable impact.
------------------------------
*11. Questions for the Working Group*

I would appreciate feedback on whether this approach could be considered as
a future extension/profile of DPoP.

In particular:

   1. *Can PAR be used as a nonce bootstrap mechanism for DPoP?*
   2. Does the nonce need to be bound to the PAR request, authorization
   code, or DPoP key?
   3. Could a short-lived server-generated nonce simply be issued by the AS
   and used in the subsequent DPoP proof?
   4. Should the nonce be returned using the existing DPoP-Nonce response
   header, or would a new PAR response parameter be more appropriate?
   5. Could a similar mechanism be defined for CIBA?
   6. What replay and lifetime requirements would need to be specified?
   7. Would this require an extension to RFC 9449, an extension/profile of
   PAR, or a separate specification?
   8. Are there existing OAuth WG discussions or proposals addressing DPoP
   nonce pre-provisioning that I may have missed?

------------------------------
*Summary*

The proposal can be summarized in one sentence:

*Use an existing OAuth back channel such as PAR or CIBA to pre-provision a
short-lived, server-generated DPoP nonce, allowing the client’s first token
request to contain a valid DPoP proof and avoiding the initial **400
use_dpop_nonce** challenge.*

I would be very interested in feedback on whether this provides a
meaningful optimization while preserving the security properties and
intended semantics of DPoP.


Thanks & Regards,
Vijay
Programmer | Cyber Security
Email: [email protected]

On Fri, 16 Jan 2026 at 11:27 PM, Will Bartlett <[email protected]>
wrote:

> I envisioned nonce mostly encoding one of two pieces of data:
>
>    1. A timestamp, to prevent a compromised client from forward dating
>    requests.
>    2. A request hash, to get a signature for a specific request.
>
>
> Microsoft's PoP implementation (which is not quite DPoP, but close enough
> for this conversation) uses nonces as secure timestamps and has dedicated
> endpoints for retrieving nonces (though these predate the DPoP-Nonce
> header, so I'm not sure that we would build them today, given that we
> already have DPoP-Nonce). With this implementation, there's no security
> problem that I know of. Nonces are returned in 200s mostly as an
> optimization - to return a fresh signed timestamp at 80% of the expiration
> of the current nonce. A client might still hit a 401 if its nonce expires
> due to the client making no requests in the last 20% of the nonce lifetime.
>
> I guess my two cents would be that nonce expiration isn't so different
> from token expiration / revocation, and really shouldn't be a problem. When
> you use OAuth, sometimes your tokens will fail randomly (from the
> perspective of the application developer) with a 401 because the user e.g.
> changed their password in another tab or on another device, and some sort
> of backend revocation occurred. The client reacts to the 401 by returning
> to the OAuth authorization or token server to obtain a fresh refresh or
> access token, potentially showing the user some UI first. There's nothing
> inherently problematic about 401s occurring - the client just needs to
> handle them.
>
> Thanks,
> Will
>
> ------------------------------
> *From:* vj <[email protected]>
> *Sent:* Wednesday, January 7, 2026 3:42 AM
> *To:* [email protected] <[email protected]>
> *Subject:* [EXTERNAL] [OAUTH-WG] Question: Improving DPoP Nonce
> Provisioning Without ERROR Responses
>
> You don't often get email from [email protected]. Learn why this
> is important <https://aka.ms/LearnAboutSenderIdentification>
> Hello OAuth Working Group,
>
> I’m currently implementing DPoP (RFC 9449) and have encountered a
> practical UX challenge related to the way DPoP nonces are issued by
> authorization servers.
>
> Per the current standard, when a client sends a DPoP request that requires
> a nonce, the authorization server responds with a 400 Bad Request (or 401
> Unauthorized from a resource server) including a DPoP-Nonce header and a
> use_dpop_nonce error code. The client is then expected to retry the
> request with the supplied nonce in the DPoP proof’s nonce claim. IETF
> <https://www.ietf.org/rfc/rfc9449.html?utm_source=chatgpt.com>
>
> In many implementations today, this leads to visible error responses in
> client logs or user interfaces before the retry occurs. This behavior —
> although correct per the spec — sometimes confuses customers or developers
> because an error response is served before the nonce exchange completes.
>
> *Questions / Suggestions:*
>
>    1.
>
>    *Is there any recommended best practice for provisioning a nonce
>    outside of a 400/401 error response?*
>    For example, could a dedicated endpoint be defined for clients to
>    fetch the current nonce from the authorization server prior to a token or
>    resource request?
>    2.
>
>    While the spec allows nonces to be supplied in a 200 OK response
>    header instead of via challenge responses, that behavior is optional. If
>    used consistently, it could avoid initial error responses entirely. Are
>    there guidelines or recommendations on when servers should prefer this 200
>    OK mechanism? IETF
>    <https://www.ietf.org/rfc/rfc9449.html?utm_source=chatgpt.com>
>    3.
>
>    If introducing an endpoint solely to serve a current nonce is *not* 
> advisable
>    for security or protocol correctness reasons, could the group clarify the
>    intended UX pattern for nonces in high-frequency or browser environments?
>
> We’d appreciate any clarification or guidance the working group can
> provide.
> --
> Thanks & Regards,
> Vijay
> Programmer | Cyber Security
> Email: [email protected]
>
_______________________________________________
OAuth mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to