Operate a federation
A tenant can run a federation of its own, as its Trust Anchor, or act as an intermediate inside someone else's federation and vouch for its own departments, resources and partners. In both roles the tenant publishes an authority entity, admits members by signing Subordinate Statements about them, and serves the federation endpoints that verifiers and members call. Read OpenID Federation for the model first.
Every operation below is in the OpenID Federation API.
Paths are relative to /api/platform/config/v1, and changes to an existing record require If-Match
with its current version.
Who may operate a federation
An organization that acts as an intermediate needs no special permission: owning the organization is
what allows it to sign statements about the entities below it. Running a federation as its Trust Anchor
is different, because it decides who may join at all. The platform has to entitle the tenant to do so;
without that entitlement an entity with authority kind ROOT cannot be published. The VDX platform adds
this entitlement as a tenant setting, together with console screens for hosted federations and recurring
renewal.
Credential issuers, verifiers and authorization servers are always leaves. Only organization entities can be authorities.
Publish the Trust Anchor
A federation the tenant operates is a federation context whose expected Trust Anchor is one of the
tenant's own ROOT entities, bound to the tenant's organization. A tenant can operate several
federations, each with its own anchor entity and Entity Identifier.
- Create the anchor entity with authority kind
ROOT(createOpenIdFederationEntity) and bind the organization to it (createOpenIdFederationBinding). - Create a Federation Entity Key and select it (
createOpenIdFederationEntityKey,selectOpenIdFederationEntitySigningKey). The anchor's keys are what every member and verifier trusts in the end, so choose the algorithm deliberately and keep the key in a KMS you control. - Create the federation context with the anchor's Entity Identifier as its only expected Trust Anchor
(
createOpenIdFederationContext), and add the anchor entity to it as a participation (createOpenIdFederationParticipation). Local entities that sign statements in this federation must themselves take part in it. - Publish the anchor's Entity Configuration with
POST /tenants/{tenantId}/openid-federation/entities/{entityId}/publish(publishOpenIdFederationEntity).
The published Entity Configuration of an authority lists, under its federation_entity metadata, the
endpoints it serves: federation_fetch_endpoint, federation_list_endpoint,
federation_resolve_endpoint, federation_trust_mark_status_endpoint,
federation_trust_mark_list_endpoint, federation_trust_mark_endpoint and
federation_historical_keys_endpoint (OpenID Federation 1.1 §5.1.1). Each is a path below the entity's
own Entity Identifier, such as <Entity Identifier>/federation_fetch.
Give relying parties the anchor's Entity Identifier, and if they want to pin keys, the anchor's key ids through a separate channel. Everyone else needs nothing more, because anchor keys are read from the anchor's Entity Configuration.
Running an intermediate
An intermediate is an organization entity with authority kind INTERMEDIATE. It joins its federation
like any participant, as described in Join an existing federation, and admits
members exactly like an anchor does. Its own departments and resources are declared as LOCAL
subordinates under it, and partners as EXTERNAL subordinates. Constraints in its superior's statement,
such as max_path_length, limit how deep it may delegate.
Admit members
Admission means signing a Subordinate Statement about the member. The statement says which keys the superior vouches for, so the operator must have reviewed those keys before anything is signed.
First declare the member under the authority with
POST /tenants/{tenantId}/openid-federation/superiors (createOpenIdFederationSuperior). The superior
side is your LOCAL authority entity. The subordinate side is another local entity or an EXTERNAL
entity named by its Entity Identifier. For an external member, take the Entity Identifier and key ids
from the onboarding details the member sent you.
Then preview the statement with
GET /tenants/{tenantId}/openid-federation/superiors/{edgeId}/statement/preview
(previewOpenIdFederationSubordinateStatement). The preview reads the member's current keys from its
own Entity Configuration, either the local publication or the document at the member's well-known URL,
and returns them with a fingerprint. Compare the key ids with the ones the member gave you out of band.
This comparison is the admission decision.
Sign with POST /tenants/{tenantId}/openid-federation/superiors/{edgeId}/statement
(publishOpenIdFederationSubordinateStatement, with If-Match on the relationship). The request repeats
the fingerprint you reviewed as expectedSubjectKeysFingerprint. If the member's keys changed after the
preview, the fingerprints differ and nothing is signed, so changed keys are never signed unreviewed. The
request can add statement metadata per Entity Type and constraints such as max_path_length,
naming_constraints and allowed_entity_types (OpenID Federation 1.1 §6.2). The statement is signed
with the authority's selected key and served from its fetch endpoint at once.
GET /tenants/{tenantId}/openid-federation/entities/{entityId}/subordinates
(listOpenIdFederationSubordinateStatements) lists the statements an authority serves. To remove a
member, end the superior relationship (endOpenIdFederationSuperior). Renewal only covers live
relationships, so the member's statement is no longer renewed; a statement that is already signed stays
valid until it expires, which is one reason to keep the statement lifetime short.
Many organizations want a review step around admission. See Workflow steps.
Metadata policies
A metadata policy lets the authority constrain what its subordinates may publish for an Entity Type,
for example the allowed signing algorithms of relying parties or a fixed contacts value
(OpenID Federation 1.1 §6.1). Policies are set per Entity Type with
PUT /tenants/{tenantId}/openid-federation/entities/{entityId}/policies/{entityType}
(setOpenIdFederationMetadataPolicy) and read with getOpenIdFederationMetadataPolicies. A null
policy removes it.
The standard operators are available: value, add, default, one_of, subset_of,
superset_of and essential. The policy is validated when it is stored, so a malformed operator is rejected immediately instead of
breaking chain resolution for members later. A stored policy is signed into every Subordinate Statement the authority issues from then
on. Verifiers combine the policies of all superiors in a chain when they resolve a member's metadata.
Trust Marks
A Trust Mark is a signed statement that an entity meets some requirement, such as a certification or a membership level (OpenID Federation 1.1 §7). The Trust Anchor decides which Trust Mark types exist in its federation.
Define a type with POST /tenants/{tenantId}/openid-federation/entities/{entityId}/trust-mark-types
(defineOpenIdFederationTrustMarkType). The type identifier is an https URL or a urn. The entity
becomes an issuer of that type, and its next published Entity Configuration lists the type under
trust_mark_issuers, so republish the anchor after defining types. listOpenIdFederationTrustMarkTypes
lists them and removeOpenIdFederationTrustMarkType stops issuing one.
Issue a Trust Mark with POST /tenants/{tenantId}/openid-federation/entities/{entityId}/trust-marks
(issueOpenIdFederationTrustMark), naming the type, the subject's Entity Identifier and a lifetime
between 60 seconds and two years. It is signed with the entity's selected key. The subject fetches it
from the Trust Mark endpoint, and anyone can check it at the Trust Mark status endpoint.
listOpenIdFederationTrustMarks lists what the entity issued, with ids.
Revoke with POST /tenants/{tenantId}/openid-federation/entities/{entityId}/trust-marks/{trustMarkId}/revoke
(revokeOpenIdFederationTrustMark). A Trust Mark is self-contained and cannot be recalled from the
places it was copied to, so revocation takes effect through the status endpoint: from then on it reports
the Trust Mark as revoked, and the Trust Marked entities listing, which only counts active Trust
Marks, no longer includes the subject for it.
Public endpoints
Each published entity serves its Entity Configuration at <Entity Identifier>/.well-known/openid-federation.
A published authority additionally serves the federation endpoints below, all without authentication and
at its own URL. They only ever answer about the authority's own subtree. Errors use the JSON format of
OpenID Federation 1.1 §8.9, with error and error_description; an unknown entity is 404 with
not_found and a missing or malformed parameter is 400 with invalid_request.
| Endpoint | Path below the Entity Identifier | Behavior |
|---|---|---|
| Fetch (§8.1) | GET /federation_fetch?sub= | The Subordinate Statement about sub, as application/entity-statement+jwt. |
| List (§8.2) | GET /federation_list | The Entity Identifiers of the immediate subordinates, as JSON. Filters: entity_type, intermediate, trust_marked, trust_mark_type. |
| Resolve (§8.3) | GET /federation_resolve?sub=&trust_anchor= | Resolved metadata and Trust Chain of an entity in this authority's subtree, as application/resolve-response+jwt. Optional entity_type. |
| Trust Mark status (§8.4) | POST /federation_trust_mark_status | Form parameter trust_mark. A signed status response (application/trust-mark-status-response+jwt) with status active, expired, revoked or invalid. |
| Trust Marked entities (§8.5) | GET /federation_trust_mark_list?trust_mark_type= | Entities holding an active Trust Mark of the type, as JSON. Optional sub. |
| Trust Mark (§8.6) | GET /federation_trust_mark?trust_mark_type=&sub= | The subject's current Trust Mark of the type, as application/trust-mark+jwt. |
| Historical keys (§8.7) | GET /federation_historical_keys | Keys the authority no longer uses, as a signed application/jwk-set+jwt. |
The Trust Mark filters on the list endpoint only know about Trust Marks this authority issued itself. Resolve is not an open discovery service: it answers only for entities inside the authority's own served subtree and refuses anything else.
Renewal
Every signed statement expires after the lifetime the deployment configures, one hour in the shipped deployments. A federation keeps working only if statements are signed again before they lapse.
POST /tenants/{tenantId}/openid-federation/publications/refresh
(refreshOpenIdFederationPublications) renews everything of the tenant that expires within
renewWithinSeconds. Entity Configurations are prepared again from current facts and signed. Subordinate
Statements are signed again only over the keys that were confirmed for them at admission. When a member
now publishes different keys, its statement is not renewed; the response lists it as a failure with code
KEYS_CHANGED, and the member has to be reviewed and signed again as described in
Admit members. The response lists what was renewed and every failure, so a caller can
alert on it.
The EDK enterprise images have no recurring scheduler. Call the refresh operation on a cadence shorter
than the statement lifetime from your own scheduling, or run it as a workflow step. The operation
PUT /tenants/{tenantId}/openid-federation/renewal-schedule
(ensureOpenIdFederationRenewalSchedule) registers a recurring renewal only where the platform provides
a scheduler, as the VDX platform does; the EDK services refuse it. Choose a window comfortably larger
than the interval between runs, so one missed run does not let statements expire.
Workflow steps
The federation operations are available as workflow steps in the workflow palette, under the category OpenID Federation:
oidfed.publish-entitypublishes an Entity Configuration;oidfed.publish-statementsigns a Subordinate Statement over a reviewed key fingerprint;oidfed.verify-superiorverifies admission through a superior;oidfed.issue-trust-markissues a Trust Mark;oidfed.refresh-publicationsrenews statements that expire soon.
Each step runs the same authorized operation as the API, with the same checks, so a workflow can put a
human approval, an enrollment form or a notification around an operation without opening a second path
to it. A typical admission workflow previews the member's keys, routes the fingerprint to an approver,
and then runs oidfed.publish-statement with the approved fingerprint. A renewal workflow runs
oidfed.refresh-publications and alerts on its failures.