| Internet-Draft | oauth-software-statement-issuance | August 2026 |
| McGuinness | Expires 8 February 2027 | [Page] |
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.¶
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.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
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:¶
a redirect flow, using response_type=software_statement_code and the urn:ietf:params:oauth:grant-type:software-statement redemption grant; or¶
OAuth token exchange, when it already holds an initial access token authorizing issuance (Section 8).¶
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:¶
the resource owner is the approver, because the ordinary OAuth grant is the approval;¶
the trust decision is local to one authorization server, where an initial access token [RFC7591], pre-registration [CIMD], or approval-based registration [APPROVAL-DCR] can establish the client directly; or¶
the client cannot host a metadata document at an HTTPS URL and therefore does not fit this specification's identity model (Section 4).¶
A software statement earns its cost beyond those boundaries when one or more of the following holds:¶
One approval must be honored at many authorization servers.¶
The party approving the software is not the resource owner in a transaction.¶
Approval must exist before any authorization transaction does.¶
Approval requires asynchronous review that outlives a single protocol exchange.¶
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.¶
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).¶
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.¶
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:¶
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.¶
The authorization server that makes the issuance decision and signs the software statement.¶
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]).¶
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.¶
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.¶
The validated canonical metadata bound to a request, as defined in Section 4.1.¶
The unpadded base64url encoding of the SHA-256 hash of the retrieved octets of a metadata document, as defined in Section 4.1.¶
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:¶
An HTTPS Client ID Metadata Document URL identifies the client, and its content supplies the canonical metadata [CIMD].¶
The issuing authorization server fetches and snapshots that document, decides whether to issue, and signs the statement (Section 4.1).¶
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]).¶
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.¶
+--------+ +----------------------+
| 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].¶
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:¶
none (explicit) establishes a public client.¶
Any other value establishes a confidential client, and the authorization server MUST require exactly that method, as required by [CIMD]; a declared method the authorization server does not support MUST cause rejection rather than treatment as public.¶
An omitted value establishes neither: the [RFC7591] default is a symmetric-secret method that [CIMD] prohibits and an unregistered client cannot satisfy, so any request identifying such a client MUST be rejected with invalid_request, returned to the redirection URI validated against the document.¶
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:¶
A public client using the redirect flow MUST include dpop_jkt in the authorization request and MUST present a DPoP proof signed with the corresponding key at redemption and on every polling request.¶
A public client using the token exchange profile (Section 8) MUST instead include a DPoP proof on the exchange request. The authorization server MUST bind any resulting deferral state to that proof's key, and the client MUST use the same key on every polling request.¶
A confidential client MAY use DPoP in addition to its client authentication method.¶
All uses of DPoP MUST follow [RFC9449] and [DTR].¶
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.¶
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:¶
Approved: the authorization server returns the software statement token response (Section 10).¶
Denied: it returns the terminal denial of Section 10.1.¶
Pending: a deferred issuer returns the deferred token response of [DTR]. It binds the deferral to the code's client identifier, metadata snapshot, audience, and client authentication or DPoP key. The client then polls according to Section 9.¶
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...¶
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:¶
time limited;¶
limited to the issuing authorization server;¶
bound to an exact client identifier URL or an explicitly authorized client identifier namespace; and¶
of at least 128 bits of entropy, when opaque.¶
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:¶
a software statement token response (Section 10) on success;¶
a [DTR] deferred token response from a deferred issuer, followed by polling, when processing cannot complete immediately (Section 9); or¶
the terminal denial of Section 10.1 when issuance policy denies the exchange.¶
An authorization server supports one of two conformance levels:¶
A synchronous issuer answers every originating request with a statement or terminal denial (Section 10.1), so it MUST reach the issuance decision before responding, which in the redirect flow means before returning the software statement code. It never defers, need not implement [DTR], and does not advertise deferred_token_response_supported.¶
A deferred issuer returns a deferred token response when a decision needs out-of-band processing. It implements [DTR] and advertises deferred_token_response_supported (Section 14).¶
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:¶
the client identifier;¶
the client authentication method; and¶
for a method that binds a key, that specific key: the DPoP JWK thumbprint, or the authenticated key for a method such as private_key_jwt or mTLS.¶
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.¶
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.¶
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].¶
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).¶
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.¶
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).¶
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¶
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.¶
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.¶
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:¶
Shared client key: if the statement contains jwks or jwks_uri, that attested value takes precedence under [RFC7591], and every registration derived from the statement MUST use the attested key material rather than an instance-supplied replacement. It also fixes the runtime proof, as Section 16.7 describes.¶
Per-instance keys: where authorization server policy is keyed on client_id and genuinely requires per-instance registrations, the same statement supports that model only if it omits jwks and jwks_uri; each registration then supplies its own instance key as plain metadata, subject to trusting authorization server policy and the presenter-proof guidance of Section 16.7.¶
Attested delegation: the statement omits key material but attests the instance_issuers delegation (Section 13.1), so instance keys are endorsed by an attested authority at the token endpoint instead of appearing unattested in registration metadata.¶
[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"
}
]
¶
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:¶
the exact iss identifier it will accept;¶
the source of that issuer's signing keys: the jwks_uri in the issuer's authorization server metadata [RFC8414], reached from the configured iss;¶
the signing algorithms it will accept from the issuer;¶
the client identifier namespaces the issuer may attest through sub;¶
the audience identifiers the issuer may name;¶
the maximum statement lifetime it will honor, which also caps registration validity where the server implements the registration-validity model of [PRESENTATION];¶
the metadata claims for which it treats the issuer as authoritative; and¶
its policy on repeated and multiple registration (Section 13).¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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).¶
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.¶
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.¶
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.¶
This specification requests registration of the following values in the IANA "OAuth URI" registry:¶
urn:ietf:params:oauth:grant-type:software-statement¶
OAuth Software Statement Grant Type¶
IESG¶
urn:ietf:params:oauth:token-type:software-statement¶
OAuth Software Statement Token Type¶
IESG¶
This specification, Section 10 and Section 8¶
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]:¶
This specification requests registration of the following error usage in the IANA "OAuth Extensions Error Registry" established by [RFC6749]:¶
access_denied¶
token error response¶
The software statement grant (Section 7) and token exchange profile (Section 8) of this specification¶
IESG¶
This specification, Section 10.1¶
It further requests registration of the following error usage:¶
This specification requests registration of the application/software-statement+jwt media type in the IANA "Media Types" registry [RFC6838].¶
application¶
software-statement+jwt¶
n/a¶
n/a¶
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].¶
See Section 16 of this specification and Section 11 of [RFC7519].¶
n/a¶
This specification¶
Authorization servers and clients that issue, request, or accept OAuth 2.0 software statements¶
n/a¶
File extension(s): n/a. Macintosh file type code(s): n/a.¶
Karl McGuinness, public@karlmcguinness.com¶
COMMON¶
none¶
Karl McGuinness, public@karlmcguinness.com¶
IETF¶
This specification requests registration of the following value in the IANA "JSON Web Token Claims" registry established by [RFC7519]:¶
cimd_digest¶
Unpadded base64url-encoded SHA-256 digest of the retrieved octets of the Client ID Metadata Document evaluated during software statement issuance¶
IESG¶
This specification, Section 11¶
These non-normative scenarios show two end-to-end deployments and one case outside the specification's applicability.¶
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.¶
TaskFlow requests software_statement_code and repeats audience for both customers (Section 5).¶
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).¶
Approval returns a statement whose sub identifies TaskFlow, whose aud contains both customers, and whose cimd_digest binds the reviewed document.¶
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).¶
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.¶
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.¶
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).¶
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.¶
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.¶
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.¶
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.¶
The table compares where each establishment mechanism decides trust, its input, and its cost across M authorization servers.¶
| 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.¶
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.¶
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.¶
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.¶
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.¶
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.¶