Internet-Draft oauth-software-statement-issuance August 2026
McGuinness Expires 8 February 2027 [Page]
Workgroup:
Web Authorization Protocol
Internet-Draft:
draft-mcguinness-oauth-software-statement-issuance-latest
Published:
Intended Status:
Standards Track
Expires:
Author:
K. McGuinness

OAuth 2.0 Software Statement Issuance

Abstract

RFC 7591 standardizes how a client presents a software statement and how a registration endpoint consumes it, but not how the client obtains one. This specification defines OAuth 2.0 issuance flows for that artifact, in which a Client ID Metadata Document identifies a client that has not been registered with the authorization server.

In the redirect flow, the authorization endpoint returns a short-lived software_statement_code, which the client redeems using a new token endpoint grant. A completed decision returns a statement; a pending decision uses Deferred Token Response and polling. The statement never appears in an authorization response URL.

A client that holds an initial access token authorizing issuance instead uses OAuth 2.0 Token Exchange (RFC 8693), without a redirect.

The issued statement is consumed through RFC 7591 dynamic client registration; a companion specification defines sender-constrained runtime presentation in authorization and token requests.

Status of This Memo

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 8 February 2027.

Table of Contents

1. Introduction

Section 2.3 of [RFC7591] defines a software statement as a JWT that asserts client metadata. A client presents it to a dynamic client registration endpoint, where the signature identifies who attested to the metadata. [RFC7591] standardizes consumption, but not issuance.

Today, issuance relies on manual provisioning, deployment-specific portals, or proprietary federation processes. The UK Open Banking Directory and Australian Consumer Data Right Register each built a central issuer for statements consumed through the same [RFC7591] software_statement member ([UK-OPEN-BANKING], [AU-CDR]). Clients nevertheless need an ecosystem-specific issuance integration for each.

A portal does not provide interoperable submission, deferral, delivery, metadata binding, renewal, or errors. This specification standardizes that protocol while leaving approval workflow, acceptance policy, and issuer trust to deployments.

Pre-registration [CIMD], pushed registration [PUSHED-DCR], and approval-based registration [APPROVAL-DCR] each establish trust bilaterally at one authorization server from client-supplied metadata.

A software statement makes an issuer's decision portable. A publisher program, enterprise security function, or ecosystem operator reviews the software once; each authorization server in the audience can rely on the signed decision under its own policy (Section 16.2, Appendix C.1, Section 1.1).

This specification supplies the missing issuance protocol and hardens the existing artifact for interoperability (Section 11). This document owns issuance, the statement format, and validation; the companion [PRESENTATION] owns consumption, covering registration validity and renewal as well as runtime presentation in authorization and token requests (Section 12). It introduces no new client credential or federation architecture. Portability remains bounded by configured issuer trust, typically within an ecosystem or administrative domain rather than the open web.

A client identified by its [CIMD] URL obtains a statement through either:

The flow concerns client establishment, not authorization to access a protected resource. Consequently, a software statement request cannot be combined with scope, resource, authorization_details, or an access-token-producing response type.

Other mechanisms are preferable when:

A software statement earns its cost beyond those boundaries when one or more of the following holds:

  1. One approval must be honored at many authorization servers.

  2. The party approving the software is not the resource owner in a transaction.

  3. Approval must exist before any authorization transaction does.

  4. Approval requires asynchronous review that outlives a single protocol exchange.

  5. Issuance and renewal must be automated rather than performed through a portal.

Where none applies, this issuance protocol is unnecessary. Issuance is decoupled from access grants and can complete out of band over hours or days. Appendix A illustrates the boundaries.

1.1. What Pre-Registration Does Not Solve

Pre-registration [CIMD] lets a client enroll its identifier URL before its first authorization request. The authorization server fetches the metadata, reviews it, and records a local decision. This specification does not replace that model.

Pre-registration changes when the trust decision is made, but not:

  • Who decides: each consuming authorization server still evaluates the client's self-asserted document.

  • What transfers: the decision remains local state and cannot be presented elsewhere.

  • What was approved: the subject is a URL whose content can change, with no interoperable binding to the reviewed version.

  • What acceptance depends on: later evaluation still requires dereferencing the document.

A software statement makes one decision portable, binds it to the exact content evaluated (Section 4.1), and permits offline verification. This is useful where many authorization servers are not staffed to review software: each verifies a trusted issuer's signature instead of running an approval process. The mechanisms compose (Appendix C.1).

1.2. Relationship to Other Specifications

This specification uses the following building blocks:

  • [RFC7591] defines the software statement and the client metadata carried in it.

  • [CIMD] defines the client identifier, canonical metadata source, pre-registration, and metadata-change handling. Those mechanisms can serve as approval-carrying enrollment, while the metadata digest (Section 4.1) makes changes precisely detectable.

  • [DTR] defines client opt-in, token endpoint deferral, polling, cancellation, and sender constraint. This specification profiles it for both issuance flows.

  • [RFC8693] defines both the response convention for non-access security tokens and the exchange profiled in Section 8.

[APPROVAL-DCR] creates an authorization-server-specific client_id and, when applicable, client credentials after approval. This specification issues a portable statement for later [RFC7591] registration. The two compose (Appendix C.1).

[PUSHED-DCR] pushes registration alongside an authorization flow at the same authorization server. Such a registration can carry a statement issued under this specification. That composition is out of scope; combining issuance itself with an access-granting response type remains prohibited (Section 5.1).

[CLIENT-INSTANCE] carries per-instance identity into tokens for runtime instances behind one client_id. This specification carries the trust decision about the client software to the trusting authorization server. Section 13 describes their composition.

OpenID Federation [OPENID-FED] conveys attested metadata through trust chains, suiting ecosystems prepared to operate federation infrastructure. This specification instead issues the existing [RFC7591] artifact under explicit issuer trust. Federation standardizes trust resolution, not enrollment, approval, or deferred completion; it relocates rather than replaces the issuance ceremony defined here.

The OAuth Identity Assertion Trust Framework [TRUST-FRAMEWORK] could generalize pairwise configuration by evaluating issuers against published conditions, including authority over the client's identifier namespace. Such a profile is out of scope.

This specification does not define approval workflow, approver identity, external approval integration, acceptance of any particular issuer, or issuer discovery. Acceptance policy and trust establishment are deployment-specific. A future metadata-document member could name issuers authorized for the publisher's namespace and serve as [TRUST-FRAMEWORK] evidence.

2. Conventions and Definitions

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.

OAuth terminology is defined by [RFC6749]. Client metadata and software statement terminology is defined by [RFC7591]. Client ID Metadata Document terminology is defined by [CIMD]. Deferred response terminology is defined by [DTR].

This specification additionally defines the following terms:

Software Statement Request:

A request in which a client asks an authorization server to issue a software statement, sent as an authorization request with response_type=software_statement_code.

Issuing Authorization Server:

The authorization server that makes the issuance decision and signs the software statement.

Trusting Authorization Server:

An authorization server that consumes the issued software statement, in a dynamic client registration request (Section 12), a runtime presentation, or a replacement delivery ([PRESENTATION]).

Software Statement Code:

The short-lived, single-use artifact returned by the software statement code response (Section 6.1) and redeemed at the token endpoint (Section 7). It is not an authorization code: redeeming it yields the software statement token response or a deferred token response, never an access token.

Originating Request:

A request that can produce a software statement: a software statement code redemption (Section 7) or a token exchange (Section 8). Each yields a statement, a terminal denial, or, at a deferred issuer, a deferral.

Metadata Snapshot:

The validated canonical metadata bound to a request, as defined in Section 4.1.

Metadata Digest:

The unpadded base64url encoding of the SHA-256 hash of the retrieved octets of a metadata document, as defined in Section 4.1.

3. Protocol Overview

A client initiates the redirect flow at the authorization endpoint and redeems the resulting software statement code at the token endpoint. The issuer either completes the decision synchronously or defers it under [DTR]. A client that already holds an initial access token authorizing issuance instead uses token exchange, without a user agent (Section 8).

The flow has four elements:

  1. An HTTPS Client ID Metadata Document URL identifies the client, and its content supplies the canonical metadata [CIMD].

  2. The issuing authorization server fetches and snapshots that document, decides whether to issue, and signs the statement (Section 4.1).

  3. The client presents the statement to consuming servers: in an [RFC7591] registration request (Section 12), a sender-constrained runtime presentation, or a delivery that renews what a server already holds ([PRESENTATION]).

  4. Trusting authorization servers in its audience apply their local acceptance policies.

The URL remains the client identity when its content changes. One issuance decision can serve many registrations and runtime presentations (Appendix C.1).

                +--------------------------+
                | Client ID Metadata       |
                | Document (client_id URL) |
                +--------------------------+
                  ^                      ^
            hosts |                      | fetches and
                  |                      |   snapshots
+----------+      |                      |      +---------------+
|          +------+                      +------+    Issuing    |
|  Client  |                                    | Authorization |
|          |--(1) software statement request -->|    Server     |
|          |<-(2) software statement -----------|   (approval)  |
+----------+      (signed JWT)                  +---------------+
     |
     | (3) RFC 7591 registration request
     |     carrying the software statement
     v
+---------------+  +---------------+       +---------------+
|   Trusting    |  |   Trusting    |  ...  |   Trusting    |
| Authorization |  | Authorization |       | Authorization |
|   Server 1    |  |   Server 2    |       |   Server M    |
+---------------+  +---------------+       +---------------+

The figure shows the registration path. Under runtime presentation ([PRESENTATION]), step 3 is instead a sender-constrained authorization or token request carrying the statement, and no registration is created.

3.1. Redirect Flow Overview

+--------+                                  +----------------------+
| Client |                                  | Authorization Server |
+--------+                                  +----------------------+
    |                                                 |
    | (A) Authorization request                       |
    |     response_type=software_statement_code       |
    |     client_id=<metadata document URL>           |
    |     code_challenge, [audience], [dpop_jkt]      |
    |------------------------------------------------>|
    |                                                 |
    | (B) Software statement code response            |
    |     (software_statement_code, state, iss)       |
    |<------------------------------------------------|
    |                                                 |
    | (C) Redemption                                  |
    |     (software_statement_code, code_verifier,    |
    |      completion_mode=deferred)                  |
    |------------------------------------------------>|
    |                                                 |
    | (D) Software statement response or              |
    |     deferred response (deferral_code)           |
    |<------------------------------------------------|
    |                                                 |
    | (E) Poll(s) (deferral_code), if deferred        |
    |------------------------------------------------>|
    |     authorization_pending or final response     |
    |<------------------------------------------------|

At (A), the client requests a statement. The authorization server validates the request, performs any user-agent interaction or initiates an approval workflow, and returns a software statement code at (B).

At (C), the client redeems the code with its PKCE verifier. Redemption returns the statement at (D) or a [DTR] deferral_code; in the latter case, the client polls at (E). Errors follow [RFC6749] and [DTR].

4. Client Identification and Authentication

The client_id in every request defined by this specification MUST be a client identifier URL conforming to [CIMD]. The authorization server MUST obtain and validate the corresponding Client ID Metadata Document according to [CIMD]. A non-URL identifier issued by the authorization server is not supported by this specification.

In the redirect flow, the authorization server MUST compare the redirect_uri in the request with the redirect_uris in the Client ID Metadata Document according to [CIMD] and [RFC9700]. The authorization server MUST NOT redirect the user agent when the client identifier or redirect URI is missing or invalid. A client identifier whose metadata document cannot be retrieved or validated, including a document rejected for duplicate member names (Section 4.1), is invalid for this purpose; the authorization server reports the failure directly to the user agent rather than to the redirection endpoint.

The client authenticates to the token endpoint using the token_endpoint_auth_method and related key metadata in its Client ID Metadata Document. The authorization server classifies the client from that member:

Classification uses the singular token_endpoint_auth_method; this specification does not interpret a list of methods a client merely declares it supports, and a client that wants a deterministic classification for issuance declares the singular member.

Sender constraint is established per flow:

All uses of DPoP MUST follow [RFC9449] and [DTR].

4.1. Metadata Snapshot

Client metadata documents can change while a request is pending. Before returning a software statement code or a deferral code, the authorization server MUST bind it to the validated canonical metadata. The bound values constitute the metadata snapshot for the request.

The authorization server MAY retrieve the document again before issuing the software statement. If it does so and detects a security-relevant change (for example, a change to jwks, jwks_uri, redirect_uris, or token_endpoint_auth_method), it MUST either re-evaluate the request under the new metadata or reject the request. It MUST NOT silently combine values from different document versions.

Re-evaluation replaces the bound snapshot in full. A statement attests the snapshot in effect when it is signed, and cimd_digest is that snapshot's digest, so a client that observes a digest other than the one it expected knows which document content was attested. An approval recorded against a superseded snapshot does not carry forward to its replacement without a fresh issuance-policy decision. Replacing the snapshot does not alter the sender-constraint context recorded for a deferral, which remains as it was fixed at origination (Section 9). If a replacement snapshot no longer authorizes the key material behind that context, for example because the client-authentication key is absent from the new document, the authorization server MUST invalidate the deferral; the client makes a new request under its current keys.

The metadata digest is the unpadded base64url-encoded SHA-256 hash [RFC6234] of the retrieved representation body after removal of content coding. No transcoding, normalization, or re-serialization occurs; a byte order mark and trailing newline are included. Retrieval for snapshot purposes SHOULD NOT use content negotiation, and an issuance source SHOULD serve the document without negotiated variants, so that independent fetchers obtain identical bytes.

Equal digests identify the same document for this specification. A changed digest marks a new trust state for the same client identifier and is the signal used by the re-evaluation rule above. The digest also supplies the cimd_digest claim (Section 11) and audit guidance (Section 16).

Byte identity deliberately detects serialization-only changes. A digest mismatch is an input to policy, not a validation failure. A publisher SHOULD serve a stable byte artifact whose octets change only with its metadata; a document rendered dynamically or served through content negotiation produces digest changes unrelated to its metadata. The authorization server MUST reject duplicate object member names, because parsers can interpret them differently despite an identical digest.

An issuance source SHOULD publish keys by reference through jwks_uri rather than inline through jwks. Rotation behind a stable URI leaves the document and digest unchanged; inline rotation changes both, so the attested keys no longer match the current document and a new statement is needed. The statement attests either the key location or the inline keys. The convenience cuts both ways: rotation invisible to the digest means key-host compromise is also invisible to it, and where the attested key is the runtime proof under [PRESENTATION] the compromise substitutes the presenter as well; Section 16.7 weighs the trade, and an issuer serving theft-sensitive deployments attests jwks inline instead.

A metadata document used as an issuance source MUST NOT contain a software_statement member, although [CIMD] otherwise permits one. Embedding a prior statement would change the digest on every issuance; an issuing authorization server treats a document containing one as failing validation for issuance. A statement is presented in a registration request (Section 12) or at runtime ([PRESENTATION]), never embedded in the source document.

5. Software Statement Authorization Request

The client sends an authorization request as described in Section 4.1.1 of [RFC6749], with the following parameters:

response_type:

REQUIRED. The value MUST be software_statement_code.

client_id:

REQUIRED. The client identifier URL described in Section 4.

redirect_uri:

REQUIRED. The value MUST exactly match one of the redirection URIs in the Client ID Metadata Document, subject to the redirect URI rules of [CIMD]. A public client MUST use an HTTPS redirection URI and MUST NOT use a private-use URI scheme or a loopback interface redirection URI in a software statement request. A confidential client MAY use a loopback or private-use redirection URI, because redemption is bound to its client authentication (Section 16.4); such a request MUST also include dpop_jkt, since a declared confidential method proves key possession, not that the key is absent from distributed software.

state:

REQUIRED. An opaque value used by the client to bind the authorization response to its request. The authorization server MUST return the exact value in the authorization response.

code_challenge:

REQUIRED. A PKCE challenge as defined by [RFC7636].

code_challenge_method:

REQUIRED. The value MUST be S256.

response_mode:

OPTIONAL. The mechanism for returning authorization response parameters, as defined by [OAUTH-MRT]. The default response mode for response_type=software_statement_code is query. Response mode considerations are given in Section 6.1.

audience:

OPTIONAL. A target service at which the client intends to use the statement, with the semantics defined in Section 2.1 of [RFC8693]. The parameter MAY be repeated to request multiple audiences. Each value MUST be an authorization server issuer identifier as defined by [RFC8414]; values MUST NOT be repeated, and order is insignificant. The authorization server selects the final audience according to policy. When this parameter is present, every value in the statement's aud claim MUST have appeared in the request. If no requested audience is acceptable, the authorization server MUST reject the request with invalid_target [RFC8693], following the authorization-request precedent of [RFC8707]. These semantics apply only to software statement requests and do not affect proprietary uses of audience for access-token targeting.

completion_mode:

OPTIONAL. A value that includes deferred, sent as the advance hint [DTR] defines for an endpoint preceding a token request. It lets the authorization server choose a review path suited to out-of-band completion before it begins work, and does not replace the opt-in required at redemption (Section 9).

dpop_jkt:

REQUIRED for a public client and for any request whose redirect_uri is a loopback or private-use URI; OPTIONAL otherwise. The parameter has the semantics defined in Section 10 of [RFC9449]. When present, its value MUST be associated with the resulting software statement code and with any deferral state derived from its redemption.

The authorization server MUST reject with invalid_request a request that omits a required PKCE parameter or a required dpop_jkt.

The following is a non-normative example of an authorization request from a confidential client; a public client would additionally include dpop_jkt (line breaks are for display purposes only):

GET /authorize?response_type=software_statement_code
  &client_id=https%3A%2F%2Fclient.example.org%2Fmetadata.json
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  &state=4L7xQ2mN9pR6sT1vW8yZ3aB5cD0fG2hJ
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256 HTTP/1.1
Host: server.example.com

5.1. Prohibited Parameters

A software statement request does not grant access to a protected resource. The following authorization request parameters MUST NOT be present:

  • scope;

  • resource, as defined by [RFC8707]; and

  • authorization_details, as defined by [RFC9396].

An authorization server MUST reject a request containing any of these parameters with invalid_request. The same prohibition and error apply to a software statement code redemption (Section 7). The audience parameter (Section 5) names the authorization servers at which the issued statement will be presented, a property of the requested artifact rather than a request for access, and is not prohibited by this section.

Hybrid response types that combine software_statement_code with code, token, id_token, or any other response type are not defined. An authorization server MUST reject such a request with unsupported_response_type.

6. Authorization Response

After validating the request and performing any immediate interaction, the authorization server returns the software statement code response or an error. The authorization server MUST NOT place the software statement or approval-sensitive information in any authorization response.

A denial is never signaled in the authorization response. The authorization server returns a software statement code whether the issuance decision is complete, pending, or already a denial, and a decision to deny is delivered at redemption (Section 10.1). A client therefore does not implement a redirect-side access_denied handler for issuance outcomes.

6.1. Software Statement Code Response

The authorization server returns the following parameters to the client's redirection endpoint through the user agent, using the selected response mode, whether or not the issuance decision has already completed:

software_statement_code:

REQUIRED. A short-lived, single-use artifact redeemed at the token endpoint (Section 7). It MUST be bound to the client identifier, redirect URI, PKCE challenge, metadata snapshot, requested audience, and, when dpop_jkt was present, that JWK thumbprint. The value MUST contain at least 128 bits of entropy from a cryptographically secure random source, MUST be opaque to the client, MUST expire shortly after issuance, and MUST NOT be accepted more than once.

state:

REQUIRED. The exact value received in the authorization request.

iss:

REQUIRED. The authorization server issuer identification parameter defined by [RFC9207].

A software statement code is not an authorization code and MUST NOT be redeemable as one. Redemption requires the PKCE verifier and, for a public client, a DPoP proof with the dpop_jkt key.

The fragment response mode SHOULD NOT be used, because scripts at the redirection endpoint can access it. A client MAY request form_post [FORM-POST] to keep the code out of URLs, browser history, and Referer headers.

An OAuth library that recognizes only code needs a callback adapter for software_statement_code. The adapter applies the same state, iss, and PKCE handling.

For example, using the default query response mode (line breaks are for display purposes only):

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
  software_statement_code=V7e1gP8zT2mN4qR6sW9xY3aB5cD7fH0jK2pL4uQ6vX8&
  state=4L7xQ2mN9pR6sT1vW8yZ3aB5cD0fG2hJ&
  iss=https%3A%2F%2Fserver.example.com

Request validation errors, such as a prohibited parameter or an unsupported response type, follow Section 4.1.2.1 of [RFC6749]. An issuance denial is not a request validation error.

7. Software Statement Code Redemption

The client redeems a software statement code by sending an HTTP POST request to the token endpoint using the application/x-www-form-urlencoded format with:

grant_type:

REQUIRED. The value MUST be urn:ietf:params:oauth:grant-type:software-statement.

software_statement_code:

REQUIRED. The software statement code returned by the authorization endpoint.

redirect_uri:

REQUIRED. The same redirection URI used in the authorization request.

client_id:

REQUIRED. The same client identifier URL used in the authorization request.

code_verifier:

REQUIRED. The PKCE verifier corresponding to the code_challenge in the authorization request.

completion_mode:

REQUIRED when the authorization server advertises deferred_token_response_supported (Section 14); otherwise not used, and a synchronous issuer ignores it (Section 9). When present, the value MUST include deferred, per the deferral opt-in rule of Section 9.

The request MUST NOT contain audience, which was bound at the authorization endpoint; a request containing it is rejected with invalid_request. The client authenticates according to Section 4, and when dpop_jkt was included in the authorization request, the client MUST send a DPoP proof for the token endpoint using the same key.

The authorization server MUST validate the software statement code and all of its bindings before processing the request. An invalid, expired, previously used, or incorrectly bound code MUST result in an invalid_grant error; a PKCE or DPoP binding failure is handled according to [RFC7636] or [RFC9449], respectively.

A redemption attempt consumes the software statement code whenever the presented code value is valid, including when its PKCE, DPoP, or client-authentication bindings fail, so a live code cannot be ground down by repeated guessing; the trade, that an observer of the code value can burn it and force a restart, is accepted (Section 16.4). A previously consumed code presented again MUST be rejected, and the authorization server SHOULD revoke any deferral derived from it ([RFC9700]). For a valid, unconsumed code, the result depends on the issuance decision:

A synchronous issuer never reaches the pending branch, having decided before it returned the code (Section 9).

The following is a non-normative example of a redemption request from a confidential client at a deferred issuer (line breaks are for display purposes only):

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3A
  software-statement
  &software_statement_code=V7e1gP8zT2mN4qR6sW9xY3aB5cD7fH0jK2pL4uQ6vX8
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  &client_id=https%3A%2F%2Fclient.example.org%2Fmetadata.json
  &code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
  &completion_mode=deferred
  &client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3A
  client-assertion-type%3Ajwt-bearer
  &client_assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6ImNsaWVudC0xIn0...

8. Token Exchange Profile

A software statement request asks the authorization server to make a new issuance decision. A client that already holds a token carrying issuance authority MAY instead exchange that token for a statement using OAuth 2.0 Token Exchange [RFC8693], a pattern used by existing ecosystems ([UK-OPEN-BANKING], [AU-CDR]). Support is advertised through software_statement_subject_token_types_supported (Section 14).

The client sends a token exchange request as defined in Section 2.1 of [RFC8693] with:

grant_type:

REQUIRED. The value MUST be urn:ietf:params:oauth:grant-type:token-exchange.

requested_token_type:

REQUIRED. The value MUST be urn:ietf:params:oauth:token-type:software-statement.

subject_token and subject_token_type:

REQUIRED. The subject token is an initial access token: an authorization credential issued out of band by this authorization server that pre-authorizes software statement issuance, analogous to the initial access token of [RFC7591], presented with a subject_token_type of urn:ietf:params:oauth:token-type:access_token. The credential MUST be bound to the client_id of the request. This version defines no other subject token type; renewal from a previously issued software statement is a deferred capability (Appendix C.9).

client_id:

REQUIRED. The client identifier URL described in Section 4.

audience:

OPTIONAL. The requested audience described in Section 5. The same syntax, validation, and narrowing rules apply.

completion_mode:

REQUIRED when the authorization server advertises deferred_token_response_supported (Section 14); otherwise not used, and a synchronous issuer ignores it (Section 9). When present, the value MUST include deferred, per the deferral opt-in rule of Section 9.

The request MUST NOT contain actor_token or actor_token_type, nor the scope, resource, or authorization_details parameters prohibited by Section 5.1.

The client authenticates according to Section 4, whose sender-constraint rules apply to the exchange; the polling rules of Section 9 govern any resulting deferral.

The authorization server MUST validate the subject token before retrieving client-controlled metadata or enqueueing any processing. An invalid, expired, or revoked subject token, or one that does not authorize issuance for the presented client_id, MUST result in invalid_request, as Section 2.2.2 of [RFC8693] requires for a subject token that is invalid or unacceptable under policy. An unacceptable requested audience results in invalid_target [RFC8693].

An initial access token presented under this profile MUST be:

A reusable initial access token MUST be sender-constrained, for example bound to a client key through DPoP or mTLS; a bearer initial access token MUST be single-use. The credential SHOULD be integrity protected and kept confidential in transit and at rest, and MAY further restrict audiences or metadata. The authorization server MUST enforce every restriction the credential carries and MUST prevent replay beyond its permitted number of uses. A use is consumed when the authorization server commits to an outcome for the request, whether it issues a statement, creates a deferral, or denies issuance; concurrent presentations of a single-use credential MUST NOT both be committed. Once a deferral exists, the client recovers the outcome by polling with the deferral code rather than by presenting the credential again.

A DPoP proof on the exchange constrains any resulting deferral; it does not authenticate the presenter or protect the subject token (Section 3 of [RFC9449]). The initial access token therefore needs its own sender constraint or single-use restriction.

The exchange is evaluated against current metadata. The authorization server MUST obtain and validate the Client ID Metadata Document and MUST bind a fresh metadata snapshot (Section 4.1) and the requested audience before returning either the software statement or a deferral code. The statement's claims derive from that snapshot. An authorization server that recorded the metadata digest of a prior issuance for this client_id MAY compare it against the fresh snapshot and treat a change as an input to issuance policy.

Issuance policy determines whether an initial access token authorizes only the request or issuance itself. The result is:

9. Deferred Processing

An authorization server supports one of two conformance levels:

Against a deferred issuer, every deferral originates from a deferred token response of [DTR], issued for a software statement code redemption (Section 7) or a token exchange (Section 8), and the client polls the token endpoint using the polling grant defined by [DTR].

A client contacting a deferred issuer MUST include the completion_mode parameter of [DTR] with a value that includes deferred on the originating request, and MUST support the polling grant; the issuer MAY still complete synchronously. A deferred issuer MUST reject an originating request that does not carry that opt-in with invalid_request, because [DTR] treats an absent or non-deferred value as a requirement for synchronous handling, which an issuer whose decisions can outlive a request cannot guarantee. This deliberately raises the parameter from OPTIONAL in [DTR] to REQUIRED here. A synchronous issuer neither requires nor processes completion_mode.

This specification profiles polling delivery only: a client MUST NOT include the client_notification_token parameter of [DTR] on any request under this specification, a request containing it is rejected with invalid_request, and an authorization server MUST NOT deliver callback notifications for a deferral created under this specification, regardless of any deferred_client_notification_endpoint in the client's metadata. Polling over the authenticated token endpoint retrieves the statement without an outbound channel, so this version does not require an issuer to operate one; a future version can adopt the callback mechanism of [DTR] (Appendix C.9).

When an issuer defers a request, it MUST record the sender-constraint context established at origination and bind it to the deferral:

A method that does not bind a key freezes only the client identity and method. Every polling request MUST match the recorded context. The authorization server MUST NOT re-derive that context from the current metadata document. A client that loses the origination key cannot complete the deferral and instead makes a new request.

Approval of software statement issuance can take hours or days rather than the seconds typical of user authentication, for example when it involves reviewing the client's policy or compliance documentation. Issuers SHOULD set deferral code lifetimes that reflect their actual approval latency.

9.1. First Polling Request

The first polling request is an HTTP POST request to the token endpoint using the application/x-www-form-urlencoded format. It contains:

grant_type:

REQUIRED. The value MUST be urn:ietf:params:oauth:grant-type:deferred.

deferral_code:

REQUIRED. The deferral code returned in the deferred response.

The polling request carries no PKCE parameter: for a redirect-flow deferral, the verifier was consumed when the software statement code was redeemed (Section 7). The polling request MUST NOT contain a software_statement_code, code_verifier, redirect_uri, audience, subject_token, subject_token_type, or requested_token_type parameter; a polling request containing any of them is rejected with invalid_request.

On this and every subsequent polling request, the client MUST satisfy the sender-constraint context recorded for the deferral (Section 9): it uses the origination client authentication method and, when that method or a DPoP sender constraint binds a key, signs with the origination key. The authorization server verifies the request against the stored context, not against the current metadata document, and MUST reject a request that does not match, including a DPoP proof whose key differs from the recorded thumbprint.

9.2. Subsequent Polling Requests

If the request remains pending, the client continues polling according to [DTR] using only the polling grant's normal parameters and the sender constraint described in Section 9.1.

Pending, denied, expired, canceled, and polling-rate behavior follows [DTR]. A successful first or subsequent polling response is the software statement token response defined in Section 10.

Cancellation of a deferral follows the revocation mechanism of [DTR]: the client presents the deferral code to the authorization server's revocation endpoint [RFC7009] with a token_type_hint of urn:ietf:params:oauth:token-type:deferral-code. For a deferral created under this specification, the authorization server MUST require the deferral's sender constraint on the revocation request: client authentication where the deferral is bound to client authentication, or a DPoP proof with the origination-bound key otherwise. A revocation request that does not present the bound constraint MUST be treated as presenting an unrecognized token per [DTR].

10. Software Statement Token Response

A successful response has HTTP status code 200, a media type of application/json, and the following members:

access_token:

REQUIRED. The software statement issued by the authorization server. As in [RFC8693], the historically named access_token member carries the issued security token.

issued_token_type:

REQUIRED. The value MUST be urn:ietf:params:oauth:token-type:software-statement.

token_type:

REQUIRED. The value MUST be N_A, indicating that an OAuth access token type does not apply.

expires_in:

RECOMMENDED. The remaining lifetime of the software statement in seconds. If present, it MUST be consistent with the statement's exp claim.

The response MUST NOT contain refresh_token or scope. The authorization server MUST include Cache-Control: no-store; it SHOULD also include Pragma: no-cache.

DPoP under this specification binds requests and deferral state, not the issued artifact: the software statement is not an OAuth access token, and [DTR]'s requirement that a final access token inherit the originating DPoP binding does not apply because none is issued. The statement's replay and theft properties are those described in Section 16.7, including key binding through attested jwks or jwks_uri where a deployment wants proof of possession at registration, and, for runtime presentation, the sender constraint [PRESENTATION] mandates.

For example:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":
    "eyJ0eXAiOiJzb2Z0d2FyZS1zdGF0ZW1lbnQrand0...",
  "issued_token_type":
    "urn:ietf:params:oauth:token-type:software-statement",
  "token_type": "N_A",
  "expires_in": 3600
}

The client consumes the issued statement, the value of access_token, as described in Section 12: through an [RFC7591] registration request or by runtime presentation ([PRESENTATION]).

The access_token member is a security-token container ([RFC8693]), not an OAuth access token: the software statement is consumed only as a software statement (Section 12), MUST NOT be attached to a request as an Authorization: Bearer credential, and is not subject to refresh. Implementations that cache issued tokens by type SHOULD key this artifact on its issued_token_type so that generic access-token handling does not apply to it, and SHOULD treat it as a sensitive credential in logs.

A client obtains a replacement for an expiring or expired software statement by performing a new software statement request, or, if it holds an initial access token, through an exchange under Section 8. Whether replacement requires new approval is determined by issuer policy. This document defines how a client obtains a replacement; [PRESENTATION] defines how it delivers one to a trusting authorization server, and orders replacements by iat (Section 11).

10.1. Terminal Denial

When the authorization server decides not to issue the requested software statement, whether that decision is already complete when the originating request arrives or completes during deferred processing, it returns a token error response per Section 5.2 of [RFC6749] with the error code access_denied and HTTP status code 400, and MUST include the Cache-Control: no-store response header field. The same rule applies to both originating requests: a software statement code redemption (Section 7) and a token exchange (Section 8). A decision that completes as a denial during deferred processing is delivered in response to a polling request (Section 9).

The denial is terminal for the request. A deferral resolves to the denied state, in which subsequent polling requests return the same access_denied response for the remainder of the deferral code's lifetime, as [DTR] requires for a request that has resolved with an error. A denial does not preclude a later issuance request; whether to accept one is issuance policy.

11. Software Statement Format

The software statement is a compact JWT [RFC7519] protected by JWS [RFC7515]. Although [RFC7591] permits a MAC, a statement issued under this specification MUST use an asymmetric digital signature so trusting servers need not receive an issuer-held symmetric key. The issuer and trusting authorization server MUST follow [RFC8725] algorithm-verification guidance. The none algorithm and symmetric algorithms MUST NOT be used.

The JOSE header MUST include kid, identifying the signing key within the issuer's JWK Set, and MUST include typ with the value software-statement+jwt, applying Section 3.11 of [RFC8725]. This value names application/software-statement+jwt (Section 18.6) with the application/ prefix omitted, as described in Section 4.1.9 of [RFC7515]. Explicit typing prevents confusion with other JWTs from the same issuer.

Extensions can add claims; an incompatible revision would use a new type value. Supported algorithms appear in software_statement_signing_alg_values_supported (Section 14).

The JWT payload MUST contain the following claims in addition to the approved client metadata.

iss:

REQUIRED. The issuer identifier of the issuing authorization server, as defined by [RFC8414].

sub:

REQUIRED. The exact client identifier URL presented in the request that produced the statement.

aud:

REQUIRED. One or more audience identifiers for the authorization servers permitted to accept the statement. Each value MUST be an authorization server issuer identifier as defined by [RFC8414]. A trusting authorization server MUST reject the statement unless one of its locally configured audience identifiers exactly matches a value in this claim. When the request contained audience values, every value in this claim MUST have appeared among them.

iat:

REQUIRED. A NumericDate value representing the time at which the software statement was issued. Consumers order replacements by this value ([PRESENTATION]), so an issuer MUST NOT issue a statement for a given iss and sub pair with an iat earlier than one it has already issued for that pair, and SHOULD ensure the value is strictly increasing across its signing nodes. Back-dating a statement to allow for clock skew makes it unusable as a replacement.

exp:

REQUIRED. A NumericDate value representing the expiration time. A trusting authorization server MUST reject an expired statement.

jti:

REQUIRED. A unique identifier for the statement within the issuer's namespace.

cimd_digest:

REQUIRED in a CIMD-anchored statement; Section 11.1 defines the registration-only shape without it, and its presence or absence discriminates the two. [PRESENTATION] consumes these shapes as its CIMD profile and DCR profile respectively. The metadata digest (Section 4.1) of the Client ID Metadata Document from which the metadata snapshot was derived. This claim binds the statement to the exact document content evaluated during issuance and lets any party determine whether the client's currently published metadata still matches what was attested.

Each metadata claim MUST be client metadata registered in the IANA "OAuth Dynamic Client Registration Metadata" registry, or otherwise recognized by the authorization server, such as instance_issuers (Section 13.1). The following authorization-server-assigned, credential, and recursive metadata members are not eligible for attestation and MUST NOT appear in a software statement issued under this specification: client_id, client_secret, client_id_issued_at, client_secret_expires_at, registration_access_token, registration_client_uri, and software_statement. An authorization server MAY exclude additional metadata according to policy. The client_id member required in the Client ID Metadata Document by [CIMD] identifies the canonical document during issuance; the statement represents that identifier in sub and MUST NOT copy it as client metadata.

The issuer determines the audience and lifetime according to policy. Lifetime carries two consequences that pull in opposite directions: a short lifetime bounds exposure and keeps the review fresh, while at a trusting authorization server implementing the registration-validity model of [PRESENTATION] the same value is the registration's validity and therefore the renewal cadence the client and issuer must sustain. An issuer SHOULD choose a lifetime it can renew reliably for the deployments it serves, and SHOULD stagger expiries across the statements it issues, or renew ahead of the boundary, so that a fleet issued together does not lapse together. A client can request an audience using the audience parameter, but the issuer MAY narrow that request and MUST NOT widen it. If the parameter is omitted, the issuer selects an audience entirely according to policy. Every client metadata claim MUST correspond to a member present in the metadata snapshot, carrying either that member's value or, for a set-valued member such as redirect_uris, grant_types, or scope, a subset of it. The issuer MAY omit members but MUST NOT introduce a member absent from the snapshot, alter a value that is not set-valued, or otherwise contradict or widen the snapshot.

The sub claim is the client identifier URL, not the local client_id assigned through [RFC7591] registration. A trusting authorization server MAY use sub to correlate registrations and apply per-client policy (Section 13).

11.1. Statements for Non-CIMD Clients

The format above anchors its subject in a Client ID Metadata Document. Clients without one, registered statically at an authorization server or through plain [RFC7591] registration, are also subjects of portable review: an enterprise allowlist keys on identifiers its providers already know, not on hosted metadata. A statement for such a client conforms to this section's shape, discriminated from the CIMD-anchored shape by the absence of cimd_digest, and consumed as the DCR profile of [PRESENTATION].

The signing, header, and typing rules are unchanged, as are iss, aud, iat, exp, and jti. The differences:

sub:

REQUIRED. The client software identifier agreed between issuer and audience. For software registered through [RFC7591], the subject is the software_id, the identifier that holds across registrations and versions. For import at an authorization server where no vendor identifier exists, sub is a client identifier already registered at the server named in aud. It is never a Client ID Metadata Document URL, and no retrieval is implied.

cimd_digest:

MUST be absent. There is no canonical document to bind; the statement's own claims carry the entire reviewed content.

software_version:

OPTIONAL. When attested, the [RFC7591] software_version the review covered; a new version of the software requires re-issuance, and cannot be introduced by renewing an existing registration ([PRESENTATION]). A version string is a vendor-asserted label, not a byte binding, so this binds the review to what the vendor calls that version, a weaker guarantee than cimd_digest gives the CIMD-anchored shape.

Attested metadata is inline only: the snapshot-subset rule above does not apply, and the issuer attests exactly the members its review covered, which take [RFC7591] precedence at registration as usual. Issuer scoping uses an enumerated identifier set or a tenant rather than a URL namespace (Section 15).

The statement binds to a registration request through these identifiers. A trusting authorization server MUST reject a registration request whose software_id differs from the statement's sub and, where the statement attests software_version, MUST reject a request whose software_version differs from the attested value, in both cases with invalid_software_statement: the statement does not describe the registering software. A request that omits either member inherits the attested value through [RFC7591] precedence. A replacement delivered outside a registration request carries no such member, so [PRESENTATION] compares the attested software_version against the value recorded for the registration; a replacement attesting a different version is a version change requiring a fresh review, not a renewal.

A statement in this shape is consumable through registration (Section 12) or as direct policy import at an authorization server that already knows the identifier; it cannot be presented at runtime, because the machinery of [PRESENTATION] assumes the document the CIMD-anchored subject names. [PRESENTATION] profiles its consumption as the DCR profile, including the registration-validity and revalidation model that binds a registration's lifetime to the statement's expiry; that profile covers the software_id subject, while a statement whose sub is an already-registered client identifier is imported by the authorization server administratively and is outside the profiles that document defines. The issuance flows of this document identify clients by their metadata document and therefore produce only CIMD-anchored statements; a statement in this shape is issued by an out-of-band process, such as an enterprise review console or an ecosystem directory, and consumed under this contract.

With a stable URL across releases, sub correlates releases and cimd_digest distinguishes reviewed content. With distinct release URLs, sub identifies a release and an attested [RFC7591] software_id can correlate them. This specification does not derive either identifier from the other.

The following is a non-normative example of the JOSE header and JWT payload of a software statement:

{
  "typ": "software-statement+jwt",
  "alg": "ES256",
  "kid": "issuer-key-1"
}
.
{
  "iss": "https://server.example.com",
  "sub": "https://client.example.org/metadata.json",
  "aud": ["https://server.example.net"],
  "iat": 1767225600,
  "exp": 1767229200,
  "jti": "0b1f8a3e-6d2c-4c58-9a0f-6b2f6c3d9e21",
  "cimd_digest": "3W6cWfLXi0mZbUIhk8N4Zt2v9Qq7oT1xJdKe5RgYs0A",
  "client_name": "Example App",
  "redirect_uris": ["https://client.example.org/cb"],
  "grant_types": ["authorization_code"],
  "scope": "read",
  "token_endpoint_auth_method": "private_key_jwt",
  "jwks_uri": "https://client.example.org/jwks.json"
}

Before accepting the statement, a trusting authorization server MUST:

  • verify that the typ header carries the value software-statement+jwt;

  • verify the signature under a key trusted for the exact iss value;

  • validate the presence and type of every required claim, and validate iss, aud, iat, and exp, rejecting an iat unreasonably far in the future according to its clock-skew policy;

  • verify that sub matches the statement's shape: a client identifier URL conforming to [CIMD] when cimd_digest is present, an agreed software identifier otherwise (Section 11.1);

  • verify that sub falls within the identifier scope for which it accepts the issuer, URL namespaces for the CIMD-anchored shape, an enumerated identifier set or tenant otherwise (Section 15);

  • reject every metadata claim prohibited by this section; and

  • apply the JWT validation guidance in [RFC8725].

An issuer URL or JWK Set does not establish trust. A trusting authorization server accepts only configured issuers (Section 15) and obtains their keys from authorization server metadata [RFC8414], not from the statement.

A trusting authorization server MAY retrieve current client metadata and compare its digest with cimd_digest; if it does so, it MUST also verify that the document's client_id exactly equals sub, as required by [CIMD]. A mismatch indicates post-issuance change and is a policy input, not a validation failure. Because the digest covers the whole document, a mismatch signals only that something changed; a trusting authorization server SHOULD distinguish a change confined to metadata the statement did not attest, which leaves the attested claims intact, from a change to an attested member, which means the statement no longer describes the published document. The server then consumes the statement as described in Section 12.

When the statement is consumed via registration (Section 12), rejections are reported using the registration error codes of Section 3.2.2 of [RFC7591]. A statement that cannot be validated, because it is malformed, expired, or fails signature or claim validation, results in invalid_software_statement. A statement that validates but is not acceptable here, because its issuer is not configured, its aud does not include this server, its sub falls outside the issuer's configured namespaces, or its lifetime exceeds what the server honors, results in unapproved_software_statement. The distinction tells a client whether to obtain a corrected statement or to approach a different issuer. A runtime presentation or a replacement delivery reports these conditions through the coarser error surface [PRESENTATION] defines, where the distinction may be preserved in error_description to an authenticated client but is not carried by the error code.

A trusting authorization server MUST reject a statement whose lifetime exceeds the maximum it records for the issuer (Section 15). An attested claim outside the set for which the trusting authorization server treats the issuer as authoritative MUST NOT take the [RFC7591] precedence of an attested value; the server either ignores the claim or treats it as client-supplied registration metadata, according to policy.

12. Consuming a Software Statement

A validated software statement (Section 11) is consumed in one of three ways, which share the artifact and its validation: registration, runtime presentation, and delivery of a replacement statement to a client the server has already established. An authorization server can support any of them.

In registration, the client supplies the statement as the software_statement member of an [RFC7591] dynamic client registration request. The authorization server validates it (Section 11), registers a client, assigns a local client_id, and applies its registration policy; rejections use the [RFC7591] error codes given in Section 11. This path consumes the artifact through the interface [RFC7591] registration endpoints have offered since 2015; what is new for the consumer is the validation this document requires (Section 11). Both statement shapes are consumable here, CIMD-anchored and non-CIMD; the latter binds to the registration request through its identifiers (Section 11.1).

In runtime presentation, defined by the companion [PRESENTATION], the client presents the statement in an authorization or token request, sender-constrained by a proof that chains to the statement; the authorization server applies the attested metadata to that request and creates no persistent registration. That path consumes any statement conforming to this document's CIMD-anchored format (Section 11); obtaining one through the issuance flows defined here is one way, not a requirement of presentation. Where the client is already registered at that server, [PRESENTATION] treats a statement-carrying request as a delivery rather than a presentation: it renews the registration's validity and the registration record continues to govern the request.

13. Multi-Instance Client Software

A software statement attests client software, identified by sub; it does not attest or identify the runtime instances of that software. This specification defines no instance identifier, and instances do not obtain per-instance statements. This section concerns the registration path (Section 12); under runtime presentation ([PRESENTATION]) the presenter proves a key that chains to the statement, an instance is identified only where that key material is per-instance, and no persistent registration is created.

A single unexpired statement is therefore intended to be presented more than once: at each trusting authorization server in its audience and, where local policy permits, in more than one registration at the same authorization server, for example one registration per deployment or tenant. Where those servers implement the registration-validity model of [PRESENTATION], every registration derived from one statement inherits its exp and lapses at the same moment, which is what the staggering guidance of Section 11 addresses. A trusting authorization server SHOULD use the statement's sub and jti to inventory the registrations derived from a statement and to enforce any local bound on their number.

A trusting authorization server SHOULD bound the number of registrations derived from one statement at one local audience. The safe default is one registration per (iss, jti, local audience). On repeated presentation, local policy can reject the request, treat it as idempotent, or create another registration; [RFC7591] defines no duplicate-registration protocol.

A server that treats a repeat as idempotent MUST NOT disclose the credentials or registration access token of the prior registration to a later presenter unless it independently authorizes that presenter.

Deployments whose client software runs many concurrent instances SHOULD register the logical client once per authorization server and differentiate instances at the token endpoint, for example with [CLIENT-INSTANCE] or attestation-based client authentication [ABCA], rather than minting a registration per instance. The statement's key material determines which registration models it can support:

13.1. Attesting Instance Issuers

[CLIENT-INSTANCE] defines the instance_issuers client metadata parameter, through which a client delegates attestation of its runtime instances to named authorities. For the purposes of this specification, instance_issuers is client metadata like any other: it can appear in the canonical Client ID Metadata Document and be carried as an attested claim in the software statement.

A statement containing instance_issuers attests the instance-attestation delegation instead of presenting a self-asserted list. This avoids dependence on document availability or locally configured lists. An issuing authorization server SHOULD include instance_issuers in a statement only when it recognizes the member and its approval process covered the delegation the member expresses.

For example, the following claims fragment attests one instance issuer for the client:

"instance_issuers": [
  {
    "issuer": "https://workload.client.example.org",
    "jwks_uri": "https://workload.client.example.org/jwks.json"
  }
]

14. Authorization Server Metadata

The issuing authorization server is a role, not necessarily a general-purpose OAuth deployment. An issuer offering only token exchange can consist of a token endpoint, an authorization server metadata document, and signing keys. It can operate solely as an attestation service, without an authorization endpoint, access tokens, or protected resources.

An authorization server that issues software statements under this specification advertises true for client_id_metadata_document_supported, as defined by [CIMD], and publishes software_statement_signing_alg_values_supported below.

An issuer that may defer a request advertises true for deferred_token_response_supported, as defined by [DTR] (Section 9), and, because deferrals are cancellable, lists urn:ietf:params:oauth:token-type:deferral-code in revocation_endpoint_token_type_values_supported as [DTR] requires. A synchronous issuer, which answers every request with a statement or a terminal denial, advertises neither and need not implement [DTR].

An authorization server supporting the redirect flow advertises:

An authorization server supporting the token exchange profile (Section 8) advertises urn:ietf:params:oauth:grant-type:token-exchange in grant_types_supported and publishes software_statement_subject_token_types_supported below; general token exchange support does not by itself imply support for this profile. An implementation supporting only that profile advertises neither the software statement grant nor the software_statement_code response type.

A client that requires deferral MUST NOT send a request to an authorization server that does not advertise deferred_token_response_supported; a synchronous issuer answers such a request with a statement or a terminal denial rather than a deferral.

This specification defines the following additional authorization server metadata members:

software_statement_signing_alg_values_supported:

REQUIRED for an authorization server that issues software statements under this specification. A JSON array containing the asymmetric JWS alg values that the authorization server can use to sign software statements. The array MUST NOT contain none or a symmetric algorithm. This member describes the issuing role; an authorization server that only accepts software statements does not publish it.

software_statement_audiences_supported:

OPTIONAL. A JSON array containing authorization server issuer identifiers that the issuer is prepared to place in a software statement's aud claim. Omission means that the complete set is not publicly enumerable; it does not mean that no audience is supported. Publication does not guarantee that every client is eligible for every listed audience.

software_statement_subject_token_types_supported:

REQUIRED for an authorization server that supports the token exchange profile (Section 8), and absent otherwise. A JSON array of the subject_token_type values the authorization server accepts when requested_token_type is urn:ietf:params:oauth:token-type:software-statement. Publication of this member is the discovery signal for the profile.

15. Issuer Trust Establishment

A trusting authorization server accepts statements only from configured issuers. Trust is established out of band, for example through a marketplace publisher program or shared enterprise operation. This specification defines no in-band issuer discovery or trust decision.

Configuring trust in an issuer is a one-time act that covers every client that issuer attests, so a trusting authorization server maintains a small, stable set of trusted issuers rather than per-client state. For each, it records at least:

These inputs, not the signature alone, define acceptance. Because the issuer is an authorization server role, key retrieval reuses [RFC8414] discovery (Section 14).

A trusting authorization server MUST derive trust from this local configuration and MUST NOT derive it from an iss, jku, x5u, or other key-location value carried in a presented statement. Having established trust, it validates each statement as described in Section 11.

Issuer trust SHOULD be scoped as well as explicit. An issuer accepted for all values of sub can, if compromised or over-broad, mint acceptable statements about any client software; trust configuration SHOULD therefore constrain each issuer to the client identifier namespaces it is expected to attest, for example URLs under the domains of the software publishers it serves, and a statement whose sub falls outside that scope MUST be rejected even when its signature verifies (Section 11). For the non-CIMD shape (Section 11.1) the scope is an enumerated identifier set or a tenant rather than a URL namespace; the rejection rule is the same.

Pairwise configuration bounds a statement's reach to the issuers a trusting authorization server has configured, which is why a statement's practical audience is an ecosystem or administrative domain rather than the open web. The OAuth Identity Assertion Trust Framework [TRUST-FRAMEWORK] generalizes the model: a trusting authorization server publishes the conditions an issuer must satisfy and evaluates published evidence, such as authorization by the owner of a client identifier's namespace, when a statement is presented, replacing enumeration of trusted issuers with open-world policy. OpenID Federation [OPENID-FED] provides an alternative through trust chains. Both are out of scope here.

16. Security Considerations

16.1. Client Establishment Is Not an Access Grant

A software statement attests client metadata; it grants no resource access or consent on behalf of the software's users. Each user still authorizes access through the established client.

Authorization servers MUST enforce the prohibited-parameter and response-type rules in Section 5.1. The successful response uses access_token only as the generic security-token container defined by [RFC8693]; the contained software statement MUST NOT be accepted as an access token at a protected resource.

When an approval interface is shown, it MUST clearly describe that the decision concerns attestation to client metadata. It MUST NOT imply that the approver is granting the client access to resources.

An erroneous approval affects every authorization server in the statement's audience until expiry. The approval interface therefore MUST present:

  • the client identifier URL;

  • the metadata to be attested; and

  • the audience the issuer intends to place in the statement.

It SHOULD present the intended lifetime, and SHOULD make narrowing visible when the client requested a different or broader audience. Attesting instance_issuers (Section 13.1) endorses the listed authorities to attest runtime instances and deserves particular scrutiny.

16.2. What Issuance Attests

A software statement is an attestation about software: a signed, attributable claim by a named issuer, bounded by that issuer's process rather than proof that its contents are true. [PRESENTATION] sets it beside the client attestation and instance assertion that attest a presenter, which differ in subject, authority, lifetime, and effect and compose with it rather than replace it.

A software statement means one thing: the issuer evaluated the exact document content captured in the metadata snapshot (Section 4.1), under its issuance policy, at the time recorded in iat, and decided to attest the contained metadata for the named audience.

The client authors the metadata document, so issuance does not make every value an independently verified fact. It records an accountable evaluation of a deterministic, digest-bound input (Section 4.1). An issuer SHOULD corroborate security-relevant metadata through evidence beyond the document itself. Verification depth is part of the trust relationship.

A trusting authorization server can conclude only what the issuer decided; local client-establishment policy determines what that decision is worth.

16.3. Client Metadata Retrieval

Fetching a Client ID Metadata Document and resources referenced by it exposes the authorization server to server-side request forgery, resource exhaustion, malicious content, and client impersonation risks. The validation, address filtering, response-size limits, redirect handling, caching, logo handling, and domain-trust considerations of [CIMD] apply.

The metadata snapshot requirements in Section 4.1 prevent a time-of-check/time-of-use change from silently altering the attested metadata after approval; members the statement does not attest remain live, and runtime presentation ([PRESENTATION]) sources them from the current document at each presentation. Authorization servers SHOULD record the metadata digest (Section 4.1) and retain the exact retrieved octets of the approved document for audit purposes; a re-serialized copy cannot reproduce the digest.

16.4. Authorization Response Security

The software statement is a signed credential and can contain sensitive deployment information. It MUST NOT be returned through the authorization endpoint. The software statement code response applies exact redirect URI matching, PKCE with S256, and the other applicable authorization response protections in [RFC9700].

Before redeeming a software statement code, the client MUST verify state and MUST validate the authorization response iss parameter according to [RFC9207]. PKCE with S256 provides the cross-site request forgery protection described in [RFC9700]; state also correlates concurrent requests with their responses.

A public client presents no client authentication, so its association with the software depends on delivery to a metadata-listed redirection endpoint. Only HTTPS demonstrates control of the publisher's origin. Another application can claim a private-use or loopback endpoint ([RFC8252]); PKCE and DPoP bind the code to the initiator but cannot stop an attacker from initiating under another party's client_id.

A public client therefore MUST use an HTTPS redirection URI (Section 5). A native public client can host such an endpoint or use the redirect-free token exchange profile (Section 8).

A confidential client's authentication protects redemption, so it MAY use a loopback or private-use redirection URI. An authorization server SHOULD additionally relate the redirection URI's origin to the client identifier URL or the metadata document's client_uri according to policy. Endpoint or key control informs issuance policy but does not determine issuance.

A software statement code in a URL is visible to browser history, referrer fields, logs, and other observers. It is short lived, single use, and unredeemable without the PKCE verifier and, for a public client, the dpop_jkt key.

Deferral codes travel only over a direct TLS connection and are protected by sender-constrained polling and cancellation (Section 9). Deployments sensitive to URL disclosure can use form_post [FORM-POST]; the fragment response mode SHOULD NOT be used.

16.5. Deferral Sender Constraint

Every deferral is created by a token request, and every poll is bound to the client authentication or DPoP key fixed at origination (Section 9), so a public redirect-flow client's dpop_jkt carries sender constraint continuously from the authorization response through polling. All additional sender-constraint, polling-rate, replay, cancellation, and logging requirements of [DTR] apply.

16.6. Token Exchange Considerations

A token exchange reaches the token endpoint without prior user-agent interaction. Validating the subject token before metadata retrieval or enqueueing (Section 8) limits resource consumption by unauthorized requesters. Authorization servers SHOULD still rate-limit these exchanges, cache retrieval results and failures, and bound pending deferrals per client identifier and requester. Client authentication remains mandatory when established by the Client ID Metadata Document. The redirect flow likewise reaches the approval queue before any client-authenticated step; the same rate limits and pending-approval bounds SHOULD apply per client identifier there.

A subject token is an authorization credential, not a client identifier or substitute for client authentication when the Client ID Metadata Document establishes a method. Because it appears in a form body, any component recording request bodies can expose it. Authorization servers MUST exclude subject tokens from logs, traces, error messages, and audit records; clients and authorization servers MUST protect the credential as a bearer credential unless its format provides proof of possession. The binding, lifetime, entropy, and replay requirements of Section 8 limit disclosure impact.

No response parameter transits a browser, but there is also no in-band evidence of user participation. An authorization server MUST NOT treat a token exchange as implying prior user consent and MUST apply the same issuance and approval policy as for the redirect flow.

16.7. Statement Validation and Replay

A software statement is reusable (Section 13) and, until expiry, so is a stolen copy at every registration endpoint in its audience. Issuers SHOULD use the narrowest practical audience and lifetime, and the registration bounds of Section 13 limit what a stolen statement can create. This replay exposure is specific to the registration path; [PRESENTATION] requires a runtime presentation to prove a key that chains to the statement, which makes a stolen statement inert there to every party outside the issuer's review.

When registrations derived from a statement are intended to share a client key, and the canonical metadata provides jwks or jwks_uri, the issuer SHOULD include that member in the attested metadata. A trusting authorization server can then require proof of the corresponding private key during or after registration, making a stolen statement unusable without that key. Attesting jwks_uri attests the location, not its contents: a compromised key host can add keys that satisfy such proofs with no digest change, so where that exposure matters, attest jwks inline and accept digest-visible rotation. When each registration is expected to supply a distinct instance key, the issuer MUST omit jwks and jwks_uri so that plain registration metadata can carry that key without conflicting with [RFC7591] precedence. Omitting key material also spends the runtime-presentation option: such a statement is presentable under [PRESENTATION] only through an attested instance_issuers delegation or scoped attester trust, so an issuer anticipating runtime presentation SHOULD attest instance_issuers in this model. Attesting key material is equally consequential in the other direction: under [PRESENTATION] it leaves the directly attested key as the only accepted proof at every server in the audience, and a server that does not treat the issuer as authoritative for that member rejects the presentation rather than accepting an endorsement. Before attesting jwks or jwks_uri in a statement intended for runtime presentation, an issuer SHOULD confirm that every audience member treats it as authoritative for that member.

A statement authorizes metadata, not its presenter. If it omits attested key material for per-instance keys (Section 13), any holder can register its own key. A trusting authorization server SHOULD require independent proof that the presenter is an authorized instance of the software before accepting such a registration, such as [ABCA], an attested instance_issuers chain (Section 13.1), or a registration credential the trusting server issued. Without such proof, the one-registration-per-(iss, jti, local audience) default bounds exposure.

Renewal in this version does not accept a prior software statement as a subject token; a client renews by presenting an initial access token to the token exchange profile (Section 8) or by making a new software statement request. A stolen statement therefore cannot be exchanged for a fresh one that outlives it. The consumption side carries a different exposure: delivering a replacement to an existing registration proves that registration's own credential and the currency of any statement for the software, not that the deliverer is the reviewed software, so a stolen client credential can sustain a registration indefinitely. [PRESENTATION] states that limit and the credential-rotation and re-registration practices that answer it. Statement-as-subject renewal, and the holder binding against current metadata it requires, is deferred to a future version (Appendix C.9).

This specification does not define online revocation, and defines no status claim for it. Short lifetimes bound exposure; the Australian Consumer Data Right Register uses ten minutes ([AU-CDR]). Scoped trust supports emergency removal of a compromised issuer or namespace (Section 15). An extension could add acceptance-time status, for example a claim referencing a Token Status List [STATUS-LIST], along with the processing rules a trusting authorization server would apply (Appendix C.9).

At a server that does not implement the registration-validity model of [PRESENTATION], revocation does not undo registrations already derived from a statement, and responding to malicious software after registration is client lifecycle management at that server. Where that model is in force, a registration expires at the recorded exp unless a replacement renews it, so ceasing renewal retires the registration without per-server action.

The explicit, scoped issuer trust configuration that acceptance depends on, and the requirement never to derive trust from key-location values in the statement itself, are specified in Section 15.

16.8. Registration Fraud and Impersonation

Open registration permits client_name, logo_uri, and client_uri values that imitate trusted software on consent screens. Requiring a statement replaces self-asserted branding with issuer-reviewed values. Servers that render registration-supplied values on consent screens SHOULD prefer attested values and SHOULD apply heightened scrutiny to unattested registrations that claim user-visible branding.

Statement-gated registration also makes each rotated identity require another issuer decision, rather than letting a discarded client return at no cost; sub and jti tracking bounds registrations (Section 13). Neither control makes metadata true: a client that misleads review can obtain a genuine statement for fraudulent metadata, so issuer verification depth remains decisive (Section 16.2).

16.9. Signing Keys and Algorithms

Compromise of a software-statement signing key enables an attacker to mint statements for every audience that trusts that key. Issuers MUST protect signing keys according to the scope of their trust relationships and SHOULD support controlled key rotation. Trusting authorization servers MUST restrict algorithms to those allowed for the issuer and MUST follow [RFC8725] when selecting keys and validating JWTs. Issuers SHOULD prefer signature algorithms with modern security properties, such as PS256, ES256, or EdDSA, over RSASSA-PKCS1-v1_5 (RS256); ecosystem profiles that consume software statements commonly restrict signing to such algorithms.

16.10. Approver Identity and Audit

The software statement attests to metadata; it does not identify the human or system that approved issuance. Deployments that require approver attribution MUST retain it in an authorization server audit record or define an explicit statement claim and its privacy semantics. They MUST NOT infer approver identity from the signature alone.

Approval authority is a policy decision with audience-wide effect: an approved statement is accepted at every authorization server in its audience, not only within the approver's own scope. The policy governing who may approve issuance MUST be at least as restrictive as the policy governing manual client establishment at the issuing authorization server, and approval by a party authorized only for a personal or organizational scope MUST NOT produce a statement whose audience exceeds that scope.

An audit record SHOULD bind each decision, whether approval or denial, to the metadata digest (Section 4.1) of the document the deciding party evaluated, the policy under which the decision was made, the identity of that party, and the time of decision. A recorded denial carrying its grounds has the same audit value as a recorded approval. Portable, independently verifiable decision records are out of scope for this specification.

17. Privacy Considerations

The authorization server learns the client identifier URL, the canonical metadata document, and information about the party interacting with the authorization endpoint. It SHOULD collect and retain only the information required for issuance, security monitoring, and audit obligations.

A software statement distributes attested client metadata to every authorization server at which the client presents it. Issuers SHOULD omit metadata that is not required by the intended audience and SHOULD choose the narrowest practical audience. Clients SHOULD NOT present statements outside their intended deployment context. Requested audience values reveal the authorization servers with which the client plans to establish relationships. A redirect-flow client SHOULD use Pushed Authorization Requests [RFC9126] when that relationship is sensitive. Authorization servers SHOULD avoid logging issued statements.

Approval records can link a person to a client and deployment. Such records SHOULD be access-controlled and retained only as long as required.

18. IANA Considerations

18.1. OAuth Authorization Endpoint Response Types Registry

This specification requests registration of the following value in the IANA "OAuth Authorization Endpoint Response Types" registry established by [RFC6749]:

Response Type Name:

software_statement_code

Change Controller:

IESG

Specification Document(s):

This specification, Section 5 and Section 6

18.2. OAuth URI Registry

This specification requests registration of the following values in the IANA "OAuth URI" registry:

URN:

urn:ietf:params:oauth:grant-type:software-statement

Common Name:

OAuth Software Statement Grant Type

Change Controller:

IESG

Specification Document(s):

This specification, Section 7

URN:

urn:ietf:params:oauth:token-type:software-statement

Common Name:

OAuth Software Statement Token Type

Change Controller:

IESG

Specification Document(s):

This specification, Section 10 and Section 8

18.3. OAuth Parameters Registry

This specification requests that IANA add this specification, Section 5 and Section 8, as an additional reference for the existing audience parameter registered by [RFC8693] and extend its usage location to include authorization requests. The parameter name and change controller are unchanged.

This specification also requests registration of the following value in the IANA "OAuth Parameters" registry established by [RFC6749]:

Parameter Name:

software_statement_code

Parameter Usage Location:

authorization response, token request

Change Controller:

IESG

Specification Document(s):

This specification, Section 6.1 and Section 7

18.4. OAuth Extensions Error Registry

This specification requests registration of the following error usage in the IANA "OAuth Extensions Error Registry" established by [RFC6749]:

Error name:

access_denied

Error usage location:

token error response

Related protocol extension:

The software statement grant (Section 7) and token exchange profile (Section 8) of this specification

Change controller:

IESG

Specification document(s):

This specification, Section 10.1

It further requests registration of the following error usage:

Error name:

invalid_target

Error usage location:

authorization error response, token error response

Related protocol extension:

The software_statement_code response type and the audience parameter usage of this specification

Change controller:

IESG

Specification document(s):

This specification, Section 5 and Section 8

18.5. OAuth Authorization Server Metadata Registry

This specification requests registration of the following values in the IANA "OAuth Authorization Server Metadata" registry established by [RFC8414]:

Metadata Name:

software_statement_signing_alg_values_supported

Metadata Description:

JSON array containing the asymmetric JWS algorithms supported by the authorization server for signing software statements.

Change Controller:

IESG

Specification Document(s):

This specification, Section 14

Metadata Name:

software_statement_audiences_supported

Metadata Description:

JSON array containing authorization server issuer identifiers that the issuer is prepared to place in software statement audience claims.

Change Controller:

IESG

Specification Document(s):

This specification, Section 14

Metadata Name:

software_statement_subject_token_types_supported

Metadata Description:

JSON array of subject token type values accepted for exchanging into software statements; signals support for the token exchange profile.

Change Controller:

IESG

Specification Document(s):

This specification, Section 14 and Section 8

18.6. Media Type Registration

This specification requests registration of the application/software-statement+jwt media type in the IANA "Media Types" registry [RFC6838].

Type name:

application

Subtype name:

software-statement+jwt

Required parameters:

n/a

Optional parameters:

n/a

Encoding considerations:

8bit. A software statement is a JWT; JWT values are encoded as a series of base64url-encoded values separated by period ('.') characters, as registered for application/jwt in Section 10.3.1 of [RFC7519].

Security considerations:

See Section 16 of this specification and Section 11 of [RFC7519].

Interoperability considerations:

n/a

Published specification:

This specification

Applications that use this media type:

Authorization servers and clients that issue, request, or accept OAuth 2.0 software statements

Fragment identifier considerations:

n/a

Additional information:

File extension(s): n/a. Macintosh file type code(s): n/a.

Person & email address to contact for further information:

Karl McGuinness, public@karlmcguinness.com

Intended usage:

COMMON

Restrictions on usage:

none

Author:

Karl McGuinness, public@karlmcguinness.com

Change controller:

IETF

18.7. JSON Web Token Claims Registry

This specification requests registration of the following value in the IANA "JSON Web Token Claims" registry established by [RFC7519]:

Claim Name:

cimd_digest

Claim Description:

Unpadded base64url-encoded SHA-256 digest of the retrieved octets of the Client ID Metadata Document evaluated during software statement issuance

Change Controller:

IESG

Specification Document(s):

This specification, Section 11

19. References

19.1. Normative References

[CIMD]
"OAuth Client ID Metadata Document", n.d., <https://datatracker.ietf.org/doc/draft-ietf-oauth-client-id-metadata-document>.
[CLIENT-INSTANCE]
"OAuth 2.0 Client Instance Assertion", n.d., <https://datatracker.ietf.org/doc/draft-mcguinness-oauth-client-instance-assertion>.
[DTR]
"Deferred Token Response", n.d., <https://datatracker.ietf.org/doc/draft-gerber-oauth-deferred-token-response>.
[FORM-POST]
"OAuth 2.0 Form Post Response Mode", n.d., <https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html>.
[OAUTH-MRT]
"OAuth 2.0 Multiple Response Type Encoding Practices", n.d., <https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC6234]
Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, , <https://www.rfc-editor.org/rfc/rfc6234>.
[RFC6749]
Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, , <https://www.rfc-editor.org/rfc/rfc6749>.
[RFC6838]
Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, , <https://www.rfc-editor.org/rfc/rfc6838>.
[RFC7009]
Lodderstedt, T., Ed., Dronia, S., and M. Scurtescu, "OAuth 2.0 Token Revocation", RFC 7009, DOI 10.17487/RFC7009, , <https://www.rfc-editor.org/rfc/rfc7009>.
[RFC7515]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, , <https://www.rfc-editor.org/rfc/rfc7515>.
[RFC7519]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, , <https://www.rfc-editor.org/rfc/rfc7519>.
[RFC7591]
Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol", RFC 7591, DOI 10.17487/RFC7591, , <https://www.rfc-editor.org/rfc/rfc7591>.
[RFC7636]
Sakimura, N., Ed., Bradley, J., and N. Agarwal, "Proof Key for Code Exchange by OAuth Public Clients", RFC 7636, DOI 10.17487/RFC7636, , <https://www.rfc-editor.org/rfc/rfc7636>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8414]
Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 Authorization Server Metadata", RFC 8414, DOI 10.17487/RFC8414, , <https://www.rfc-editor.org/rfc/rfc8414>.
[RFC8693]
Jones, M., Nadalin, A., Campbell, B., Ed., Bradley, J., and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693, DOI 10.17487/RFC8693, , <https://www.rfc-editor.org/rfc/rfc8693>.
[RFC8707]
Campbell, B., Bradley, J., and H. Tschofenig, "Resource Indicators for OAuth 2.0", RFC 8707, DOI 10.17487/RFC8707, , <https://www.rfc-editor.org/rfc/rfc8707>.
[RFC8725]
Sheffer, Y., Hardt, D., and M. Jones, "JSON Web Token Best Current Practices", BCP 225, RFC 8725, DOI 10.17487/RFC8725, , <https://www.rfc-editor.org/rfc/rfc8725>.
[RFC9126]
Lodderstedt, T., Campbell, B., Sakimura, N., Tonge, D., and F. Skokan, "OAuth 2.0 Pushed Authorization Requests", RFC 9126, DOI 10.17487/RFC9126, , <https://www.rfc-editor.org/rfc/rfc9126>.
[RFC9207]
Meyer zu Selhausen, K. and D. Fett, "OAuth 2.0 Authorization Server Issuer Identification", RFC 9207, DOI 10.17487/RFC9207, , <https://www.rfc-editor.org/rfc/rfc9207>.
[RFC9396]
Lodderstedt, T., Richer, J., and B. Campbell, "OAuth 2.0 Rich Authorization Requests", RFC 9396, DOI 10.17487/RFC9396, , <https://www.rfc-editor.org/rfc/rfc9396>.
[RFC9449]
Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449, , <https://www.rfc-editor.org/rfc/rfc9449>.
[RFC9700]
Lodderstedt, T., Bradley, J., Labunets, A., and D. Fett, "Best Current Practice for OAuth 2.0 Security", BCP 240, RFC 9700, DOI 10.17487/RFC9700, , <https://www.rfc-editor.org/rfc/rfc9700>.

19.2. Informative References

[ABCA]
"OAuth 2.0 Attestation-Based Client Authentication", n.d., <https://datatracker.ietf.org/doc/draft-ietf-oauth-attestation-based-client-auth>.
[APPROVAL-DCR]
"OAuth 2.0 Approval-Based Dynamic Client Registration", n.d., <https://datatracker.ietf.org/doc/draft-dellaert-oauth-approval-based-dcr>.
[AU-CDR]
"Consumer Data Standards (Australia)", n.d., <https://consumerdatastandardsaustralia.github.io/standards/>.
[OID4VCI]
"OpenID for Verifiable Credential Issuance 1.0", n.d., <https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html>.
[OPENID-FED]
"OpenID Federation 1.0", n.d., <https://openid.net/specs/openid-federation-1_0.html>.
[PRESENTATION]
"OAuth 2.0 Software Statement Consumption and Runtime Presentation", n.d., <https://datatracker.ietf.org/doc/draft-mcguinness-oauth-sw-stmt-presentation>.
[PUSHED-DCR]
"OAuth 2.0 Pushed Client Registration", n.d., <https://datatracker.ietf.org/doc/draft-richer-oauth-pushed-client-registration>.
[RFC8252]
Denniss, W. and J. Bradley, "OAuth 2.0 for Native Apps", BCP 212, RFC 8252, DOI 10.17487/RFC8252, , <https://www.rfc-editor.org/rfc/rfc8252>.
[RFC8628]
Denniss, W., Bradley, J., Jones, M., and H. Tschofenig, "OAuth 2.0 Device Authorization Grant", RFC 8628, DOI 10.17487/RFC8628, , <https://www.rfc-editor.org/rfc/rfc8628>.
[STATUS-LIST]
"Token Status List", n.d., <https://datatracker.ietf.org/doc/draft-ietf-oauth-status-list>.
[TRUST-FRAMEWORK]
"OAuth Identity Assertion Trust Framework", n.d., <https://datatracker.ietf.org/doc/draft-mcguinness-oauth-id-assertion-framework>.
[UK-OPEN-BANKING]
"Open Banking UK Dynamic Client Registration Specification v3.3", n.d., <https://openbankinguk.github.io/dcr-docs-pub/v3.3/dynamic-client-registration.html>.

Appendix A. Deployment Examples

These non-normative scenarios show two end-to-end deployments and one case outside the specification's applicability.

A.1. Publisher Program: One Review, Many Customer Authorization Servers

TaskFlow is a workflow client used by marketplace customers. Its metadata at https://taskflow.example/oauth/metadata.json defines a production redirect URI and private_key_jwt authentication through jwks_uri. The marketplace's issuer is https://issuer.marketplace.example. Two customers trust it for TaskFlow's namespace at https://as.customer-a.example and https://as.customer-b.example.

  1. TaskFlow requests software_statement_code and repeats audience for both customers (Section 5).

  2. After the developer authenticates, TaskFlow validates state and iss, then redeems the code with PKCE, completion_mode=deferred, and private_key_jwt. A two-day review defers redemption, so TaskFlow polls with the same authentication (Section 7, Section 9).

  3. Approval returns a statement whose sub identifies TaskFlow, whose aud contains both customers, and whose cimd_digest binds the reviewed document.

  4. TaskFlow presents the statement at both [RFC7591] registration endpoints. Each validates it and assigns a local client_id. Both registrations use the attested jwks_uri (Section 11, Section 13).

  5. Out of band, the publisher program also issued TaskFlow an initial access token scoped to its client identifier and both audiences. Before expiry, the release pipeline exchanges it for a new statement (Section 8); line breaks are for display purposes only:

POST /token HTTP/1.1
Host: issuer.marketplace.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3A
  token-exchange
  &requested_token_type=urn%3Aietf%3Aparams%3Aoauth%3A
  token-type%3Asoftware-statement
  &subject_token=SplxlOBeZQQYbYS6WxSbIA...
  &subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3A
  token-type%3Aaccess_token
  &client_id=https%3A%2F%2Ftaskflow.example%2Foauth%2F
  metadata.json
  &audience=https%3A%2F%2Fas.customer-a.example
  &audience=https%3A%2F%2Fas.customer-b.example
  &completion_mode=deferred
  &client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3A
  client-assertion-type%3Ajwt-bearer
  &client_assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6InRhc2tmbG93LTEifQ...

The marketplace completes renewal synchronously when policy permits, using the unchanged audience and matching fresh metadata digest as inputs. The digest match alone does not determine the result.

A.2. Enterprise Deployment of a Third-Party Agent

ACME's AI agent uses one client identifier URL, https://acme.example/agent, across installations. An enterprise identity platform at https://idp.enterprise.example operates a token-exchange-only issuer. Internal authorization servers at https://tools-as.enterprise.example and https://data-as.enterprise.example trust it for the ACME agent.

  1. At onboarding, the identity platform gives its daemon an initial access token authorizing issuance for ACME. The daemon exchanges it while requesting both internal authorization servers as repeated audience values, with completion_mode=deferred and a DPoP proof (Section 8).

  2. The identity platform validates the token and returns a three-day [DTR] deferral. The daemon polls at the advertised interval with fresh proofs from the same DPoP key and no PKCE verifier (Section 9.1). Security review occurs out of band.

  3. The final poll returns the statement. The daemon registers once at each internal authorization server and supplies the enterprise's instance issuer as plain metadata (Section 13). Instances authenticate through that issuer, allowing shared registrations with per-instance token identity ([CLIENT-INSTANCE]). Because the statement omits jwks and jwks_uri, policy could instead permit per-deployment registrations with distinct keys.

The deferred response in step 2 is shown below. The HTTP 400 status and authorization_pending error indicate a successfully established deferral, not rejection:

HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
  "error": "authorization_pending",
  "deferral_code":
    "m9K2pL4uQ6vX8cD0fG2hJ5nR7sT1wY3aB6eP8zN4qV0",
  "expires_in": 259200,
  "interval": 300
}

The registration request at the tools authorization server in step 3 is:

POST /register HTTP/1.1
Host: tools-as.enterprise.example
Content-Type: application/json

{
  "software_statement": "eyJ0eXAiOiJzb2Z0d2FyZS1zdGF0ZW1l...",
  "instance_issuers": [
    {
      "issuer": "https://workload.enterprise.example",
      "jwks_uri": "https://workload.enterprise.example/jwks.json"
    }
  ]
}

Because the statement omits instance_issuers, the local value does not conflict with [RFC7591] precedence. It is unattested, so the internal authorization servers accept it under local policy, having authenticated the enterprise's own deployment tooling as the presenter (Section 16.7). Had the agent been deployed by a party the internal servers did not already authenticate, the attested variant of Section 13.1 would carry that delegation instead.

Before expiry, the daemon renews with the same initial access token and audiences; this version does not accept a prior statement as subject token (Section 8). If an ACME update changes the metadata digest, policy defers renewal for another security review.

A.3. The Resource Owner as Approver: A Case This Specification Does Not Serve

Now consider an individual running the ACME agent against their own authorization server. The resource owner is the approver, so the Introduction's applicability guidance excludes this case.

The OAuth authorization grant already records the user's approval. The generic URL identifies the client [CIMD]; instance assertions identify installations at the token endpoint ([CLIENT-INSTANCE]). Tokens can then identify the user as subject and the instance as actor, sender-constrained to the installation key.

A statement adds nothing: there is a single authorization server, a single approver already present in the transaction, and no review whose cost needs amortizing. Appendix A.2 reverses each condition.

Appendix B. Issuance Across the Software Delivery Lifecycle

This non-normative appendix places review, attestation, renewal, and expiry in the software-delivery lifecycle. Renewal here means re-issuing a statement; renewing the registration a statement governs is the consumption-side operation [PRESENTATION] defines. A publisher or enterprise reviews once and issues a statement (Appendix A.1, Appendix A.2). A release pipeline renews through token exchange; a changed digest prompts a carry-forward-or-re-review decision (Section 8). Sunset begins with the absence of renewal, which stops further statement use; registrations already derived from a statement expire with it at a server implementing the registration-validity model of [PRESENTATION], and elsewhere their retirement remains that server's own lifecycle work (Section 16.7).

The statement attests the software, not its instances (Section 13). It does not attest binaries or build provenance, identify running instances, or grant access; identifying the presenter is the work of a client attestation or instance assertion ([ABCA], [CLIENT-INSTANCE]), which composes with the statement rather than substituting for it (Section 16.2). It standardizes the vouching layer of delivery, which no other layer of the stack defines.

Appendix C. Design Rationale

The table compares where each establishment mechanism decides trust, its input, and its cost across M authorization servers.

Table 1
Mechanism Decision made at Input evaluated Cost for M authorization servers
Pre-registration of a client identifier URL ([CIMD]) each authorization server self-asserted metadata document M decisions
Pushed client registration ([PUSHED-DCR]) each authorization server self-asserted pushed metadata, per transaction M decisions
Approval-based registration ([APPROVAL-DCR]) each authorization server self-asserted registration request M approvals
This specification the issuing authorization server canonical metadata document one issuance decision, M policy evaluations of an attested artifact
OpenID Federation ([OPENID-FED]) resolved along a trust chain entity statements federation infrastructure

The bilateral mechanisms compose with statements: pre-registration or pushed registration can carry attested metadata, and approval-based registration can evaluate an issuer's decision. For one authorization server, they remain sufficient alone; portability justifies issuance. OpenID Federation supplies trust chains when pairwise issuer configuration no longer scales.

OpenID for Verifiable Credential Issuance [OID4VCI] has a similar flow but serves wallet-held credentials presented to verifiers. A software statement describes software and is consumed by [RFC7591] registration or runtime presentation ([PRESENTATION]). An OID4VCI profile would still need this specification's format, metadata binding, and consumption rules, although an existing ecosystem could carry the statement as a credential payload.

C.2. Why Use the Authorization Endpoint

The authorization endpoint supplies redirect URI validation, request correlation, PKCE, and issuer identification for browser-mediated interaction. A short-lived, sender-constrained code keeps the statement out of the browser; the token endpoint delivers it over a direct TLS connection. Without in-band interaction, a pre-authorized client instead uses token exchange (Section 8).

C.3. Why Not the Device Authorization Grant

The device authorization grant [RFC8628] assumes an interactive user co-present with a constrained device. Software-statement approval can instead involve a remote administrator and a long-running out-of-band workflow. Token endpoint deferral covers that case without a verification URI or user code; the redirect flow covers interactive authentication or consent.

C.4. Why the Issuer Is an Authorization Server Role

An alternative design defines a standalone issuer and leaves the minting interface out of scope, as [CLIENT-INSTANCE] does for instance issuers. That works for intra-domain instance attestation. It does not work here: [RFC7591] already standardized registration-time presentation, so minting is the missing interface.

The authorization server role reuses token endpoint authentication, [DTR] deferral, [RFC8693] token exchange, and [RFC8414] discovery. A minimal issuer needs only a token endpoint, metadata, and signing keys (Section 14). Explicit typ values separate statement and instance issuers.

C.5. Why the Software Statement Code Is Not an Authorization Code

The code is distinct because successful authorization_code redemption issues an access token under [RFC6749]. OpenID Connect returns an ID Token alongside, not instead of, an access token. A separate code preserves a code-shaped front channel while keeping deferral at the token endpoint.

C.6. Why Token Exchange Is a Profile, Not the Only Flow

Token exchange requires a subject_token [RFC8693], which a first-time client lacks. It derives authority from that token; the redirect flow derives authority from a new issuance decision. Thus token exchange serves pre-authorized clients, while the redirect flow serves those without a token.

C.7. Why Deferral Happens Only at the Token Endpoint

A short-lived code keeps statements and long-lived credentials out of the browser. Token endpoint redemption returns the statement or defers through [DTR], so every deferral originates from a token request.

An [RFC7591] registration endpoint creates a local client, and [APPROVAL-DCR] defers that operation there. This specification instead mints a portable artifact for registration elsewhere; placing issuance at registration would validate metadata without creating a client. The token endpoint already mints security tokens and hosts the pre-authorized path (Section 8). Using it for both flows reuses its authentication and [DTR] polling, cancellation, sender constraint, and rate limiting.

C.8. Why the Response Uses access_token

The response follows [RFC8693]: access_token carries the artifact, issued_token_type identifies it, and token_type=N_A excludes access-token semantics. Immediate and deferred responses therefore use existing token endpoint processing without implying resource access.

C.9. Deliberately Deferred Capabilities

This version omits seven capabilities, each with an extension point:

  • Token-endpoint initiation: a client without a user agent or pre-authorizing credential cannot initiate issuance. An extension can use the software statement grant without software_statement_code and advertise that mode in metadata.

  • Statement-as-subject renewal: renewal uses an initial access token or a new request (Section 8), not a prior statement. software_statement_subject_token_types_supported can advertise a future holder-bound subject-token profile.

  • Request-time metadata selection: only issuer-side narrowing is supported (Section 11). An extension can define a selection parameter.

  • Callback delivery: this version permits polling only (Section 9). A future version can adopt [DTR] callbacks.

  • Canonicalized digests: serialization changes alter the octet digest (Section 4.1). An extension can define a canonicalized digest claim or parameter.

  • Acceptance-time status: lifetime is the only in-band revocation control (Section 16.7); under [PRESENTATION] it expires a statement-governed registration outright and, as a matter of local policy, ends a runtime-established grant at refresh. An extension can define a status claim, for example over a Token Status List [STATUS-LIST], with the processing rules a trusting authorization server applies.

  • CIMD-native conveyance: runtime presentation ([PRESENTATION]) carries the statement in the request, and the registration path carries it in a registration request. A further profile could let a Client ID Metadata Document reference where a client publishes its current statements, so a resolving server fetches the review out of band with neither; [PRESENTATION] lists it as an extension point. This differs from embedding a statement in the document, which the digest rule of Section 4.1 forbids.

Appendix D. Acknowledgments

This specification builds on [DTR], [CIMD], and [APPROVAL-DCR]. The author thanks the authors and contributors to those specifications and the OAuth working group participants whose discussions informed this work.

Author's Address

Karl McGuinness