Web Authorization Protocol S. Canning
Internet-Draft Canva
Intended status: Standards Track 16 June 2026
Expires: 18 December 2026
Registration Lifecycle and Continuous Signalling for OAuth Clients
draft-canning-oauth-registration-lifecycle-latest
Abstract
This document defines a lifecycle state machine for OAuth 2.0 clients
identified by an OAuth Client ID Metadata Document (CIMD) URL or
registered via Dynamic Client Registration (RFC 7591), together with
an Authorization Server-hosted admin-approval ceremony that
transitions a just-in-time-registered "unmanaged" client into an
admin-pinned "managed" state, and a Security Event Token-shaped event
format that signals state transitions to interested consumers.
The mechanism extends RFC 7591 from binary (registered or not) to a
four-state machine (UNREGISTERED → UNMANAGED → MANAGED, with
SUSPENDED reachable from UNMANAGED and MANAGED) while preserving
client identifier stability across all transitions. The
Authorization Server metadata registry is extended with a
client_promotion_endpoint member naming the ceremony endpoint, and a
small profile of [SSF]/[CAEP] event types is defined.
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 18 December 2026.
Copyright Notice
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.
Table of Contents
1. Introduction
1.1. Editor's note: running-code basis
1.2. Terminology
2. Registration State Machine
2.1. States
2.2. Identifier stability
2.3. Transitions
3. Unmanaged-Tier Policy
4. Admin Approval Ceremony
4.1. Endpoint
4.2. Ceremony obligations
4.3. Pinning
4.4. Action: unsuspend
5. Managed-Tier Policy
6. Suspended State
6.1. Behaviour
6.2. Reverse transitions
7. Per-Request Guards
7.1. JWKS fetch size cap and SSRF discipline
7.2. private_key_jwt audience value
8. Lifecycle Event Signalling
8.1. Envelope
8.2. Event types
8.3. Event payload
8.4. Signing and delivery
9. Security Considerations
9.1. Refresh tokens deferred until MANAGED
9.2. Same-origin redirect_uris for unmanaged clients
9.3. Exfiltration via the ceremony return_uri
9.4. Pinning vs. silent change
9.5. SUSPENDED → MANAGED reverse-transition
9.6. Lookalike clients
9.7. Event signal authenticity
9.8. Admin role compromise
10. IANA Considerations
10.1. OAuth Authorization Server Metadata
10.2. Token Claims
10.3. SET Event Type URIs
11. References
11.1. Normative References
11.2. Informative References
Appendix A. Open Issues
A.1. A.1 PENDING state (admin approval before first login)
A.2. A.2 JWKS size cap numerics
A.3. A.3 private_key_jwt audience canonicalisation
A.4. A.4 Hard-reset action ("purge")
A.5. A.5 Admin role vocabulary
A.6. A.6 Pinning granularity (URL only vs. URL + key hash)
A.7. A.7 Event signing
A.8. A.8 Permanent prefix for event type URIs
Appendix B. Acknowledgments
Author's Address
1. Introduction
OAuth 2.0 client registration today is binary. A client either holds
a client_id issued by the Authorization Server (whether out-of-band,
by Dynamic Client Registration [RFC7591], or by identifying itself
with a CIMD URL [CIMD]) or it does not. Real enterprise deployments
operate a wider range of registration states: a just-in-time-
registered first-seen client may need extra controls (restricted
scope, extra consent, no refresh tokens) until an administrator has
had an opportunity to review it; a previously trusted client may be
suspended pending investigation; an admin who has approved a client
may wish to "pin" the specific keys and redirect URIs in force at the
time of approval, so that subsequent silent changes by the client are
not honoured until the admin re-reviews them.
This document defines a four-state lifecycle, an Authorization
Server-hosted admin ceremony for promotion and suspension actions,
and a Security Event Token-shaped event format for signalling state
transitions. The lifecycle is independent of the registration
mechanism (CIMD URL, DCR client_id, or pre-configured client_id); it
preserves identifier stability across all transitions.
The mechanism is sized for the *same-domain SSO bootstrap* target of
the broader zeroconf-sso profile [ZEROCONF-SSO]: in particular, the
UNMANAGED state is restrictive enough that an Authorization Server
can safely accept a first-seen CIMD URL without administrator
intervention, while the MANAGED state's pinning rules preserve the
admin's review choices against silent client-side change.
1.1. Editor's note: running-code basis
This draft is motivated by, and tracks, the following entries in
spec/GAPS.md of the zeroconf-sso prototype [ZEROCONF-SSO] [GAPS]:
- *GAP-3* — "Registration lifecycle states and signaling". The
state machine and admin ceremony are direct lifts of spec/
PROTOCOL.md §9 in that prototype, which the prototype's IdP
component implements end-to-end (admin promotion, suspension,
unsuspension; event emission at /admin/events).
- *GAP-6* — "JWKS fetch size cap and SSRF discipline" — addressed
in Section 7.1.
- *GAP-7* — "private_key_jwt audience value" — addressed in
Section 7.2, where this draft pins the canonical value pending
RFC 7523bis stabilisation.
- *GAP-8* — "SUSPENDED state's required reverse-transition path"
— addressed in Section 6.
- *GAP-9* — "Admin ceremony role vocabulary" — deliberately left
in Open Issues, with a minimal in-text MUST that an admin role
exists.
The prototype IdP implements UNMANAGED, MANAGED, and SUSPENDED end
to end; the prototype's integration tests assert that promotion
changes policy without re-registration and that suspension blocks
login.
1.2. Terminology
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.
The following terms are used throughout, in addition to the terms
defined in [RFC6749], [RFC8414], [RFC7591], and [CIMD].
Client identifier: The OAuth 2.0 client_id value, whether issued by
the Authorization Server out-of-band, issued by DCR [RFC7591], or
formed by the client as a CIMD URL [CIMD].
Registration state: The state of a client identifier on the
Authorization Server, as defined in Section 2.
Pinned set: The snapshot of jwks_uri and redirect_uris taken by the
Authorization Server at the moment a client transitions into the
MANAGED state, applied subsequently in place of the live values
from the client's metadata source. Defined in Section 4.3.
Domain admin: An End-User of the Authorization Server who holds an
implementation-defined role that authorises driving the admin
ceremony defined in Section 4. Role naming is discussed in Open
Issues (Appendix A).
Lifecycle event: A Security Event Token-shaped event ([RFC8417])
emitted by the Authorization Server when a client transitions
between registration states. Defined in Section 8.
2. Registration State Machine
2.1. States
A client identifier known to an Authorization Server implementing
this specification is in exactly one of the following states at any
time:
+-------------+
| UNREGISTERED|
+------+------+
|
first valid authz request
|
v
+-------------+ admin promote +---------+
| UNMANAGED |------------------>| MANAGED |
+------+------+ +----+----+
| |
+------- admin suspend ---------+
|
v
+-----------+
| SUSPENDED |
+-----------+
|
admin unsuspend (returns to MANAGED only)
The states are:
UNREGISTERED: The Authorization Server has no record of the client
identifier.
UNMANAGED: The Authorization Server has accepted a first valid
authorization request bearing this client identifier, but no
domain admin has approved the client. Restrictive policy applies
(Section 3).
MANAGED: A domain admin has approved the client through the ceremony
in Section 4. The Authorization Server holds a pinned set of
jwks_uri and redirect_uris for the client and applies them in
place of the live values. Relaxed policy MAY apply (Section 5).
SUSPENDED: A domain admin has suspended the client, or an
implementation- defined automated trigger has suspended it. All
authorization requests are refused with unauthorized_client
(Section 6).
This document does not define additional states; in particular it
does not define a PENDING state (admin approval _before_ first
login). PENDING is discussed under Open Issues (Appendix A).
2.2. Identifier stability
The client identifier MUST NOT change across any transition defined
in this document. Promotion from UNMANAGED to MANAGED, suspension
from any active state to SUSPENDED, and unsuspension SUSPENDED →
MANAGED are policy-state changes on the existing identifier; they are
NOT re-registrations.
This rule applies regardless of how the identifier was minted: a CIMD
URL [CIMD] client_id is still its CIMD URL after promotion; a DCR
[RFC7591]-issued identifier is still the same string.
2.3. Transitions
The transitions defined by this document are:
+==============+===========+=============================+
| From | To | Trigger |
+==============+===========+=============================+
| UNREGISTERED | UNMANAGED | First valid authorization |
| | | request from the client. |
+--------------+-----------+-----------------------------+
| UNMANAGED | MANAGED | Domain admin completes |
| | | promote action (Section 4). |
+--------------+-----------+-----------------------------+
| UNMANAGED | SUSPENDED | Domain admin or automated |
| | | trigger suspends. |
+--------------+-----------+-----------------------------+
| MANAGED | SUSPENDED | Domain admin or automated |
| | | trigger suspends. |
+--------------+-----------+-----------------------------+
| SUSPENDED | MANAGED | Domain admin completes |
| | | unsuspend action. |
+--------------+-----------+-----------------------------+
Table 1
No other transitions are permitted. In particular:
* There is no SUSPENDED → UNMANAGED transition. See Section 6 and
Open Issues (Appendix A).
* There is no MANAGED → UNMANAGED transition (a "demote" action is
not defined by this document).
* Deletion (transitioning back to UNREGISTERED by removing the
client record) MAY be performed by the Authorization Server
operator out-of-band; this document does not define a deletion
ceremony.
3. Unmanaged-Tier Policy
When the Authorization Server processes an authorization request
([OAUTH-2.1] §4.1) from a client in UNMANAGED state, it MUST:
* For CIMD clients ([CIMD]), enforce *same-origin* ([RFC6454])
between every redirect_uri in the client's CIMD document and the
CIMD URL (i.e. the client_id). The authorization request's
redirect_uri MUST also share that origin and MUST be one of those
listed in the CIMD document.
* For DCR clients ([RFC7591]), enforce that every registered
redirect_uri shares an origin with at least one of the
Authorization Server-validated identifiers presented at
registration time. In the absence of such an identifier the
Authorization Server MUST require the operator to pre-approve the
client (i.e. the client SHOULD NOT be permitted to operate in
UNMANAGED state via DCR alone). This avoids reintroducing the
unbounded-DCR problem that motivated CIMD.
* Restrict the granted scope set to an implementation- or profile-
defined minimum. For the zeroconf-sso profile [ZEROCONF-SSO] the
RECOMMENDED minimum is openid email profile. The Authorization
Server MUST reject requested scopes outside this set with the
OAuth 2.1 error invalid_scope ([OAUTH-2.1] §4.1.2.1).
* Display an explicit consent screen on every authorization,
prominently showing the client_id (CIMD URL or DCR-issued
identifier) hostname (cf. [CIMD] §6.4).
* NOT issue refresh tokens to the client. Refresh tokens are a
delegable grant surface; this document defers them to the MANAGED
state.
* Persist an audit record per authorization containing at minimum:
timestamp, end-user sub, client_id, redirect_uri, granted scope,
and request IP. The record MUST be visible to a domain admin
reviewing first-seen clients.
* Include the claim app_tier with the value "unmanaged" in any ID
Token issued ([RFC7519]); this claim is REQUIRED for UNMANAGED-
state issuances and is REGISTERED by this document (Section 10).
4. Admin Approval Ceremony
4.1. Endpoint
This document registers a new Authorization Server metadata member
(Section 10):
client_promotion_endpoint: An https URL identifying the endpoint at
which the admin ceremony is hosted. RECOMMENDED for any
Authorization Server that supports the UNMANAGED state.
A Relying Party admin tool initiates the ceremony by causing the
admin's browser to navigate to the endpoint with the following
parameters:
client_id (REQUIRED): The client_id of the candidate client (a CIMD
URL or DCR-issued identifier).
action (REQUIRED): One of "promote", "suspend", "unsuspend".
return_uri (REQUIRED): An https URL to which the Authorization
Server redirects the admin after the ceremony completes, carrying
the outcome.
state (RECOMMENDED): An opaque value the RP admin tool will validate
when the admin returns. Echoed by the Authorization Server in the
return_uri redirect.
4.2. Ceremony obligations
The Authorization Server MUST satisfy the following on receipt of a
ceremony request:
1. Authenticate the End-User driving the ceremony. The End-User
MUST hold a domain admin role (see Open Issues, Appendix A, for
role-vocabulary discussion). If authentication fails, or the
authenticated user does not hold the role, the ceremony MUST be
denied and a result=denied outcome MUST be reported per (6)
below.
2. Re-fetch the candidate client's CIMD document (for CIMD clients)
under the same fetch discipline as during authorization
processing: HTTP GET, no redirects, SSRF-special-use-IP
rejection, 5 KB cap for the CIMD doc itself, validation per
[CIMD]. A failure here MUST cause the ceremony to surface the
error to the admin and MUST NOT transition state.
3. Display, on the approval screen, the resolved redirect_uris,
jwks_uri, and client_name (if present) so the admin can see
exactly what is being pinned.
4. Verify that return_uri shares an origin with the candidate
client_id. For CIMD clients the origin of the client_id is the
origin of the CIMD URL; for DCR clients the Authorization Server
MAY use the origin of any registered redirect_uri. A mismatch
MUST cause result=invalid_request.
5. Apply the action only if the admin issues an explicit approval
gesture (e.g. clicks a confirmation button). Closing the browser
tab MUST be treated as denial, leaving the registration state
unchanged.
6. Regardless of outcome, redirect the admin to the return_uri
carrying:
* result — one of "approved", "denied", "invalid_request".
* client_id — the candidate identifier.
* state — echoed if supplied per §5.1.
The return_uri MUST receive only these parameters. The Authorization
Server MUST NOT include any user-identifying information about the
admin in the return_uri redirect.
4.3. Pinning
On approval of a promote action, the Authorization Server MUST
snapshot:
* the client's CIMD URL (for CIMD clients), or DCR identifier (for
DCR clients), as the canonical client identifier;
* the current jwks_uri value, and the SHA-256 hash of the document's
current key set (the Authorization Server MAY pin both the URL and
the hash, or only the URL — see Open Issues (Appendix A));
* the current redirect_uris set.
After promotion, the Authorization Server SHOULD continue to refresh
the CIMD document on its normal cache schedule, but MUST treat any
change to jwks_uri or redirect_uris as a security-relevant change per
[CIMD] §6.3 and SHOULD require re-approval before honouring the new
values.
4.4. Action: unsuspend
The unsuspend action requires that the candidate client be in
SUSPENDED state. On approval, the Authorization Server MUST re-
establish the pinned set previously held (i.e. the values pinned at
the most recent promote) and transition the client to MANAGED.
The Authorization Server MUST NOT discard the pinned set on
unsuspension. See Section 6 for the rationale.
5. Managed-Tier Policy
When the Authorization Server processes an authorization request from
a client in MANAGED state, the Authorization Server:
* MUST enforce redirect_uri against the *pinned* set, not the
current CIMD document or DCR record.
* MAY relax the UNMANAGED scope restriction subject to the
Authorization Server's local policy.
* MAY skip the per-request consent screen if the End-User has
previously consented (standard OpenID Connect behaviour).
* MAY issue refresh tokens.
* MUST still emit the iss authorization response parameter
[RFC9207], and MUST still validate private_key_jwt ([RFC7523])
against the pinned JWKS.
* MUST NOT include app_tier: unmanaged in any ID Token. The claim
MAY be set to "managed" for downstream Relying Party signalling.
6. Suspended State
6.1. Behaviour
A SUSPENDED client MUST be refused with the OAuth 2.1 error
unauthorized_client ([OAUTH-2.1] §4.1.2.1). The error response MUST
be delivered to the request's redirect_uri only if that URI remains
valid for the suspended client (i.e. it remains in the pinned set for
previously-MANAGED clients, or the same-origin rule of Section 3 for
never-promoted clients). Otherwise the Authorization Server MUST
surface the error to the End-User directly per [OAUTH-2.1] §2.3.5 and
§4.1.2.1.
The Authorization Server MUST emit the iss parameter on the error
redirect ([RFC9207] §2.2) when it does deliver an error to the
request's redirect_uri.
6.2. Reverse transitions
A SUSPENDED client returns to MANAGED state via the unsuspend action
(Section 4.4). No other reverse transition out of SUSPENDED is
defined by this document.
In particular, SUSPENDED → UNMANAGED is NOT permitted. This
preserves the pinned set the admin previously reviewed; discarding it
would lose information without operator review and re-introduce the
silent-change risk the pinning step was designed to close. A
deployment that wants a hard reset (re-establish via the JIT path
with no pinned values) MUST delete the client record out-of-band (see
Open Issues, Appendix A, for a possible "purge" action).
7. Per-Request Guards
This section pins two behaviours that the CIMD draft [CIMD] and RFC
7523bis [RFC7523BIS] leave open, and that the prototype
[ZEROCONF-SSO] surfaced (GAP-6 and GAP-7).
7.1. JWKS fetch size cap and SSRF discipline
The Authorization Server MUST fetch the client's JWKS from the
jwks_uri in the (live or pinned) client metadata to validate
private_key_jwt ([RFC7523]) client assertions. This fetch MUST
apply:
* the same hostname-resolution and SSRF protections as the CIMD
fetch ([CIMD] §6.5), in particular: rejection of host components
resolving to RFC 6890 special-use addresses (except where the
Authorization Server itself is on a loopback interface);
* no HTTP redirects;
* a body size cap of *32 KB*. This is larger than the [CIMD] §6.6 5
KB cap for the metadata document because realistic JWKS documents
carrying current and rotation keys, plus optional key-
encipherment material, exceed 5 KB. The 32 KB number was
determined empirically against a sample of real-world JWKS
documents; it accommodates roughly 16 RSA-2048 keys with metadata.
The cache invalidation rules from [CIMD] §4.4 apply unchanged to the
JWKS cache.
7.2. private_key_jwt audience value
The Authorization Server MUST accept a client assertion JWT (per
[RFC7523]) whose aud claim equals either:
* the Authorization Server's issuer value as published in its
metadata ([RFC8414]); OR
* the URL of the token endpoint at which the assertion is being
presented.
This document REQUIRES Authorization Servers to accept both values in
this revision. RFC 7523bis [RFC7523BIS] is the authoritative
specification once published; the choice of which value to RECOMMEND
to clients is deferred to it. Clients MAY mint assertions with the
issuer value, but the token endpoint value remains the canonical OIDC
Core §9 convention and many existing Authorization Servers require
it; clients SHOULD be prepared to use either based on deployment
policy.
This permissive posture is bounded in time: once [RFC7523BIS]
stabilises, a future revision of this document SHOULD remove the
permissive acceptance rule.
8. Lifecycle Event Signalling
8.1. Envelope
The Authorization Server MUST emit a lifecycle event for every state
transition defined in Section 2. Events are structurally compatible
with the OpenID Shared Signals Framework [SSF] and Continuous Access
Evaluation Profile [CAEP], and are carried inside a Security Event
Token (SET) [RFC8417].
A lifecycle event SET MUST carry the following claims:
iss: The Authorization Server's issuer URL as published in its
metadata ([RFC8414]).
iat: Event issuance time.
jti: Unique event identifier.
aud: The audience(s) entitled to receive the event. In this
profile, the audience SHOULD include the client_id of the subject
client. Stream-configured fan-out to additional audiences is an
SSF stream property and out of scope.
events: A single-entry object keyed by an event type URI defined in
Section 8.2, whose value is the per-event payload defined in
Section 8.3.
8.2. Event types
This document defines three event types within a profile URI prefix:
+=======================+==================================+
| Event type URI suffix | Trigger |
+=======================+==================================+
| client-promoted | UNMANAGED → MANAGED |
+-----------------------+----------------------------------+
| client-suspended | UNMANAGED or MANAGED → SUSPENDED |
+-----------------------+----------------------------------+
| client-unsuspended | SUSPENDED → MANAGED |
+-----------------------+----------------------------------+
Table 2
The URI prefix is https://schemas.zeroconf-sso.example/secevent/ in
this revision (matching the prototype [ZEROCONF-SSO]). A permanent
IANA-registered prefix is requested in Section 10; until that
registration is approved, implementations MUST use the prefix above
for interoperability with the prototype.
8.3. Event payload
A lifecycle event payload MUST contain at minimum:
subject: A SET §2.3-compatible subject object { "format": "uri",
"uri": "..." } whose uri value is the client_id of the subject
client.
event_timestamp: Milliseconds since the Unix epoch.
prior_state: One of "UNREGISTERED", "UNMANAGED", "MANAGED",
"SUSPENDED".
new_state: One of "UNMANAGED", "MANAGED", "SUSPENDED".
The following additional members are REQUIRED on specific event
types:
* client-promoted and client-unsuspended MUST carry a pinned object
with members jwks_uri (the URL) and redirect_uris (the array).
The pinned key set hash MAY be included as jwks_sha256 (lower-case
hex).
* client-suspended MUST carry reason (free-form string) and
triggered_by (one of "admin", "automated").
8.4. Signing and delivery
The lifecycle event format defined here is structurally compatible
with a SET-wrapped JWT, but this document does NOT mandate signing in
this revision. The prototype [ZEROCONF-SSO] emits plain JSON event
objects so that the event log is inspectable to the integration test;
this MUST be revisited before any real-world deployment (see Open
Issues, Appendix A).
Delivery is via an SSF stream configured out-of-band per [SSF] §7.
The Authorization Server MUST persist emitted events in a log
addressable for inspection (admin debug endpoint or operator-side
durable log); the prototype implements /admin/events for this
purpose.
9. Security Considerations
9.1. Refresh tokens deferred until MANAGED
Refresh tokens are a delegable grant surface: possession of a refresh
token, plus the ability to authenticate as the client, lets the
holder mint access tokens indefinitely until the refresh token is
revoked. This document defers refresh-token issuance to the MANAGED
state (Section 3) so that the first interactive grant to a first-seen
client cannot be silently extended past the End-User's attention. A
deployment that disagrees with this trade-off MAY relax it as local
policy, but at the cost of admin visibility: unmanaged-tier policy is
the only thing the Authorization Server gives an enterprise to limit
a not-yet-reviewed client's reach.
9.2. Same-origin redirect_uris for unmanaged clients
The UNMANAGED state's same-origin rule on redirect_uris (Section 3)
closes an exfiltration channel: a CIMD URL at
https://app.example.com/cimd whose document lists redirect URIs at
arbitrary unrelated hosts could otherwise be used to surface
authorization codes at any of them. Forcing every redirect URI to
share an origin with the client_id constrains the attack surface to
the host that holds the CIMD URL itself.
9.3. Exfiltration via the ceremony return_uri
The return_uri parameter of the admin ceremony (Section 4) carries
the outcome of a promotion or suspension back to the RP admin tool.
If the Authorization Server accepted an arbitrary return_uri, a
hostile admin tool at an unrelated origin could receive the
result=approved signal and use it to drive out-of-band exploitation
against an enterprise that mistakenly clicked through the ceremony.
The Authorization Server MUST constrain return_uri to share an origin
with the candidate client_id (Section 4, step 4) to close this
channel.
9.4. Pinning vs. silent change
The pinning rule (Section 4.3) is the only mechanism this document
provides against silent client-side change after admin approval. An
attacker who briefly controls a managed client's hosting endpoint
(but not its CIMD signing keys, if applicable) cannot mint new
redirect URIs that the Authorization Server will honour; the
Authorization Server applies the pinned set. The administrator MUST
be re-engaged to honour a change.
Authorization Servers that omit the pinning step (i.e. continue to
follow live redirect_uris and jwks_uri after admin approval) re-
introduce the silent-change risk in full.
9.5. SUSPENDED → MANAGED reverse-transition
The decision to permit only SUSPENDED → MANAGED (Section 6) trades
off "fast recovery to the most recent admin-reviewed state" against
"operator-driven hard reset". A deployment that experiences a
genuine compromise of a previously-managed client SHOULD prefer
deletion of the client record over unsuspension, so that the
subsequent JIT re-establishment puts the admin back in the loop. See
Open Issues (Appendix A) for a possible "purge" action.
9.6. Lookalike clients
This document does not address lookalike clients (a malicious vendor
publishing a CIMD document with a deceptively similar client_name or
logo). The UNMANAGED-tier policy of Section 3 is the only mitigation
here, and is structural rather than detective: the restricted scope
and explicit consent screen reduce blast radius even if the End-User
is deceived. A heavier verification mechanism remains out of scope;
see Open Issues.
9.7. Event signal authenticity
This revision does not require lifecycle events to be signed JWTs
(Section 8). A deployment that consumes events from an outside party
MUST sign them per [RFC8417] §4; the prototype's omission is for
inspectability only.
9.8. Admin role compromise
Possession of the admin role at the Authorization Server is
equivalent to control over the MANAGED-tier policy applied to every
client the role can promote. The Authorization Server MUST hold
domain admins to authentication standards at least as strong as those
it requires of end users, and SHOULD require step-up authentication
([RFC9470]) at the moment of ceremony approval.
10. IANA Considerations
10.1. OAuth Authorization Server Metadata
This document registers the following member in the "OAuth
Authorization Server Metadata" registry established by [RFC8414]:
Metadata Name: client_promotion_endpoint
Metadata Description: An HTTPS URL identifying the Authorization
Server-hosted admin ceremony endpoint for transitioning clients
between lifecycle states.
Change Controller: IETF
Reference: This document, Section 4
10.2. Token Claims
This document registers the following claim in the "JSON Web Token
Claims" registry established by [RFC7519]:
Claim Name: app_tier
Claim Description: Lifecycle state of the client to which a token
was issued, expressed as one of "unmanaged" or "managed". Used by
Relying Parties to distinguish administrator-reviewed from JIT-
only-registered clients.
Change Controller: IETF
Reference: This document, Section 3 and Section 5
10.3. SET Event Type URIs
This document REQUESTS the registration of three new SET event type
URIs in the OAuth/OIDF event-type registry. Pending establishment of
a permanent prefix, the URIs in Section 8.2 use a profile- private
prefix. Once a permanent prefix is assigned, this document will be
updated to refer to it.
11. References
11.1. Normative References
[CIMD] Parecki, A. and E. Smith, "OAuth Client ID Metadata
Document", March 2026, .
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
.
[RFC6454] Barth, A., "The Web Origin Concept", RFC 6454,
DOI 10.17487/RFC6454, December 2011,
.
[RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
RFC 6749, DOI 10.17487/RFC6749, October 2012,
.
[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, July 2015,
.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, .
[RFC8414] Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0
Authorization Server Metadata", RFC 8414,
DOI 10.17487/RFC8414, June 2018,
.
[RFC8417] Hunt, P., Ed., Jones, M., Denniss, W., and M. Ansari,
"Security Event Token (SET)", RFC 8417,
DOI 10.17487/RFC8417, July 2018,
.
11.2. Informative References
[CAEP] OpenID Foundation, "OpenID Continuous Access Evaluation
Profile 1.0", 2024,
.
[GAPS] "zeroconf-sso: standards gaps log (spec/GAPS.md)", 2026,
.
[I-D.canning-oauth-dns-issuer-discovery]
Canning, S., "DNS-Based Discovery of OAuth Authorization
Servers for Email Domains", 2026,
.
[I-D.canning-oauth-issuer-domain-binding]
Canning, S., "Issuer-to-Domain Authority Binding for
OAuth", 2026, .
[OAUTH-2.1]
Hardt, D., Parecki, A., and T. Lodderstedt, "The OAuth 2.1
Authorization Framework", 2025,
.
[RFC7519] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token
(JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015,
.
[RFC7523] Jones, M., Campbell, B., and C. Mortimore, "JSON Web Token
(JWT) Profile for OAuth 2.0 Client Authentication and
Authorization Grants", RFC 7523, DOI 10.17487/RFC7523, May
2015, .
[RFC7523BIS]
IETF OAuth WG, "OAuth 2.0 JWT-Secured Authorization
Request Profile for Client Authentication and
Authorization Grants", 2026,
.
[RFC9207] Meyer zu Selhausen, K. and D. Fett, "OAuth 2.0
Authorization Server Issuer Identification", RFC 9207,
DOI 10.17487/RFC9207, March 2022,
.
[RFC9470] Bertocci, V. and B. Campbell, "OAuth 2.0 Step Up
Authentication Challenge Protocol", RFC 9470,
DOI 10.17487/RFC9470, September 2023,
.
[SSF] OpenID Foundation, "OpenID Shared Signals Framework
Specification 1.0", 2024, .
[ZEROCONF-SSO]
"zeroconf-sso prototype and profile (running code)", 2026,
.
Appendix A. Open Issues
This appendix lists open questions that this revision does not
foreclose. Each entry corresponds to an item in spec/GAPS.md of the
zeroconf-sso prototype [ZEROCONF-SSO][GAPS].
A.1. A.1 PENDING state (admin approval before first login)
This document defines the path "first authorization request →
UNMANAGED → admin promotes → MANAGED". An enterprise that wants its
admins to approve a client BEFORE the first user login (the PENDING
case) cannot express that policy under this revision; the first login
is always permitted under UNMANAGED-tier policy. A future revision
MAY add a PENDING state, gated by a per-Authorization-Server policy
that the operator sets out-of-band.
A.2. A.2 JWKS size cap numerics
Section 7.1 pins 32 KB based on empirical inspection of real- world
JWKS documents. The right number depends on observed key- rotation
patterns and on the upper bound an Authorization Server is willing to
accept before considering a document hostile. A future revision
SHOULD revisit the number with broader deployment evidence.
A.3. A.3 private_key_jwt audience canonicalisation
Section 7.2 accepts both the issuer URL and the token endpoint URL
pending [RFC7523BIS]. The right canonical value is deferred to that
draft. This document SHOULD be aligned with RFC 7523bis once that
document stabilises; the permissive acceptance rule SHOULD be removed
in favour of a single canonical value.
A.4. A.4 Hard-reset action ("purge")
Section 6 permits only SUSPENDED → MANAGED, not SUSPENDED →
UNMANAGED. An operator that wants to wipe the pinned set on the way
back from suspension has no protocol-level lever in this revision
beyond deletion of the client record. A future revision MAY define a
fourth ceremony action purge that combines deletion with an event
signal so that downstream consumers see the reset.
A second design question is whether the client_unsuspended event
should carry the prior pinned values so that consumers can detect
tampering across the suspended interval. This document does not
require it.
A.5. A.5 Admin role vocabulary
Section 4 requires a "domain admin role" but defines exactly one.
Real deployments routinely carry multiple roles (security_admin,
app_admin, audit) and different action verbs (promote vs. suspend vs.
unsuspend) may warrant different roles. The prototype [ZEROCONF-SSO]
maps a single literal role string to all three actions. A future
revision MAY define:
* A small standardised role vocabulary with a profile-defined
mapping from role to permitted action.
* An OAuth-scopes-based gate on the admin's IdP session, in lieu of
a separate role vocabulary.
This document takes no position.
A.6. A.6 Pinning granularity (URL only vs. URL + key hash)
Section 4.3 permits the Authorization Server to pin only the jwks_uri
URL, or the URL plus a SHA-256 hash of the current key set. The
trade-off is admin friction during scheduled key rotation versus
blast radius if jwks_uri content is silently swapped. A future
revision MAY mandate the hash form for high-assurance deployments.
A.7. A.7 Event signing
Section 8 does not mandate JWT-wrapping of lifecycle events. The
running-code argument for plain-JSON envelopes is inspectability
during integration testing. The argument for mandating JWT (i.e. RFC
8417 SET signing) is that any cross-organisation event delivery
demands cryptographic authenticity. A future revision SHOULD mandate
the SET-wrapped form for any deployment that publishes events to a
consumer outside the issuing organisation.
A.8. A.8 Permanent prefix for event type URIs
Section 8.2 uses a profile-private prefix. Allocation of a permanent
IANA-registered prefix is requested in Section 10; until that
allocation is approved, deployments will need to interoperate on the
profile-private URIs.
Appendix B. Acknowledgments
This work was motivated by the zeroconf-sso prototype [ZEROCONF-SSO],
whose spec/GAPS.md log [GAPS] catalogued the specific scenarios cited
in Appendix A. The state machine and admin ceremony shape are direct
lifts of spec/PROTOCOL.md §9 in that prototype, where they are
implemented end-to-end and exercised by the prototype's integration
tests.
Author's Address
Simon Canning
Canva
Email: scanning@canva.com