OpenID Federation 1.0
OpenID Federation 1.0 (OIDF) replaces ad-hoc client registration with a JWS-signed delegation chain. Every entity in the federation publishes an *entity configuration* at (a self-signed JWT listing the entity's keys + metadata + which superiors are allowed to sign subordinate statements about it via authority_hints).
Each *intermediate* publishes *subordinate statements* signed over the entity directly below — these statements pin the subordinate's JWKS plus an optional metadata_policy that adjusts the subordinate's claimed metadata (default values, required claims, allowed-value sets, etc.). The *trust anchor* sits at the top — its public key is operator-configured (out-of- band, baked into the deployment).
The verifier walks: leaf entity-config → leaf's authority_hints → fetch subordinate-statement-about-leaf from each authority → verify the JWS using that authority's keys → ascend to that authority's entity config → repeat until a trust anchor is reached. The chain must close at a trust anchor; a chain that doesn't is refused.
Surface:
b.auth.openidFederation.parseEntityStatement(jwt) → claims b.auth.openidFederation.verifyEntityStatement(jwt, jwks) → claims b.auth.openidFederation.buildTrustChain({ leafEntityId, trustAnchors, fetcher? }) → [{jwt, claims, role}] (leaf-first) b.auth.openidFederation.applyMetadataPolicy(metadata, chain) → effective metadata b.auth.openidFederation.resolveLeaf({ leafEntityId, trustAnchors, ... }) → { effectiveMetadata, chain, trustAnchor }
The framework does NOT publish entity configurations — that's a route the operator's RP code stands up. Verification + chain construction is the framework's job; serving is operator-side.
Metadata-policy operators implemented (per OpenID Federation 1.0 §6.2): value, add, default, one_of, subset_of, superset_of, essential. Unknown operators refuse loudly so a misconfigured policy doesn't silently let unauthorized metadata through.
b.auth.openidFederation.parseEntityStatement(jwt) #
Decode (without verifying) an entity statement / configuration JWT and return its header + claims. Used to look up the right verification key BEFORE the signature check.
var parsed = b.auth.openidFederation.parseEntityStatement(entityConfigJwt);
// → { header: { typ, alg, kid }, claims: { iss, sub, iat, exp, jwks, ... } }
b.auth.openidFederation.verifyEntityStatement(jwt, jwks, vopts) #
{
maxClockSkewSec: number // tolerance for iat / exp; default: 60
now: number // override Date.now() for tests
}
Verify a single entity statement's JWS signature using the provided JWKS. Returns the parsed claims on success; throws on any failure (malformed / wrong typ / unsupported alg / no matching kid / bad signature / iat-future / expired).
var claims = b.auth.openidFederation.verifyEntityStatement(jwt, anchorJwks);
// → { iss, sub, iat, exp, jwks, metadata, authority_hints, ... }
b.auth.openidFederation.applyMetadataPolicy(metadata, chain, kind) #
Apply the federation's metadata_policy (top-down) to the leaf's declared metadata for the given entity-kind ("openid_relying_party" / "openid_provider" / "federation_entity" / etc.) and return the effective metadata. Throws on any policy violation.
Per OpenID Federation 1.0 §6.2, an entity's metadata_policy comes from the SUPERIOR-SIGNED subordinate statement about that entity (chain[i].subordinate.metadata_policy), NOT from the entity's own self-published configuration. An entity cannot self-declare the policy that constrains it — that would let a leaf widen or drop the trust anchor's value / subset_of / essential constraints. The leaf's own self-config metadata_policy is therefore ignored.
The chain is leaf-first; each chain[i].subordinate is the statement signed by the superior directly above entity i; every level's policy is merged into ONE combined policy so a subordinate can only NARROW a superior's constraint (a leaf-ward level pinning a different value/default refuses the chain as a trust downgrade), then applied once (OIDF 1.0 §6.1.5.3).
var effective = b.auth.openidFederation.applyMetadataPolicy(
leafClaims.metadata.openid_relying_party,
chain,
"openid_relying_party"
);
// → metadata with default / one_of / subset_of constraints applied
b.auth.openidFederation.buildTrustChain(opts) #
{
{
leafEntityId: string, // the entity to verify
trustAnchors: { [entityId]: jwks }, // operator-configured anchors
fetcher?: async fn(url)→jwt, // override the default httpClient fetch
fetchSubordinate?: async fn(authority, sub)→jwt, // optional explicit fetcher; default = `/fetch?iss=&sub=`
maxDepth?: number, // chain cap (default 10)
}
Returns `[{ jwt, claims, role }]` leaf-first. Each element has
`role` ∈ {"leaf", "intermediate", "trust_anchor"}.
}
Construct + verify a leaf-to-anchor trust chain.
var chain = await b.auth.openidFederation.buildTrustChain({
leafEntityId: "https://rp.example",
trustAnchors: { "https://anchor.example": anchorJwks },
});
// → [{ role: "leaf", ... }, { role: "intermediate", ... }, { role: "trust_anchor", ... }]
b.auth.openidFederation.resolveLeaf(opts) #
{
{
leafEntityId: string,
trustAnchors: { [entityId: string]: object },
kind: string, // e.g. "openid_relying_party"
fetcher?: async fn(url) -> jwt,
fetchSubordinate?: async fn(authority, sub) -> jwt,
maxDepth?: number,
}
}
One-shot helper: build the trust chain for a leaf entity, apply the federation's metadata policy, and return the effective metadata for the requested entity-kind (opts.kind — "openid_relying_party", "openid_provider", "federation_entity", "oauth_resource", etc.). Throws on any chain / policy failure.
var resolved = await b.auth.openidFederation.resolveLeaf({
leafEntityId: "https://rp.example",
trustAnchors: { "https://anchor.example": anchorJwks },
kind: "openid_relying_party",
});
// → { chain, trustAnchor, effectiveMetadata, leafEntityId }
Last updated 2026-08-08T16:39:49.652Z by seeder.