@oidfed implementation overview & feedback

@oidfed

A complete OpenID Federation 1.0 implementation for JavaScript.

oidfed entity statement anatomy — header, claims, signature

@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Yamonwan Justin Dah-kenangnon

  • Background — Engineering graduate in Mathematics & Modelingsoftware engineer with a focus on identity and integration work
  • OIDC — integrations mostly built on Filip Skokan's node-oidc-providerdeploying real OPs and consuming them as RPs
  • Federation — came in cold to the OpenID Federation specthis implementation is the way I learned it — the source of today's feedback
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

What @oidfed is

  • @oidfed/coreEntity Statements, trust chain resolution, metadata policy, crypto verification
  • @oidfed/authorityTrust Anchor & Intermediate — subordinate mgmt, issuance, endpoints, policy
  • @oidfed/leafLeaf Entity toolkit — EC serving, authority discovery, chain participation
  • @oidfed/oidcOIDC / OAuth 2.0 flows — automatic & explicit registration, Request Object
  • @oidfed/cliResolve, fetch, validate, decode, sign — debug deployments from the terminal

Apps & resources

fed.oidfed.com

Reference federation deployment — six topologies built on the @oidfed packages, exercised end-to-end to validate spec compliance.

explore.oidfed.com

Browser-based federation explorer — paste any entity URL, render its trust chain, statements, and resolved metadata inline.

resources

learn.oidfed.com  ·  oidfed.com
course material and project home.

@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

What each library runs

Four spec packages  ·  roles in any federation

@oidfed/core

Foundation. Entity statements, trust-chain resolution, crypto, schemas, constants — every other package depends on it.

resolveTrustChainForAnchor  ·  generateSigningKey  ·  entityId(url)

@oidfed/authority

Runs Trust Anchors and Intermediates. All federation endpoints, subordinate management, key lifecycle, trust-mark issuance & status.

createAuthorityServer({…}).handler()

@oidfed/leaf

Any entity at the edge — OPs, RPs, RSs. Serves /.well-known/openid-federation, discovers and validates peers.

createLeafEntity({…}).handler()  ·  discoverEntity(id, anchors)

@oidfed/oidc

OIDC / OAuth 2.0 profile of federation. RP- and OP-side automatic & explicit registration, Request Object validation.

automaticRegistration  ·  processAutomaticRegistration  ·  explicitRegistration  ·  processExplicitRegistration

@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

The demo federation

Single-anchor topology  ·  what we will exercise live

Trust Anchor ta.single.fed.oidfed.com runs federation endpoints (fetch, list, resolve, trust-mark)
OP (leaf) op.single.fed.oidfed.com supports automatic & explicit client registration · ES256 · scopes openid profile email
RP1 (leaf) rp1.single.fed.oidfed.com client_registration_types: ["automatic"]
RP2 (leaf) rp2.single.fed.oidfed.com client_registration_types: ["explicit"]

Source: github.com/Dahkenangnon/fed-oidfed-com/blob/main/src/topologies/single-anchor.ts

@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Live demo

  1. rp1.single.fed.oidfed.comautomatic client registration
  2. rp2.single.fed.oidfed.comexplicit client registration
  3. explore.oidfed.com — the same federation, visualised
# Inspect any participant straight from the terminal — no install needed:
$ npx -y -p @oidfed/cli oidfed entity https://op.single.fed.oidfed.com
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Three pieces of feedback

From running the implementation

Item 1 §12.1.1.1.1 ·
request delivery

Embedded trust_chain did not fit the query carrier in our deployment — sharing what we saw.

Item 2 §6.2 ·
constraints side

Unknown constraint parameters are silently ignored — a gap compared to the metadata side.

Item 3 Runtime policy ·
when inputs change

Decisions whose inputs change between requests — sharing a need we ran into.

@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 1  ·  §12.1.1.1.1

Request delivery  ·  Observation & Description

Observation

In our deployment, an embedded trust_chain in the Request Object's JWS header pushes the ?request=<JWT> query carrier past common HTTP-intermediary defaults.

Description

A three-statement chain (Leaf + Intermediate + TA) is already 8–12 KB — past nginx's default proxy_buffer_size of 8 KB. The 502 fired on the smallest real federation, not on a deep edge case.

The spec already names the carriers that handle this in §12.1.1.1.1 — "… it may be necessary to use the HTTP POST method, a request_uri, or a Pushed Authorization Request [RFC 9126] for the request." In our deployment, that note turned out to describe the default path, not an edge case.
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 1  ·  §12.1.1.1.1

Request delivery  ·  Suggestion & Example

Suggestion

A clearer note on this — saying the query carrier is risky when trust_chain is embedded, and pointing readers to form_post, request_uri, or PAR — would save the next implementer the same 502.

No change to OIDC Core's request parameter; the carrier choice only matters when the chain is in the header.

Example

// Failing path
GET /authorize?request=<9KB JWT with trust_chain>
→ HTTP/1.1 502 Bad Gateway   (nginx proxy_buffer_size)
 
// Working path (form_post default in @oidfed/oidc@0.4.0)
POST /authorize  Content-Type: application/x-www-form-urlencoded
request=<same JWT>
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 2  ·  §6.2

Constraints-side parallel  ·  Observation & Description

Observation

§6.2 lets federations define custom constraint parameters and requires silent-ignore for unrecognised ones. There is no fail-closed equivalent on the constraint side.

Description

The metadata side already has metadata_policy_crit (§6.1.3.2) — a federation can mark a custom operator as required-to-understand, with chain invalidity as the failure mode.

On the constraint side there is no equivalent today. A verifier that hasn't implemented a custom constraint silently admits the chain, even when the federation operator considers that constraint essential.
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 2  ·  §6.2

Constraints-side parallel  ·  Suggestion & Example

Suggestion

A constraints_crit claim that mirrors metadata_policy_crit semantics would close this gap. One new claim, no change to existing ones.

Example

// Subordinate Statement
{
  "iss": "https://ta.regulated-fed.example",
  "sub": "https://intermediate.bank.example",
  "constraints": {
    "max_path_length": 2,
    "required_trust_marks_in_chain": ["https://.../audit-2026"]
  },
  "constraints_crit": ["required_trust_marks_in_chain"]
}
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 3  ·  runtime policy

When inputs change between requests  ·  Observation & Description

Observation

§6's extension points (operators, constraints) are designed to be distributed as code and stay static. They aren't shaped to carry decisions whose inputs change between requests — entity-graph state, federation-operational mode, dynamic naming.

Description

Real cases we ran into: delegation budgets that should narrow during incidents, federation-wide capacity limits, entity-reliability numbers over sliding windows.

§6.1.1 Determinism rightly keeps these out of static metadata-policy — so this kind of decision can't live inside metadata_policy. Federations that need it today have to build it outside the chain, and lose the federation's signature on the result.
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 3  ·  runtime policy

When inputs change between requests  ·  Direction

Direction

What we have in mind is an opt-in federation_policy_evaluation_endpoint that sits next to the static §6 layer — it never replaces it. The endpoint returns a signed decision with iat/exp, so cached decisions stay deterministic inside the window.

The decision can only narrow what the static layer already allows; it can never loosen it — §6.1.1 Hierarchy preserved.

Question

Just one: "Does the underlying need feel real enough for the WG to look at it further?"
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Feedback 3  ·  runtime policy

When inputs change between requests  ·  Example

TA declares the endpoint

"metadata": {
  "federation_entity": {
    "federation_policy_evaluation_endpoint":
      "https://policy.ai-fed.example/evaluate",
    "federation_policy_evaluation_fallback": "use_cached"
  }
}

Signed decision

// policy-decision+jwt — narrows a static budget federation-wide
{ "iss": "https://policy.ai-fed.example",
  "sub": "https://advisor-platform.example",
  "iat": 1779373800,  "exp": 1779373860,
  "decision": "modified",
  "effective_metadata": { "default_delegation_budget": 50 } }
@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com
@oidfed implementation overview & feedback

Thank you.

Open to any suggestion, question, or further involvement — on the spec, on the implementation, or on the demo.

@oidfed · OIDF AB/Connect WG · 2026-05-21              oidfed.com