Skip to main content
Version: v0.25.0 (Latest)

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.

  1. Create the anchor entity with authority kind ROOT (createOpenIdFederationEntity) and bind the organization to it (createOpenIdFederationBinding).
  2. 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.
  3. 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.
  4. 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.

EndpointPath below the Entity IdentifierBehavior
Fetch (§8.1)GET /federation_fetch?sub=The Subordinate Statement about sub, as application/entity-statement+jwt.
List (§8.2)GET /federation_listThe 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_statusForm 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_keysKeys 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-entity publishes an Entity Configuration;
  • oidfed.publish-statement signs a Subordinate Statement over a reviewed key fingerprint;
  • oidfed.verify-superior verifies admission through a superior;
  • oidfed.issue-trust-mark issues a Trust Mark;
  • oidfed.refresh-publications renews 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.