| Internet-Draft | DPoP Credential Presentation | September 2026 |
| Lee | Expires 1 April 2027 | [Page] |
This document defines how a Holder presents an issuer-signed JWT credential
directly to an HTTP resource server using OAuth 2.0 Demonstrating Proof of
Possession (DPoP). The credential is carried in the Authorization header with
the DPoP scheme, and possession of the key confirmed in the credential's cnf
claim is demonstrated with a DPoP proof.¶
The wire format is the same as that of a DPoP-bound access token. What this document adds is a model rather than a mechanism: the credential is issued by an authorization server or identity provider that the resource server already trusts, the credential may carry no issuer-defined audience, and the resource server checks the credential's status. Neither an authorization server nor a presentation protocol such as OpenID for Verifiable Presentations is involved between issuance and use.¶
This note is to be removed before publishing as an RFC.¶
Status information for this document may be found at https://datatracker.ietf.org/doc/draft-lee-oauth-dpop-credential-presentation/.¶
Discussion of this document takes place on the Web Authorization Protocol Working Group mailing list (mailto:oauth@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/oauth/. Subscribe at https://www.ietf.org/mailman/listinfo/oauth/.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 1 April 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
An issuer-signed JWT credential is issued once and presented many times to verifiers that were not known at issuance time. Credential formats are mature, but the way a Holder hands a credential to a verifier is specified only for interactive, browser- or wallet-mediated flows, namely OpenID for Verifiable Presentations [OpenID4VP]. OpenID4VP requires the verifier to operate an authorization request, a presentation query language and a response endpoint. That is proportionate when a person opens a wallet, but excessive when software calls an HTTP API.¶
OAuth 2.0 resource servers already have a complete mechanism for accepting a
key-bound token in an HTTP request: DPoP [RFC9449]. A DPoP proof is a
statement, signed by the holder of the key confirmed in the token, that "this
token is being presented for this request". That is the same structure that
credential specifications call a presentation. The resource server verifies
the token with the issuer's key, verifies that the DPoP proof is signed by the
key confirmed in the token's cnf claim, and verifies that the proof is bound
to the request. An OAuth resource server is, in effect, already a presentation
verifier.¶
The gap is most visible for AI agents. Agents are software that call the HTTP APIs of tools and of other agents on behalf of people, and their ecosystem builds authorization on OAuth. The Model Context Protocol authorization specification [MCP.Authorization] defines an MCP server as an OAuth 2.1 resource server, and the Agent2Agent protocol [A2A] lets an Agent Card declare OAuth 2.0 and OpenID Connect security schemes. When these agents need to prove, with a credential, on whose behalf and in what capacity they are calling, there is no standardized presentation method that reuses the OAuth resource request processing model. This document defines one. An agent can present a credential with the OAuth client stack it already uses, and a tool server can verify it with the OAuth resource server stack it already has.¶
This document defines the presentation of an issuer-signed JWT credential with
two HTTP header fields, Authorization: DPoP and DPoP, and adds three rules
to the verification that a DPoP-capable resource server already performs:¶
The verifier trusts the credential's Issuer. In this document the Issuer is an authorization server or identity provider that the verifier already trusts, so the trust configuration is the same as in current DPoP deployments (Section 6.3).¶
The credential may carry no issuer-defined audience. In that case it can be submitted to any verifier that trusts its Issuer, and the DPoP proof binds proof of possession to the request in which it is submitted.¶
A credential may live longer than an access token, so the verifier checks the status information the credential refers to.¶
A credential presented under this document is the same on the wire as a DPoP-bound access token. An implementation can support this document by treating the presented credential as the DPoP-bound token and applying the additional validation rules defined here.¶
Two IETF working group documents already use the same structural pattern of a key-confirmed JWT plus a per-request proof, and this document is deliberately aligned with them.¶
[I-D.ietf-oauth-attestation-based-client-auth] presents a key-confirmed JWT together with a DPoP proof. Its purpose is client authentication: "what is this OAuth client?". The purpose of this document is credential presentation: "what credential does this Holder possess?". The structure is the same; the question answered is different.¶
[I-D.ietf-wimse-wpt] separates a reusable workload identity token from a proof bound to the request. This document follows the same separation, but reuses DPoP instead of defining new header fields.¶
The boundaries with two other documents are as follows.¶
[RFC9068] requires aud in JWT access tokens, so a credential under this
document is not an access token under that profile. The two documents use
the same wire format with different issuance models.¶
A credential conforming to [I-D.ietf-oauth-sd-jwt-vc] can be used under this document when presented without disclosures (Section 4).¶
Presentation protocols such as [OpenID4VP] exist to solve a negotiation problem. The Verifier does not know in advance which credentials the Holder has, the Holder does not know which claims the Verifier needs, and a person may have to be asked for consent in between. An authorization request, a query language such as DCQL and a response endpoint are the cost of that negotiation.¶
Many deployments have no such problem: AI agents calling tool servers, agents calling other agents, and services calling partner APIs. The Holder is an OAuth client that already knows the Resource Server it calls and already holds a credential that the Resource Server accepts. It can submit the credential, whole and unilaterally, with the request, as it would submit an access token. Just as an OAuth client decides which scope to request by reading the resource server's documentation rather than negotiating at runtime, the choice of credential is made at development time. In this situation a runtime negotiation protocol adds round trips, implementation surface and failure modes without adding information.¶
This document is RECOMMENDED when both of the following hold:¶
The Holder is software acting as an OAuth client and submits the credential without a Verifier-initiated request or user interaction at presentation time.¶
The Resource Server is, or can become, a DPoP-capable OAuth resource server.¶
[OpenID4VP] or another Verifier-initiated presentation protocol SHOULD be used instead when the Verifier must discover which credentials the Holder has, when the required claims vary per request and only a subset is to be disclosed, or when a natural person must consent at presentation time. The two mechanisms address different situations and a deployment MAY support both. A Resource Server that implements this document is not thereby required to implement [OpenID4VP], and vice versa.¶
Profiles that require audience-restricted tokens, such as
[MCP.Authorization], can use this document with credentials that carry an
aud claim (Section 6.2).¶
This document specifies only the presentation of a single credential, whole, to an HTTP resource server and its verification. The Issuer is limited to an authorization server or identity provider that the verifier already trusts (Section 6.3). Accepting credentials from external issuers with which the verifier has no prior trust relationship, selective disclosure, issuance, publication of credential status, and delegation between holders are out of scope. For selective disclosure see Appendix C.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
This document sits where credential specifications and OAuth specifications name the same roles differently. The roles correspond as follows, and this document uses the terms in the first column.¶
| This document | OAuth 2.0 (RFC 6749, RFC 9449) | OpenID4VP, SD-JWT (RFC 9901) |
|---|---|---|
| Issuer | Authorization Server or identity provider | Issuer |
| Holder | Client | Holder (Wallet) |
| Verifier | Resource Server | Verifier |
Issuer, Holder and Verifier are as defined in [RFC9901]. In this document the Verifier is always a Resource Server as defined in [RFC6749], and the Holder is always a Client as defined in [RFC6749]. DPoP Proof is as defined in [RFC9449]. An OpenID Connect Relying Party corresponds to the Client in this table, not to the Verifier.¶
+--------+ 1. issue credential (cnf = Holder key) +----------+
| Issuer | ----------------------------------------> | Holder |
+--------+ | (Client) |
| +----------+
| 4. issuer keys, status list |
v | 2. sign
+------------+ | proof
| Verifier | 3. Authorization: DPoP <credential> |
| (Resource | <------------------------------------------+
| Server) | DPoP: <proof: htu, htm, ath, nonce>
+------------+
The Issuer issues a Credential whose cnf claim confirms the Holder's key.¶
For each request, the Holder signs a DPoP proof over the request and the hash of the Credential.¶
The Holder sends the Credential in the Authorization header with the
DPoP scheme and the proof in the DPoP header.¶
The Resource Server verifies the Issuer's signature, the DPoP proof, the key binding between them, and the Credential's status. There is no round trip to the Issuer or to an authorization server on the request path.¶
A Credential is a JWT [RFC7519] signed with an asymmetric algorithm. The following requirements apply to its payload.¶
| Claim | Requirement | Description |
|---|---|---|
iss
|
REQUIRED | Identifies the Issuer. |
sub
|
REQUIRED | Identifies the principal the claims are about. |
exp
|
REQUIRED | |
cnf
|
REQUIRED | Confirmation claim per [RFC7800]. The jwk member is RECOMMENDED; the jkt member of Section 6.1 of [RFC9449] MAY be used. See Section 6.1. |
status
|
RECOMMENDED | Status information per [I-D.ietf-oauth-status-list]. |
aud
|
OPTIONAL | If present, restricts the set of Resource Servers that may accept the Credential (Section 6.2). It does not identify the target of an individual request. |
iat, nbf, jti
|
OPTIONAL | As in [RFC7519]. |
status is not REQUIRED because some Credentials are intentionally
non-revocable, or short-lived enough that revocation is not needed.¶
Other claims MAY be present. The Verifier receives the whole Credential, so there is no step in which the Holder selects claims to disclose. Issuers SHOULD include only claims that may be seen by every Verifier to which the Credential may be presented.¶
The typ header parameter MUST be present and MUST NOT be at+jwt or a value
used for ID Tokens. Deployments MUST define the acceptable typ value or
values for each trusted Issuer.¶
This document does not define the SD-JWT presentation syntax. An SD-JWT VC
[I-D.ietf-oauth-sd-jwt-vc] can be used as a Credential only when its
issuer-signed JWT, carrying cnf, is sent without disclosures.¶
To present a Credential, the Holder creates a DPoP proof JWT as defined in
Section 4.2 of [RFC9449], signed with the private key corresponding to the
Credential's cnf, with the following claims:¶
htm and htu: the HTTP method and target URI of the request.¶
nonce: REQUIRED if the Resource Server has provided a DPoP-Nonce
(Section 9 of [RFC9449]).¶
ath: REQUIRED, computed as defined in Section 4.2 of [RFC9449].¶
This document profiles the DPoP authorization scheme of [RFC9449] as
follows: the Credential takes the place that the access token occupies in
[RFC9449]. Consequently ath is the hash of the Credential value, and the
way it is computed does not change.¶
The Holder sends:¶
Since [RFC9449] makes ath REQUIRED for resource requests, this section is
the client behavior of Section 7.1 of [RFC9449] with the Credential in place
of the access token.¶
A Resource Server that receives a request with the DPoP authorization scheme
performs the following steps. Steps 1 through 4 apply the corresponding
requirements of Section 7.1 of [RFC9449] and Section 4.3 of [RFC9449],
with the Credential as the token value in the ath calculation as specified
in Section 5. Steps 5 through 7 are specific to this document.¶
Check that a DPoP header is present and contains exactly one well-formed
JWT.¶
Verify the DPoP proof's signature, typ, htm, htu, iat freshness,
jti uniqueness and, if required, nonce, as in
Section 4.3 of [RFC9449].¶
Compute the SHA-256 hash of the US-ASCII bytes of the Credential as
received and check that it equals the proof's ath.¶
Check that the DPoP proof's public key matches the key confirmed in the
Credential's cnf (Section 6.1).¶
Verify the Credential's signature with a key of its iss, applying the
algorithm restrictions of [RFC8725]. The Verifier MUST reject a
Credential whose iss it does not trust (Section 6.3).¶
Check exp, nbf and, if present, aud (Section 6.2).¶
If the Credential carries a status claim, obtain and check the status as
defined in [I-D.ietf-oauth-status-list]. The Verifier MUST reject a
Credential whose status is invalid.¶
If any step fails, the Resource Server responds as in
Section 7.1 of [RFC9449] with WWW-Authenticate: DPoP and an appropriate
error code. Resource Servers SHOULD provide DPoP-Nonce values as described
in Section 9 of [RFC9449] to bound the replay window of proofs.¶
What this document adds to resource server validation under [RFC9449] is
steps 5 through 7, in particular the acceptance of Credentials without aud
and the status check.¶
[RFC9449] confirms the key with a JWK thumbprint in cnf.jkt, while
[RFC9901] and [I-D.ietf-oauth-sd-jwt-vc] use cnf.jwk. To interoperate
with both, the Verifier proceeds as follows:¶
If cnf contains jkt, compare it with the JWK SHA-256 thumbprint
[RFC7638] of the jwk header of the DPoP proof.¶
If cnf contains jwk, compute the JWK SHA-256 thumbprint of that key and
compare it with the thumbprint of the jwk header of the DPoP proof.¶
The keys match if and only if the thumbprints are equal. Issuers MAY include both members; if both are present they MUST identify the same key.¶
The only audience is the Credential's aud, and it is set by the Issuer. The
Holder does not set an audience; it only chooses the Resource Server to which
it sends the Credential. The two MUST NOT be confused.¶
The DPoP proof's htu and htm identify the request for which the
Credential is presented. The Verifier accepts the proof only if htu
matches the request it received. This is request-level proof-of-possession
binding and does not replace audience validation.¶
The Credential's aud, if present, is set by the Issuer at issuance and
restricts where the Credential may be used at all. The Verifier MUST reject
a Credential whose aud does not contain the Verifier's configured
identifier. Which identifier a Verifier uses is a matter of deployment
configuration. Issuers SHOULD omit aud unless such a restriction is
intended, because its presence turns a reusable credential into a token for
a fixed set of recipients.¶
In this document the Issuer is a party that the Verifier already trusts. It takes one of two forms, and in neither does the Verifier acquire a new trust relationship.¶
The Issuer is the Verifier's authorization server. The organization's
authorization server issues Credentials under this document alongside, or
instead of, access tokens. The Verifier's trust configuration is the same as
in current DPoP deployments; what changes is the lifetime of the issued
token and the handling of aud and status.¶
The Issuer is an identity provider that the Verifier already trusts. If the organization's OpenID Provider already publishes keys for single sign-on and the Verifier already accepts them, the same identity provider becomes the Issuer of the Credential (Appendix B). Its issuance logic gains one additional token type.¶
In both cases the verification procedure is the same; only the trusted iss
in step 5 differs. Because the Issuer and the Verifier trust each other
already, the claim vocabulary of the Credential and the provision of status
are agreed between them.¶
Accepting Credentials from an external party with which the Verifier has no prior trust relationship is out of scope for this document. That case requires establishing trust through an allow-list or a trust framework and agreeing how the Verifier interprets each Issuer's claim vocabulary, which is a separate problem. The verification procedure of this document would still apply, but this document makes no provision for establishing that trust.¶
A Credential without a DPoP proof is useless to an attacker who does not hold
the confirmed private key. Replay within a proof's validity window is limited
exactly as in [RFC9449], by htu, htm, jti uniqueness and a
server-provided nonce. Verifiers MUST enforce jti uniqueness at least for
the accepted iat window.¶
Specifications such as [I-D.ietf-wimse-workload-identity-practices] require
aud on JWT credentials, with the aim of preventing reuse across trust
boundaries. A Credential without aud can be presented to every Resource
Server that trusts its Issuer. This document does not define trust boundaries
between Resource Servers. If use must be restricted to a particular set of
Resource Servers, the Issuer MUST use aud. Protection is layered:¶
Credentials under this document may live much longer than access tokens. The
role that short access token lifetimes play is taken here by status.
Verifiers MUST check status when present, and MAY treat the absence of
status on a long-lived Credential as grounds for rejection. Issuers SHOULD
provide status information for Credentials whose lifetime is longer than they
are willing to leave unrevocable. Verifiers MAY cache status lists; the cache
lifetime becomes the delay before a revocation takes effect.¶
The Holder submits the Credential whole, so every claim is visible to every
Verifier. Issuers need to design claims with this in mind, and use cases in
which different Verifiers must see different subsets need a selective
disclosure presentation protocol rather than this document (Appendix C).
The Credential travels in an HTTP header and can appear in server access logs
and in proxies that log headers. Deployments MUST use TLS and SHOULD configure
intermediaries not to log the Authorization header.¶
A Verifier that accepts any iss whose keys it can fetch is vulnerable to an
attacker who hosts keys and issues a Credential to themselves. Verifiers MUST
accept as Issuers only authorization servers and identity providers that they
already trust, as described in Section 6.3, and MUST reject a Credential
whose iss is not trusted even if its signature is valid.¶
A Credential is the same on the wire as a DPoP-bound access token. A Resource
Server that accepts both MUST distinguish them by iss and typ.
Interpreting an access token issued by an authorization server as a
Credential, or the reverse, would misapply the trust model and the status
check.¶
The Issuer is not contacted at presentation time and does not learn where or how often a Credential is used, except through status list retrieval. Verifiers SHOULD cache status lists and MAY fetch them through the privacy-preserving means discussed in [I-D.ietf-oauth-status-list]. An issuer-signed JWT is correlatable across Verifiers by its signature value. Deployments that need unlinkability should issue batches of single-use Credentials.¶
This document has no IANA actions. It defines no new header fields, claims, media types or error codes, and profiles the use of those registered by [RFC9449].¶
[OpenID4VP] and this document address different situations and do not compete.¶
| OpenID4VP | This document | |
|---|---|---|
| Initiator | Verifier sends an authorization request | Holder sends an HTTP request |
| Holder | Wallet, usually with a person present | Any software holding the key |
| Transport | Redirects, response_uri, DC API |
Two HTTP header fields |
| Presentation query | DCQL | None; the whole Credential is sent |
| Selective disclosure | Supported | Out of scope |
| Key binding | Key Binding JWT | DPoP proof |
| Verifier implementation | OpenID4VP verifier | DPoP-capable resource server |
An OpenID Provider [OIDC.Core] already signs JWTs about authenticated users
and publishes its keys. It can act as an Issuer under this document by issuing
a token that differs from an ID Token in three ways: it carries a cnf claim
for a key whose possession the Holder demonstrated during authentication, it
omits the aud that an ID Token fixes to the requesting client, and it SHOULD
carry a status claim. Such a token is not an ID Token and MUST NOT be
labeled or accepted as one. Its typ follows Section 4.¶
This document intentionally covers only the submission of a whole Credential.
When the Credential is an SD-JWT [RFC9901] and the Holder wants to disclose
only some of its disclosures, presenting it with the same two header fields is
technically possible. The ath of [RFC9449] and the sd_hash of
[RFC9901] are both defined as a hash of the US-ASCII bytes of the presented
string, so computing ath over the presentation string including disclosures
would let the DPoP proof play the role of the Key Binding JWT.¶
Selective disclosure, however, presupposes that the Holder knows which claims
to disclose, that is, a negotiation with the Verifier. Whether that
negotiation lives in documentation at development time, is declared in OAuth
2.0 Protected Resource Metadata [RFC9728], or is signaled per request
through a WWW-Authenticate challenge (Section 3 of [RFC6750]) is a separate
design problem, as is the relationship with the key binding requirements of
[I-D.ietf-oauth-sd-jwt-vc]. This document leaves that problem open for a
separate document.¶
The structure of this mechanism follows the pattern established by [I-D.ietf-oauth-attestation-based-client-auth] and the WIMSE workload token specifications.¶