| Internet-Draft | OIDFed Node Admin | August 2026 |
| Kodden | Expires 2 March 2027 | [Page] |
This document specifies a compact HTTP application programming interface for administering an OpenID Federation node. The interface manages the operator-controlled inputs from which a node produces the Entity Configurations, Subordinate Statements, Trust Marks, and Federation Entity Keys defined by OpenID Federation 1.1. It does not replace the public federation protocol. It is the management plane used by operators and control-plane software to configure what that protocol publishes.¶
The design is document-oriented. Operators read and write the same JSON objects OpenID Federation already defines, rather than a large set of per-claim endpoints. Five resources cover node identity, Federation Entity Keys, the node's Entity Configuration, Immediate Subordinates, and Trust Mark issuance.¶
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 2 March 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.¶
OpenID Federation 1.1 [OIDF.Federation] defines
how Federation Entities publish signed Entity Statements, build
Trust Chains, apply metadata policies, and issue Trust Marks.
Those mechanisms are the public protocol plane: any relying
party on the Internet can fetch
/.well-known/openid-federation, call
federation_fetch_endpoint, and resolve a Trust Chain.¶
The specification does not define how an operator configures a node so that those public artifacts exist. In practice, Trust Anchors, Intermediate Entities, Leaf Entities, and Trust Mark Issuers are administered through vendor-specific HTTP APIs. Existing implementations [Sphereon.Admin], [GEANT.Admin], [Gateway.Admin], and [SURF.OIDFed] expose dozens of fine-grained endpoints, one for each nested claim. That style is convenient for some user interfaces. It is a poor protocol: it duplicates the OpenID Federation data model, drifts as the federation specification evolves, and forces every control plane to learn a different surface.¶
This document specifies a single, compact administration protocol that is strictly aligned with OpenID Federation 1.1:¶
The result is a small, implementable API that Leaf nodes, Intermediates, Trust Anchors, and Trust Mark Issuers can share, advertising which resources they actually support.¶
This protocol is intended for:¶
This protocol is not intended to replace Trust Chain resolution, Automatic or Explicit Registration, or any other public federation endpoint. Clients that only need to consume federation data MUST use [OIDF.Federation] and MUST NOT require this API.¶
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.¶
JSON object member names are case-sensitive. This document uses the JSON data model of [RFC8259]. HTTP terminology follows [RFC9110]. URI syntax follows [RFC3986].¶
Unless stated otherwise, examples are non-normative.¶
This document uses the terms Entity, Entity Identifier, Entity Configuration, Entity Statement, Entity Type, Federation Entity Keys, Immediate Superior, Immediate Subordinate, Intermediate Entity, Leaf Entity, metadata, metadata policy, Subordinate Statement, Trust Anchor, Trust Chain, Trust Mark, Trust Mark Issuer, and Trust Mark Owner as defined in [OIDF.Federation].¶
This document also uses the following terms:¶
/.well-known/openid-federation.¶
A node has two HTTP surfaces. The Protocol Plane is defined
entirely by [OIDF.Federation]. It serves Entity
Configurations, Subordinate Statements, Trust Marks, and related
federation endpoints to unauthenticated or
private_key_jwt-authenticated federation participants.¶
The Administration Plane is defined by this document. It is a confidential HTTP API used by operators and control-plane clients to create, update, suspend, and revoke the inputs from which the Protocol Plane is generated.¶
Operator / Control Plane
|
| Administration API (this document)
| authenticated, confidential
v
+------------+ signs +----------------+
| Admin docs | --------------------> | Protocol Plane |
| Keys | Entity Config | /.well-known/ |
| Status | Subord. Statement | fetch / list |
| | Trust Mark JWT | resolve / TM |
+------------+ +----------------+
^ |
| v
Administration Server Federation participants
A successful mutating Administration API request MUST leave the Protocol Plane consistent with the resulting Admin Documents before the success response is returned, with the exception of key rollover grace periods described in Section 11. Implementations MAY sign new Entity Statements lazily, provided that the next Protocol Plane response reflects the update.¶
This document does not specify multi-node orchestration, operator identity providers, or a federation-wide registry. Those are deployment concerns (Section 17).¶
A node is initialized when it has an Entity Identifier and at least one signing-capable Federation Entity Key (the server holds the private key or can invoke a KMS to use it).¶
The Entity Identifier is established by local configuration
(for example a configuration file or container image) or by
the first successful PUT {base}/configuration whose
body includes entity_id. After initialization the
server MUST reject any write that would change
entity_id (400 with problem type
invalid_request).¶
GET {base} MUST succeed once the Administration
Server is listening, including before initialization. Before
the Entity Identifier is set, the Node document omits
entity_id and signing_kid.¶
Requests that require a signature — publishing an Entity
Configuration or Subordinate Statement, or issuing a Trust
Mark — MUST fail with 409 and problem type
not_initialized until initialization is complete.¶
A node plays one or more of the roles defined by [OIDF.Federation]:¶
trust_anchor — has Immediate Subordinates and no
Superior (or is treated as a Trust Anchor by its federation).¶
intermediate — has both Immediate Superiors and
Immediate Subordinates.¶
leaf — has Immediate Superiors and no Immediate
Subordinates.¶
trust_mark_issuer — issues Trust Marks.¶
resolver — publishes
federation_resolve_endpoint.¶
The resolver role means the node publishes
federation_resolve_endpoint in its Entity
Configuration, typically under
metadata.federation_entity. This document does not
define administration of resolver state such as cached Trust
Chains or the set of Trust Anchors a resolver uses. Those
remain Protocol Plane behavior and local configuration
([OIDF.Federation], Sections 8.3 and 10.6). A
node that is only a resolver MUST implement Node, Keys, and
Entity Configuration. It MUST return
unsupported_resource for Subordinates and Trust Marks
unless it also plays a Superior or issuer role.¶
Roles determine which Administration API resources a node MUST implement. A node that is only a Leaf MUST implement Node, Keys, and Entity Configuration. A node that is a Superior MUST additionally implement Subordinates. A node that issues Trust Marks MUST implement Trust Marks.¶
The node advertises implemented resources in the Node resource (Section 10). Clients MUST query that resource and MUST NOT assume that every node implements every resource.¶
The Administration API is a set of HTTPS resources under a
single base path. The default base path is /admin/v1.
Servers MAY use a different base path; clients discover it from
the Node resource or from deployment configuration.¶
Five resources constitute the API:¶
| Resource | Path | Purpose |
|---|---|---|
| Node |
{base}
|
Identity, roles, capabilities |
| Keys |
{base}/keys
|
Federation Entity Keys |
| Entity Configuration |
{base}/configuration
|
Self-asserted Admin Document |
| Subordinates |
{base}/subordinates
|
Immediate Subordinate Admin Documents |
| Trust Marks |
{base}/trust-marks
|
Trust Mark issuance and subject grants |
Each collection uses the HTTP methods in [RFC9110] with the following uniform meaning:¶
GET — read a document or list members.¶
POST — create a member (or invoke a controller such as rotate).¶
PUT — replace a document.¶
PATCH — merge-patch a document
([RFC5789], [RFC7396]).¶
DELETE — remove a member and stop publishing it.¶
Signed protocol artifacts are available as sub-resources that return the JWT the node currently publishes:¶
GET {base}/configuration/statement¶
GET {base}/subordinates/{entity_id}/statement¶
GET {base}/trust-marks/{type}/subjects/{entity_id}/token¶
That is the entire API. Nested claim paths such as
/subordinates/{id}/metadata-policies/{entityType}/{claim}/{operator}
are deliberately omitted. Operators who need to change one
field send a JSON Merge Patch against the document that
contains it.¶
A node's Entity Identifier is the iss / sub
value of its Entity Configuration. It is immutable for the
lifetime of the node after initialization.¶
Immediate Subordinates and Trust Mark subjects are addressed by
their Entity Identifier. Trust Mark types are addressed by
their trust_mark_type URI.¶
When an Entity Identifier or Trust Mark type appears as a path
segment, it MUST be percent-encoded as a single segment per
[RFC3986]. Clients MUST encode the entire
identifier, including scheme, :, /, and
?. Servers MUST decode exactly one path segment.¶
Servers MAY also accept an opaque server-assigned
id as an alias. If they do, the Admin Document MUST
still include the entity_id member, and listing
responses MUST include both identifiers.¶
JSON Web Key kid values used as path segments MUST be
percent-encoded.¶
The Administration API MUST be served over HTTPS [RFC9110]. Servers and clients MUST verify TLS server identity as specified in [RFC9525].¶
Every request except OPTIONS CORS preflight (if
offered) MUST be authenticated. This specification does not
mandate a single authentication scheme. Servers MUST support at
least one of:¶
Servers MAY additionally support mutual TLS or HTTP Basic authentication for constrained deployments. Servers MUST NOT accept unauthenticated mutating requests.¶
Authorization — which operators may create subordinates, rotate keys, or issue Trust Marks — is out of scope. Deployments SHOULD apply least-privilege roles and SHOULD record an audit trail of mutating requests.¶
Unless a section specifies otherwise:¶
application/json [RFC8259].¶
PATCH requests use
application/merge-patch+json
[RFC7396].¶
application/entity-statement+jwt
[OIDF.Federation].¶
application/trust-mark+jwt
[OIDF.Federation].¶
application/problem+json
[RFC9457] (Section 15).¶
Except in JSON Merge Patch request bodies
([RFC7396]), Admin Documents, Key Documents,
list responses, and error bodies MUST NOT use the JSON value
null. A member that does not apply is omitted. This
matches the prohibition on null in Entity metadata
([OIDF.Federation], Section 5).¶
Admin Documents MAY contain the following members in addition to the OpenID Federation claims of the corresponding artifact. These members MUST NOT appear in published Entity Statements or Trust Marks.¶
pending, active, suspended,
or revoked. Default active. For keys:
one of active, retiring, or
revoked. See Section 9.3.¶
exp claim of the next signed
artifact. If omitted, the server uses a locally configured
default.¶
If-Match on subsequent writes.¶
Unknown members that are not OpenID Federation claims and
are not defined here MUST be ignored on read and MUST be
preserved across PATCH if the server stored them,
unless the patch sets the member to null.¶
status controls Protocol Plane visibility. A
Subordinate Statement or Trust Mark MUST NOT be published
until live verification has succeeded
(Section 9.8).¶
pending.¶
federation_list_endpoint and are returned by
federation_fetch_endpoint. Trust Marks are issued
and validate at
federation_trust_mark_status_endpoint. Keys with
active status are eligible for signing and appear
in the published jwks.¶
active republishes it after live verification.¶
PUT or POST with the same
identifier is a new object, not a resurrection of the
revoked one. Servers MAY retain revoked records for audit.¶
pending --> active <--> suspended
| | |
+------> revoked <------+
pending and suspended MAY transition to
active only after live verification succeeds.
revoked MUST NOT return to pending,
active, or suspended. DELETE is
equivalent to transitioning to revoked and then
removing the record from ordinary list results. Servers MAY
keep pending or revoked objects visible in list
results when the client passes the corresponding
status query.¶
OpenID Federation 1.1 does not define a revocation protocol ([OIDF.Federation], Section 11.4). Status is an administration control that causes the node to stop publishing the corresponding artifact so that Trust Chains expire or fail to refresh.¶
Servers MUST return an ETag header on every
successful GET, PUT, POST, and PATCH of an Admin Document.
Clients SHOULD send If-Match on PUT, PATCH, and
DELETE. If If-Match does not match the current
revision, the server MUST return
412 Precondition Failed.¶
List endpoints return:¶
{
"items": [
{
"entity_id": "https://op.example.org",
"status": "active"
}
],
"next": "LjI"
}¶
limit (query, positive integer) is OPTIONAL.
Servers MUST honor values up to an implementation-defined
maximum and MUST NOT return more items than requested.
cursor (query, string) is OPTIONAL and continues a
previous page. When no further page exists, the
next member is omitted.¶
List endpoints MAY support:¶
PATCH uses JSON Merge Patch
[RFC7396]. A member set to null is
deleted. Arrays are replaced, not merged. To change one
element of authority_hints or trust_marks,
the client sends the complete replacement array.¶
OpenID Federation objects such as metadata,
metadata_policy, and constraints are JSON
objects and therefore merge recursively. This is the intended
way to change a single metadata parameter or a single policy
operator.¶
On every write of an Admin Document the server MUST validate that the OpenID Federation claims would produce a syntactically valid artifact under [OIDF.Federation]:¶
metadata_policy (Section 6.1) and
constraints (Section 6.2).¶
The server MUST reject writes that violate those rules with
400 and problem type
invalid_federation_claim
(Section 15). The server MUST NOT accept
iss or sub values that conflict with the
node's Entity Identifier or the subordinate's
entity_id. The server assigns iss,
sub, iat, and exp when it signs.¶
The server MUST reject a Leaf configuration that includes
federation_fetch_endpoint or
federation_list_endpoint, and MUST reject a Superior
configuration that omits them, consistent with Section 5.1.1
of [OIDF.Federation].¶
Claim validation (Section 9.7) is not enough to add another Entity to the federation. A write that would publish a Subordinate Statement or issue a Trust Mark MUST also live-check the subject before the Protocol Plane changes. Keys are local to the node: generate and import validate the public JWK and MUST NOT publish private material; they have no remote subject to fetch.¶
The server MUST perform live verification when any of the following holds:¶
status is active and the
object was not already active (create, or
transition from pending or suspended).¶
status is active and the
write changes a subordinate's entity_id or
jwks.¶
status active.¶
A metadata-only change to an already-active subordinate does not require a new live check. Claim validation still applies.¶
Subordinate live verification: the server MUST fetch the
subject's Entity Configuration and verify that the
presented jwks matches the subject's Federation
Entity Keys and that the node's Entity Identifier appears
in the subject's authority_hints.
naming_constraints and
allowed_entity_types MUST still be applied when
present.¶
Trust Mark grant live verification: the server MUST verify that a Trust Chain to the subject can be constructed under at least one Trust Anchor this node trusts.¶
On failure, including when the subject cannot be reached,
the server MUST return 422 with problem type
subject_mismatch and MUST NOT publish or replace
the Protocol Plane artifact. A stored
pending or suspended document is left
unchanged.¶
Query parameter verify and body member
verify have the same meaning. They default to
true. If both are present they MUST agree.
verify=false is accepted only when the resulting
status is not active; otherwise the
server MUST return 400 with problem type
invalid_request.¶
If the subject is not yet online, the operator writes
status pending. The document is stored
and MUST NOT be published. jwks MAY be omitted
while pending and is REQUIRED when the subordinate becomes
active. The later transition to active
MUST live-verify.¶
Returns the node's identity and capabilities.¶
Response 200:¶
{
"entity_id": "https://ta.example.org",
"roles": ["trust_anchor", "trust_mark_issuer"],
"base": "/admin/v1",
"spec": "draft-kodden-oidfed-admin-00",
"signing_kid": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
"implementation": {
"name": "example-node",
"version": "1.4.2"
},
"capabilities": {
"keys": ["list", "create", "rotate", "delete"],
"configuration": ["read", "replace", "patch"],
"subordinates": ["list", "create", "read", "replace",
"patch", "delete", "status", "statement"],
"trust_marks": ["list", "create", "read", "replace",
"delete", "grant", "status", "token"]
}
}¶
roles MUST be consistent with the Entity Types
present in the published Entity Configuration.
capabilities lists the operations the server
implements for each resource. Clients MUST treat a missing
resource key as "not implemented".¶
GET {base} is the capability discovery document.
There is no separate /capabilities resource.¶
Federation Entity Keys are the keys whose public halves appear
in the jwks claim of the node's Entity Configuration
as a JSON Web Key Set [RFC7517] and that sign
Entity Statements and Trust Marks as JSON Web Signatures
[RFC7515]
([OIDF.Federation], Sections 3.1.1 and 7).
Entity Statements and Trust Marks are JWTs
[RFC7519].
Protocol keys carried under Entity Type metadata are not
managed here; they are ordinary members of metadata.¶
{
"kid": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
"status": "active",
"signing": true,
"alg": "ES256",
"kty": "EC",
"public_jwk": {
"kty": "EC",
"crv": "P-256",
"kid": "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs",
"x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
},
"created_at": 1756454400
}¶
kid SHOULD be the JWK Thumbprint using SHA-256
[RFC7638], as recommended by
[OIDF.Federation]. public_jwk MUST
contain only public members. Private key material MUST NOT
appear in any Administration API response.
not_after is an OPTIONAL expiration time in
seconds since the epoch. If the key does not expire, the
member is omitted.¶
status for keys is active,
retiring, or revoked:¶
active — present in the published jwks;
eligible to become the signing key.¶
retiring — present in the published
jwks; MUST NOT be newly selected as the signing
key. It MAY remain the signing key until a rollover
switch completes (Section 11.6). Used during
rollover ([OIDF.Federation], Section 11.2).¶
revoked — absent from the current jwks;
MAY appear at
federation_historical_keys_endpoint.¶
Exactly one key is the node's signing key at any time, or
none if no signing-capable key exists. signing is
true on that Key Document. The Node document's
signing_kid is that key's kid, and is
omitted when none exists.¶
If several keys are active and signing-capable, the
server MUST choose exactly one as the signing key. It is
RECOMMENDED that this be the most recently created such key.
Clients MUST read signing_kid or signing
rather than inferring from status alone.¶
Returns a page of Key Documents. Query status MAY
filter the list.¶
Creates a key. The request is one of two shapes. Generate (server holds the private key):¶
{
"generate": {
"kty": "EC",
"crv": "P-256",
"alg": "ES256"
}
}¶
Import (private key is held elsewhere; only the public JWK is registered):¶
{
"import": {
"kty": "EC",
"crv": "P-256",
"x": "...",
"y": "...",
"alg": "ES256"
}
}¶
Response 201 with the Key Document and a
Location header. The new public JWK MUST appear in
the next published Entity Configuration jwks.¶
A newly created key that the server can sign with becomes
the signing key if none exists; otherwise it is
active with signing false. If the node
has no signing-capable active key after this
request, the server MUST still accept an import, but
requests that require a signature MUST return 409
with problem type not_initialized until a signing
key is available.¶
Returns the Key Document. 404 if unknown.¶
Transitions the key to revoked and removes it from
the published jwks. The server MUST reject the
request with 409 and problem type
last_signing_key if this is the last
active or retiring key that can sign.¶
If the deleted key was the signing key and another
signing-capable active key exists, the server MUST
select a replacement (RECOMMENDED: the most recently
created) and update signing_kid.¶
Performs a Federation key rollover for {kid} as
specified in [OIDF.Federation], Section 11:¶
POST {base}/keys).¶
jwks with
status=active.¶
status to retiring.¶
signing
true, status retiring) until an OPTIONAL
switch_after (seconds) elapses, or until the
server applies a local switch if switch_after is
omitted or zero. After the switch the new key has
signing true and the old key is
retiring with signing false. The client
MAY later DELETE the old key.¶
{
"generate": { "kty": "EC", "crv": "P-256", "alg": "ES256" },
"switch_after": 86400
}¶
Response 201 with the new Key Document. The old key
remains addressable at its original {kid}.¶
The Entity Configuration Admin Document is the
operator-editable content of the node's self-signed Entity
Statement. The server supplies iss, sub,
iat, exp, and jwks when it signs.
The operator supplies the remaining Entity Configuration
claims.¶
{
"entity_id": "https://ta.example.org",
"lifetime": 86400,
"authority_hints": [],
"metadata": {
"federation_entity": {
"organization_name": "Example Trust Anchor",
"federation_fetch_endpoint": "https://ta.example.org/fetch",
"federation_list_endpoint": "https://ta.example.org/list",
"federation_trust_mark_status_endpoint":
"https://ta.example.org/trust-mark-status"
}
},
"trust_marks": [],
"trust_mark_issuers": {
"https://ta.example.org/marks/research": [
"https://ta.example.org"
]
},
"trust_mark_owners": {}
}¶
Members authority_hints,
trust_anchor_hints, metadata,
trust_marks, trust_mark_issuers,
trust_mark_owners, and crit have the
meanings and constraints of
[OIDF.Federation], Sections 3.1.1 and 3.1.2.¶
trust_marks lists Trust Marks the node holds about
itself. The server MUST copy these objects unchanged into
the published Entity Configuration. It MUST NOT resign
another issuer's Trust Mark.¶
trust_mark_issuers and trust_mark_owners
are meaningful only on a Trust Anchor. Servers MUST reject
them on a node whose roles do not include
trust_anchor.¶
A Leaf or Intermediate MUST include a non-empty
authority_hints array. A Trust Anchor with no
Superior MUST omit authority_hints from the
published Entity Configuration.¶
Returns the Configuration Document.¶
Replaces the Configuration Document. Omitted optional
members are cleared. Response 200. The server MUST
NOT allow entity_id to change after initialization
(Section 4). If entity_id is not
yet set, this request MAY establish it.¶
Merge-patches the Configuration Document. Response 200.¶
Returns the currently published Entity Configuration JWT
with Content-Type: application/entity-statement+jwt.
This MUST be byte-for-byte the document served at
/.well-known/openid-federation.¶
The Subordinates resource is implemented by Trust Anchors and
Intermediate Entities. Leaf nodes MUST return 404
with problem type unsupported_resource for every path
under {base}/subordinates.¶
A Subordinate Admin Document is the operator-editable content of the Subordinate Statement the node will sign about one Immediate Subordinate.¶
{
"entity_id": "https://op.example.org",
"status": "active",
"lifetime": 86400,
"jwks": {
"keys": [
{
"kty": "EC",
"crv": "P-256",
"kid": "op-fed-1",
"x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
}
]
},
"metadata": {
"openid_provider": { "organization_name": "Example University" }
},
"metadata_policy": {
"openid_relying_party": {
"id_token_signed_response_alg": {
"default": "ES256",
"one_of": ["ES256", "ES384", "ES512"]
}
}
},
"constraints": {
"max_path_length": 1,
"naming_constraints": { "permitted": [".example.org"] },
"allowed_entity_types": [
"openid_provider",
"openid_relying_party"
]
}
}¶
jwks is REQUIRED for an active subordinate
and is the subject's Federation Entity Keys. It MAY be
omitted while status is pending. The
server assigns iss, sub, iat,
and exp when it signs. The server MAY add
source_endpoint set to its
federation_fetch_endpoint.¶
Returns a page of Subordinate Documents. Default filter is
status=active. Servers SHOULD omit jwks
from list items unless the client passes
detail=full.¶
Creates a subordinate. entity_id is REQUIRED.
Response 201. If a non-revoked subordinate with
the same entity_id exists, the server MUST return
409 with problem type already_exists.
Live verification (Section 9.8) applies.
To register a subject that is not yet online, set
status to pending.¶
Read, replace, merge-patch, or revoke the Subordinate
Document. PATCH is the compact replacement for the
per-claim URLs used in [Sphereon.Admin] and
[GEANT.Admin]. Replace and merge-patch
follow Section 9.8.¶
Sets status without a full document write. Body:
{ "status": "suspended" }. The server MUST enforce
Section 9.3. A transition to active
MUST live-verify (Section 9.8).¶
Returns the currently published Subordinate Statement JWT.
This MUST be byte-for-byte the document the node's
federation_fetch_endpoint returns for that subject
when status is active. Otherwise 404 with
problem type not_published.¶
The Trust Marks resource is implemented by Trust Mark Issuers.
Other nodes MUST return 404 with problem type
unsupported_resource for every path under
{base}/trust-marks.¶
This resource manages Trust Marks this node issues to
subjects. Recognition claims
(trust_mark_issuers, trust_mark_owners) and
Trust Marks this node holds about itself
(trust_marks) are Configuration Document members
(Section 12).¶
{
"trust_mark_type": "https://ta.example.org/marks/research",
"lifetime": 31536000,
"logo_uri": "https://ta.example.org/marks/research.png",
"ref": "https://ta.example.org/marks/research/policy"
}¶
trust_mark_type MUST be a collision-resistant
identifier as specified in
[OIDF.Federation], Section 7.1.
logo_uri, ref, and delegation
(when present) are copied into issued Trust Marks.¶
{
"entity_id": "https://op.example.org",
"trust_mark_type": "https://ta.example.org/marks/research",
"status": "active",
"iat": 1756458000,
"exp": 1787994000
}¶
When status is active, the node MUST issue
a Trust Mark JWT whose claims follow Section 7.1 of
[OIDF.Federation], typed
trust-mark+jwt, and signed with a Federation
Entity Key. When status is pending,
suspended, or revoked,
federation_trust_mark_status_endpoint MUST report
the mark as inactive.¶
GET/POST {base}/trust-marks lists and creates
Issuance Documents. GET/PUT/DELETE
{base}/trust-marks/{type} reads, replaces, or revokes
a type (revoking a type revokes every grant under it).¶
GET {base}/trust-marks/{type}/subjects lists
grants. PUT .../subjects/{entity_id} creates or
replaces a grant. DELETE revokes it.
PUT .../status sets grant status.
GET .../token returns the issued JWT with
Content-Type: application/trust-mark+jwt when the
grant is active.¶
Live verification (Section 9.8) applies to
grant create, replace, and a status transition to
active. To grant a mark to a subject that is not
yet online, set status to pending.¶
Error responses MUST use HTTP status codes consistently with [RFC9110] and a [RFC9457] body:¶
{
"type":
"urn:ietf:params:oidfed:admin:problem#invalid_federation_claim",
"title": "Invalid federation claim",
"status": 400,
"detail": "authority_hints must not be empty on a leaf node",
"pointer": "/authority_hints"
}¶
pointer is an OPTIONAL JSON Pointer to the offending
member.¶
| Token | Status | Meaning |
|---|---|---|
invalid_request
|
400 | Malformed JSON or missing required member |
invalid_federation_claim
|
400 | Claim violates [OIDF.Federation] |
unsupported_media_type
|
415 | Wrong Content-Type |
unauthorized
|
401 | Missing or invalid authentication |
forbidden
|
403 | Authenticated but not permitted |
not_found
|
404 | Unknown resource or identifier |
unsupported_resource
|
404 | Resource not implemented for this node role |
not_published
|
404 | Configured but not currently published |
already_exists
|
409 | Identifier already in use |
last_signing_key
|
409 | Would remove the last usable signing key |
not_initialized
|
409 | Entity Identifier or signing key not yet set |
conflict
|
409 | Other conflicting state |
precondition_failed
|
412 |
If-Match did not match |
subject_mismatch
|
422 | Live verification failed or subject unreachable |
internal
|
500 | Unspecified server failure |
The type URI is formed by appending # and
the token to urn:ietf:params:oidfed:admin:problem
(Section 20).¶
This section is normative regarding consistency and
informative regarding existing products. OpenID Federation
1.1 [OIDF.Federation] is the
protocol-independent split of OpenID Federation 1.0. It
introduces no new federation mechanisms. OpenID Connect and
OAuth metadata types used in examples
(openid_provider, openid_relying_party)
are defined in [OIDF.Connect].¶
| Admin resource | Protocol artifact | OIDFed section |
|---|---|---|
| Configuration | Entity Configuration JWT | 3, 9 |
| Keys |
jwks; historical keys endpoint |
3.1.1, 8.7, 11 |
| Subordinate | Subordinate Statement JWT from fetch | 3, 8.1 |
| Subordinate list |
federation_list_endpoint
|
8.2 |
| Trust Mark grant | Trust Mark JWT; status and list endpoints | 7, 8.4–8.6 |
trust_mark_issuers
|
Claim on Trust Anchor Entity Configuration | 3.1.2, 7 |
metadata_policy
|
Claim on Subordinate Statement | 6.1 |
constraints
|
Claim on Subordinate Statement | 6.2 |
A node that implements this API MUST still implement the Protocol Plane required by its roles. Implementing this API does not satisfy any Protocol Plane requirement.¶
[Sphereon.Admin], [GEANT.Admin], and the OpenAPI contract shipped with [Gateway.Admin] expose a large set of nested resources that map onto the documents in this specification: entity-configuration metadata, authority hints, and published JWKS collapse to Section 12 plus Section 11; per-subordinate metadata, policy, constraints, and JWKS collapse to Section 13; trust-mark types, issuance specs, and subjects collapse to Section 14. Control-plane products such as [SURF.OIDFed] and [Gateway.Admin] sit above this API.¶
The Administration API and the Protocol Plane MAY share an origin or MAY use distinct origins. Distinct origins are RECOMMENDED so that operator credentials never appear on the host that federation participants contact.¶
When origins differ, the Entity Identifier remains the Protocol Plane identifier. The Administration API base URL is local configuration. It MUST NOT be published in Entity Configuration metadata.¶
A control plane that manages several nodes MUST address each Administration Server separately. This document does not define a multi-node collection resource.¶
Servers SHOULD emit structured audit records for every mutating request, as specified in Section 18.10. This document does not define an Administration API resource for querying or managing those records.¶
The Administration API can change the trust fabric of a federation. Compromise of Administration API credentials is equivalent to compromise of the node's Federation Entity Keys for the purpose of issuing statements the rest of the federation will accept.¶
Unauthenticated access MUST NOT be permitted. Bearer tokens MUST be sender-constrained or short-lived. Deployments SHOULD use mutual TLS or demonstration of proof-of-possession for operator credentials that can rotate keys or create subordinates. Separating "read configuration", "manage subordinates", "issue Trust Marks", and "rotate keys" is RECOMMENDED.¶
If a browser-based operator interface is used, the
Administration Server is a confidential backend-for-frontend
concern. Browser clients MUST NOT be given long-lived
node-admin credentials. Servers that offer CORS for a
first-party UI MUST enumerate explicit origins and MUST NOT
use *.¶
Bearer tokens that are not sender-constrained can be
replayed until they expire. Servers MUST reject expired
credentials. Clients SHOULD send If-Match on writes
(Section 9); a replayed PUT or
PATCH whose If-Match no longer matches
MUST fail with 412.¶
If a deployment authenticates operators with cookies or other automatically attached credentials, it MUST implement cross-site request forgery defenses (for example a synchronized token or a custom request header that is not sent cross-origin). This document specifies Bearer tokens. Cookie sessions are not required and are NOT RECOMMENDED for the Administration API.¶
Every written claim is copied into a signed JWT that third
parties will cache and apply as policy. Servers MUST treat
Admin Document fields as untrusted input: reject unexpected
types, reject null inside metadata objects
([OIDF.Federation], Section 5), enforce URI
syntax for Entity Identifiers and endpoints, and enforce
https for federation endpoint URLs.¶
A write that sets entity_id on a Subordinate
Document or a Trust Mark grant is an assertion that the
identified Entity is that subject. An Immediate Superior
that publishes a Subordinate Statement binds the subject's
Entity Identifier to the jwks in that document.
Live verification (Section 9.8) MUST
succeed before that binding is published.
verify=false MUST NOT result in an
active object. pending stores the
document without publishing it.¶
A successful live check only shows that the subject
currently publishes matching jwks and
authority_hints, or that a Trust Chain can be
built. It is not a proof of organizational control.
naming_constraints and
allowed_entity_types MUST still be applied when
present.¶
Private keys MUST NOT be exported through this API. Key rollover MUST keep the retiring public key published long enough for relying parties to refresh Entity Configurations ([OIDF.Federation], Section 11.2). Deleting the last signing key is rejected because it would freeze the Protocol Plane.¶
Live verification fetches a subject's Entity
Configuration. Servers MUST apply SSRF controls:
allow only https, deny private and link-local
addresses unless explicitly configured, cap redirect hops,
and cap response size.¶
Servers SHOULD rate-limit mutating requests,
verify fetches, and expensive reads
(detail=full and unfiltered lists). A client that
can create subordinates or Trust Marks can otherwise exhaust
storage and signing capacity. Unbounded list responses and
repeated verify against slow or large Entity
Configurations are denial-of-service vectors even for
authenticated readers. Pagination
(Section 9) is not optional for large
collections if the server cannot bound the result set.¶
OpenID Federation 1.1 does not define a revocation protocol
([OIDF.Federation], Section 11.4). Setting
status to suspended or revoked,
or deleting a subordinate or Trust Mark grant, only stops
this node from publishing the corresponding artifact.
Relying parties continue to accept cached Entity Statements
and Trust Marks until those artifacts expire or the relying
party refreshes the Trust Chain. Operators MUST choose
lifetime values that match how quickly the
federation needs a withdrawal to take effect.
DELETE is not instant global revocation.¶
Administration actions SHOULD be attributable to an operator
identity distinct from the node's Federation Entity
Identifier. Audit logs are the primary record of who changed
the trust fabric; Entity Statement iat values
alone are not sufficient.¶
This document does not define an audit-log resource. Query, retention, and export to a SIEM or other archive are deployment concerns, typically implemented by a control plane rather than by the node.¶
A server SHOULD record at least the following for every mutating request:¶
subordinates.replace);¶
entity_id,
trust_mark_type, or kid, as applicable);¶
etag or a hash of the previous Admin
Document;¶
Privileged read operations MAY be recorded. Servers MUST NOT write private key material or access tokens into the audit trail. Request and response bodies MAY be stored in redacted form.¶
The Administration API MUST NOT provide a means to delete or rewrite audit records. Retention period and archival policy are local matters.¶
If a control plane proxies this API, the node still SHOULD emit its own records. When it does not, the operator MUST designate exactly one authoritative trail so that a change cannot occur without a durable attribution.¶
The Administration API handles identifiers and metadata that often relate to organizations and, in audit logs, to individual operators. This section follows the guidance of [RFC6973].¶
Entity Identifiers, organization_name,
logo_uri, and similar metadata members are published
on the Protocol Plane once written. Operators MUST treat Admin
Document writes as publication. Contact addresses and other
optional metadata SHOULD be limited to what the federation
policy requires.¶
Trust Marks bind an accreditation statement to an Entity Identifier. Issuing or revoking a mark is visible to any party that can query the issuer's Trust Mark status endpoint.¶
Audit records contain operator identities distinct from the node's Entity Identifier (Section 18.10). Those records MUST be access-controlled independently of the Protocol Plane and SHOULD NOT be written to the same log streams that serve public federation endpoints. Retention of operator identifiers is a local matter. Servers MUST NOT copy operator identities into Entity Statements or Trust Marks.¶
Because the Administration API is confidential, responses MUST NOT be cached by shared caches. Distinct Administration and Protocol Plane origins (Section 17) reduce the risk that a browser or intermediary mixes the two.¶
This document makes no Well-Known URI registration. The
Administration API is not discovered via
/.well-known/openid-federation.¶
IANA is requested to register the following value in the "IETF URN Sub-namespace for Registered Protocol Parameter Identifiers" registry established by [RFC3553]:¶
urn:ietf:params:oidfed:admin¶
Problem-type tokens in Section 15 are relative
to urn:ietf:params:oidfed:admin:problem.¶
This appendix shows a Trust Anchor admitting an OpenID Provider and issuing a Trust Mark. Host names and keys are illustrative.¶
The server live-verifies the subject's Entity Configuration
before publishing (Section 9.8). If the
subject were not yet online, the body would include
"status": "pending" and the Protocol Plane would
not change.¶
The following operations are all of the protocol operations.
Feature subsets are expressed only by omitting keys from
capabilities. A Leaf implements the Node, Keys, and
Configuration operations (ten). A Trust Anchor that also
issues Trust Marks implements all twenty-eight. Paths in the
catalog are relative to {base}.¶
| Method | Path | Operation |
|---|---|---|
| GET |
/
|
node.read
|
| GET |
/keys
|
keys.list
|
| POST |
/keys
|
keys.create
|
| GET |
/keys/{kid}
|
keys.read
|
| DELETE |
/keys/{kid}
|
keys.delete
|
| POST |
/keys/{kid}/rotate
|
keys.rotate
|
| GET |
/configuration
|
configuration.read
|
| PUT |
/configuration
|
configuration.replace
|
| PATCH |
/configuration
|
configuration.patch
|
| GET |
/configuration/statement
|
configuration.statement
|
| GET |
/subordinates
|
subordinates.list
|
| POST |
/subordinates
|
subordinates.create
|
| GET |
/subordinates/{entity_id}
|
subordinates.read
|
| PUT |
/subordinates/{entity_id}
|
subordinates.replace
|
| PATCH |
/subordinates/{entity_id}
|
subordinates.patch
|
| DELETE |
/subordinates/{entity_id}
|
subordinates.delete
|
| PUT |
/subordinates/{entity_id}/
|
subordinates.status
|
| GET |
/subordinates/{entity_id}/
|
subordinates.statement
|
| GET |
/trust-marks
|
trust_marks.list
|
| POST |
/trust-marks
|
trust_marks.create
|
| GET |
/trust-marks/{type}
|
trust_marks.read
|
| PUT |
/trust-marks/{type}
|
trust_marks.replace
|
| DELETE |
/trust-marks/{type}
|
trust_marks.delete
|
| GET |
/trust-marks/{type}/subjects
|
trust_marks.subjects.list
|
| PUT |
/trust-marks/{type}/subjects/
|
trust_marks.grant
|
| DELETE |
/trust-marks/{type}/subjects/
|
trust_marks.revoke
|
| PUT |
/trust-marks/{type}/subjects/
|
trust_marks.status
|
| GET |
/trust-marks/{type}/subjects/
|
trust_marks.token
|
This document draws operational experience from the Sphereon OpenID Federation Admin Server, the GÉANT Trust and Identity Incubator Federation Admin API, the Federation Gateway project, and the SURF OpenID Federation control plane and node implementations. The data model is that of OpenID Federation 1.1; any elegance in this API comes from not inventing another one.¶