Chio/Docs
LOGIN · JOIN

Federate Enterprise Identity

Admit bearer tokens by key, discovery, or introspection, derive a stable subject for each enterprise principal, and read the identity context every session carries.

Guide chio@5f63e6e

On this page

Put your identity provider in front of the MCP edge, and every session from one employee or workload acts as one Chio subject. Capabilities are issued against that subject, so receipts attribute work to the person or service behind the token.

The edge admits bearer tokens from an OIDC or OAuth 2.0 provider, canonicalizes the principal, and derives the subject from a persistent seed. The steps use an Azure AD tenant through OIDC discovery; pinned keys and token introspection follow the same path.

Start
Enterprise subjectChoose what arrives.
bearerbearerverifies: key, JWKS, or introspectionoidc:<issuer>#sub:<sub>issued againstattributed toa1session 1a2session 2σidentity providerKMCP edgesChio subjectsubjectKeyuSCIM DELETEκsession capabilitiesρreceiptsverifiesoidc:<issuer>#sub:<sub>issued againstattributed toa1session 1a2session 2σidentity providerKMCP edgesChio subjectsubjectKeyuSCIM DELETEκsession capabilitiesρreceipts

The edge admits the token and names its principal

The edge verifies the bearer under a pinned key, against the provider's discovered JWKS, or through its introspection endpoint. It canonicalizes the principal as oidc:<issuer>#sub:<sub> and derives a stable Chio subject from it with the identity federation seed. Remote MCP Edge.

Two sessions for one enterprise principal at a bearer-authenticated MCP edge, shown with the generic principal form. The Azure AD and client forms, group and role claims, and the provider registry the edge can read are left out.

1. Choose how the edge verifies tokens

Pick one mode by the tokens your provider issues. JWT verification and introspection are exclusive.

ModeFlagsVerifies
Pinned key--auth-jwt-public-key, --auth-jwt-issuer, --auth-jwt-audienceThe JWT signature under one Ed25519 key, the issuer, the audience
Discovery--auth-jwt-discovery-url, optional --auth-jwt-provider-profileThe JWT against the discovered JWKS
Introspection--auth-introspection-url, --auth-introspection-client-id, --auth-introspection-client-secretAn opaque token through the provider's introspection endpoint

Pass the introspection client id and secret together, and prefer CHIO_MCP_AUTH_INTROSPECTION_CLIENT_SECRET over the flag so the secret stays out of the process list. The edge refuses to boot with --auth-token beside any OAuth flag. Discovery fetches and introspection calls each time out after 5 seconds.

Before you begin
  • An identity provider that issues JWTs or supports OAuth 2.0 token introspection.
  • A policy file for the edge and a seed file for identity federation, kept outside source control. The seed must persist: a new seed derives new subjects.

2. Serve the edge with a federation seed

Give the admin API its own token, then start the edge with the discovery URL, the provider profile, the expected audience, and the seed file.

Terminalbash
export CHIO_ADMIN_TOKEN="$(openssl rand -hex 32)"
DISCOVERY=https://login.microsoftonline.com/larkfield.example/v2.0/.well-known/openid-configuration

chio mcp serve-http \
  --policy ./policy.yaml \
  --server-id pricing \
  --listen 127.0.0.1:8931 \
  --auth-jwt-discovery-url "$DISCOVERY" \
  --auth-jwt-provider-profile azure-ad \
  --auth-jwt-audience chio-mcp \
  --identity-federation-seed-file ./identity-federation.seed \
  -- python mcp_server.py

You should see the edge listening on 127.0.0.1:8931. JWT and introspection modes refuse to boot without CHIO_ADMIN_TOKEN. To share provider records with the trust service, add --enterprise-providers-file; Provider Registry & SCIM describes the records.

3. Read the canonical principal on a session

Connect a client with a token from your provider, then read its session through the admin API. The edge records the canonical principal and the derived subject in authContext.method.enterpriseIdentity.

Terminalbash
curl -sS -H "Authorization: Bearer $CHIO_ADMIN_TOKEN" \
  "http://127.0.0.1:8931/admin/sessions/$SESSION_ID/trust" \
  | jq '.authContext.method.enterpriseIdentity | {federationMethod, principal, subjectKey}'
Output
{
  "federationMethod": "jwt",
  "principal": "oidc:https://login.microsoftonline.com/larkfield.example/v2.0#oid:4b1f…9e02",
  "subjectKey": "7d3a…c1f8"
}

You should see the principal in one of three forms, chosen by the claims the token carries:

  • oidc:<issuer>#sub:<sub> for a user principal with a subject claim.
  • oidc:<issuer>#client:<client_id> for a client principal when the subject claim is absent.
  • oidc:<issuer>#oid:<oid> for a user under the Azure AD profile, which tries oid, then sub, then falls back to azp, appid, or client_id for clients.

The full context carries the provider id and record id, the provider kind, the federation method (jwt, introspection, scim, or saml), the principal, the subject key, the tenant, organization, groups, and roles, the source of each attribute, and the trust material reference. Beside it, authContext.method.federatedClaims holds the raw clientId, objectId, tenantId, organizationId, groups, and roles.

4. Confirm that two sessions share one subject

Open a second session with a fresh token for the same person and read it the same way. You should see the same principal and the same subjectKey: the edge derives the subject from the seed and the principal, never from the session.

The capabilities in each trust response carry the same subjectPublicKey in both sessions. The receipts for each session's tool calls name those capabilities, and GET /admin/receipts/tools?capability_id=<id> lists them, so one person's work reads as one subject across every session they opened.

A refused token stops before any session exists

A request with no bearer, or a bearer that fails the configured key, issuer, or audience, receives HTTP 401, and the edge creates no session, capability, or subject for it. A token that verifies but carries none of the claims a principal form needs is refused the same way, with a reason such as JWT bearer token missing subject and client_id for identity federation.

Tokens that carry a cnf claim are sender-constrained, and the edge enforces the DPoP proof, mTLS thumbprint, or attestation digest the claim binds; Remote MCP Edge covers that profile. To revoke the capabilities already tracked for a user, deprovision the user through SCIM on the trust service.

Next: manage the provider records