ID Partners Copilot Federation

Reference

Terms, decisions, risks and standards

The words agent, mirror, entity and instance mean different things in this design. The code cites its decisions by id. This page defines both.

Identities in this design

TermMeaning hereIdentifierEstablished by
Copilot Studio agentThe Microsoft-managed agent a maker configuresEntra Agent ID object id, sent as X-Agent-IdConnection-key check at the gateway
Mirror agent identityOur agent identity under our blueprint, one per Copilot Studio agentApp id, seen as azp in its tokensEntra token verified by the attestation service
Federation entityThe stable external OAuth client for that configured agenthttps://<bridge>/agents/<slug>OpenID Federation statements signed by the bridge
PoP keyOne per-agent Key Vault key, used to sign a fresh proof of possession on each exchangePublic key in the attestation's cnfSignature by that Key Vault key
Attestation instance idA random UUID the attestation service generates for each attestationworkload.instance_idOur attestation service only. It is not a Microsoft identifier.
Copilot Studio runOne execution of the agentConversation id, self-assertedNot verified

Decision register

The code cites decisions by id. This register was rebuilt from the code, the comments and the commit history in October 2026. Each row says what the code does.

IdDecisionWhat the code does
D1Per-agent connection keyThe caller sends X-Agent-Id (the claim) and X-Agent-Key (the proof). The gateway authenticates the Copilot Studio connection with this pair.
D2Gateway header allow-listOnly the user token, the mirror token, traceparent and Content-Type go to the bridge. An inbound mirror token header is dropped and its presence logged.
D5Mock and real modes never mixMock-tenant tokens are labelled mock, never entra_token. Real-mode verifiers refuse mock material by name before checking the signature.
D8Full check list on the raw mirror tokenSignature against the tenant JWKS, issuer, audience, expiry, idtyp=app, azp present, parent blueprint = ours, agent identity facet present.
D9Authentication failures are indistinguishableUnknown key id, unknown agent id, wrong secret and a mismatch all return the same 401 body. Enumeration learns nothing.
D10Registry changes only through reviewEvery service loads one versioned registry. It changes by commit, never at runtime. Uniqueness of slug, agent id, mirror and key id is enforced at load.
D11Missing key material is never papered overA missing key disables that role for that agent. The services never fall back to an ephemeral key.
D12Unknown agent: deny in real modeA verified azp that is not registered gets 403 unregistered_agent.
D13Audit link to the evidenceThe attestation carries the mirror token's id and a SHA-256 of the raw token.
D14Fresh PoP per exchange, one challenge retryA new PoP for every exchange, never cached. If PingFederate asks for a challenge, the bridge fetches one and retries once.
D15One key per roleThree EC P-256 pairs per agent, never shared across roles or agents.
D21Metadata policy on the bridge's subordinate statementThe bridge's statement about each agent pins the grant type to token exchange and the client authentication method to attestation. PingFederate enforces it, failing closed.
D23Federation list endpoint open in the demoThe list endpoint is unauthenticated. The production profile authenticates it.
D25Restrict the Entra token mapping to registered clientsApplied in two phases: create the clients, then restrict the access token manager to them.
D26Attested ceiling not enforced at the exchangeThe bridge does not send authorization_details by default, so the issued token's is empty. A switch turns it on.
D27Key custody precedenceKey Vault first, then an environment variable, then a local PEM. Local PEMs for development, Key Vault from staging up.
D28No plaintext secrets in the registryThe registry holds a key id and a SHA-256 of the connection secret, plus an optional next fingerprint for rotation. A unit test lints the registry.
D29Evidence verified at sourceThe attestation service verifies the raw mirror token itself. The bridge never verifies it and never summarises it.
D30One door per capabilityThe path names the destination, the headers name the caller. One shared connector, many doors.
D32Attestation service split from the bridgeSigning moved out of the bridge so a bridge compromise alone cannot produce an attestation. Each service loads only its key roles.
D33CachingThe gateway caches the mirror token until five minutes before expiry. The attestation is cached on agent, mirror-token hash and chain hash. Leaf and subordinate statements are never cached.
D34ObservabilityFailed authentication is rate-limited with an alert log. W3C traceparent is propagated from the gateway to the task agent. Refusals carry claim names and safe values, never the token.

Gates

IdWhat
G1PingFederate's attestation module runs in attestation + PoP mode. The bridge sends the attestation pair and no DPoP header, because sending both is invalid_client.
G2PingFederate, the Trust Anchor, vouches for the bridge with jwks only. This is why the metadata policy is on the bridge's statement.
M2A switch makes the bridge send the attested ceiling as authorization_details, so PingFederate enforces requested ⊆ attested. Off by default.

Named risks

IdRisk
R-ASSERTMicrosoft cannot assert which Copilot Studio agent is calling. The agent to mirror binding proves only that the caller holds that agent's connection secret, so it is labelled connection, below entra_token.
R-PAIRNo check that this user and this agent belong together. Any registered agent holding a valid subject token can exchange it.
R-BEARERIssued access tokens are bearer. Client authentication is proof of possession. The token is not DPoP-bound.
R-NAMEnaming_constraints is not implemented in PingFederate's validator, so the bridge's /agents/* namespace is enforced by the bridge.
R-ENUMThe federation list endpoint is open in the demo.

Standards the design uses

OAuth 2.0 Token Exchange

RFC 8693. The customer's token is the subject. The issued token records delegation in act.

OpenID Federation 1.0

Entity Configurations, subordinate statements, metadata policy and a trust chain from the agent to the Trust Anchor.

OAuth attestation-based client authentication

A client attestation and a per-request proof of possession, sent in the OAuth-Client-Attestation headers.

Rich Authorization Requests

RFC 9396. The agent's authority ceiling is expressed as authorization_details.

AuthZEN Authorization API

The gateway enforcement point asks PingAuthorize for a decision on each operation.

CIBA and A2A

Client-Initiated Backchannel Authentication for the step-up push. The Agent2Agent protocol between the bridge and the task agents.