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 /.well-known/openid-federation (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) #

0.8.62

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) #

0.8.62
{
  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) #

0.8.62

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) #

0.8.62
{
    {
      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) #

0.8.62
{
  {
    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.