{"slug": "the-verified-identity-agent-bridge", "title": "The Verified Identity Agent Bridge", "summary": "A new pattern called the Verified Identity Agent Bridge (VIAB) solves the problem of preserving human identity when bridging consumer AI platforms to enterprise agents. The bridge verifies the human at the trusted edge using the enterprise identity provider, resolves canonical identity claims, and forwards verified identity as per-request context to downstream agents that cannot validate user tokens. This enables user-level accountability for regulated organizations adopting third-party AI front ends over internal systems.", "body_md": "Verify the human at the trusted edge, then carry that identity as explicit context to every downstream agent. Never collapse a user-initiated action into a shared service principal.\n\nAn enterprise wants its employees to reach an internal assistant from a commercial AI platform they already use every day. The assistant is a low-code agent: a Copilot Studio bot wired to an enterprise search index and a set of Power Automate flows. The integration looks simple. The host platform calls a proxy, the proxy calls the agent, the agent answers. A working prototype ships in a week.\n\nThen the question that matters arrives. An employee asks the assistant to act on something only they should see, and someone asks who, exactly, made that request. The proxy authenticated to the downstream agent with a single application credential. Every call the agent received that month carries the same actor: the proxy’s service principal. The humans who actually asked the questions are nowhere in the agent’s context or its flow run history. Personalization is impossible because the agent never learned who is asking. Authorization is impossible for the same reason. The identity was present at the front door and discarded one hop later.\n\nThis is the default failure mode when a consumer-facing AI platform is bridged into an enterprise agent. The host platform verifies a human. The proxy in the middle, built for speed, authenticates downstream with client credentials because that is the path of least resistance. Identity terminates at the proxy.\n\nWhen integrating a host AI platform with a downstream enterprise agent through a proxy, the proxy should verify the human identity using the enterprise identity provider’s delegated flow, resolve the canonical identity claims from the provider’s own source of truth, and forward that verified identity to the downstream agent as explicit per-request context. The app-only service-principal path is reserved for genuinely user-less work and logged as an exception, never used as the default for a user-initiated action. Preserving verified human identity across this bridge is the precondition for any US enterprise to adopt a third-party AI front end over internal systems without losing user-level accountability, which is what governs whether regulated organizations can use commercial AI platforms at all.\n\nThere is a wrinkle that defines the pattern. The downstream agent here is a low-code SaaS agent. It cannot validate a user-audience OAuth token the way a custom API can. So identity cannot be propagated by token exchange alone. It has to be **verified at the bridge and asserted downstream as trusted context**. That constraint is the reason this is a distinct pattern rather than a footnote to delegated-token forwarding.\n\nThe bridge is the one component on the path that both authenticates the human and speaks to the downstream agent. It carries the identity across the gap. Five constraints define it:\n\n*VIAB flow: identity is verified at the bridge, resolved from the directory, and asserted downstream as per-request context over an authenticated channel. Source: Image by the author.*\n\nThe downstream agent cannot validate a user token, so the bridge does not forward one. It verifies the human, then vouches for them over a channel the agent already trusts.\n\nThe worked example bridges **ChatGPT Enterprise to a Microsoft Copilot Studio agent** through a Node.js MCP proxy. ChatGPT Enterprise is the host AI platform, the Copilot Studio bot is the low-code downstream agent reached through a Power Automate flow [5], and the enterprise IdP is Microsoft Entra ID. This is the exact case VIAB is built for: ChatGPT Enterprise verifies the employee, but the Copilot Studio agent on the far side cannot validate a user-audience token, so the bridge has to verify the human and assert the identity across to it. The pattern was validated experimentally against a live integration between these two systems, with a ChatGPT Enterprise action invoking the Copilot Studio agent through the proxy.\n\nThe delegated flow starts with PKCE so the authorization code cannot be replayed by an interceptor. The bridge builds the authorization URL, the user signs in against Entra, and the returned code is exchanged for a token issued to that user.\n\n``` js\nimport { randomBytes, createHash } from \"crypto\";export function generatePKCE() {  const codeVerifier = randomBytes(32).toString(\"base64url\");  const codeChallenge = createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");  return { codeVerifier, codeChallenge };}export function getAuthorizationUrl(scope: string, redirectUri: string) {  const { codeVerifier, codeChallenge } = generatePKCE();  const state = randomBytes(16).toString(\"base64url\");  const params = new URLSearchParams({    client_id: process.env.CLIENT_ID!,    response_type: \"code\",    redirect_uri: redirectUri,    scope,                       // \"openid profile offline_access User.Read\"    state,    code_challenge: codeChallenge,    code_challenge_method: \"S256\",  });  const base = `https://login.microsoftonline.com/${process.env.TENANT_ID}/oauth2/v2.0`;  return { url: `${base}/authorize?${params}`, codeVerifier, state };}\n```\n\nThe code-for-token exchange is the moment the bridge obtains a credential that belongs to the human, not to itself:\n\n```\nexport async function exchangeCodeForToken(code: string, redirectUri: string, codeVerifier: string) {  const base = `https://login.microsoftonline.com/${process.env.TENANT_ID}/oauth2/v2.0`;  const res = await axios.post(`${base}/token`, new URLSearchParams({    client_id: process.env.CLIENT_ID!,    client_secret: process.env.CLIENT_SECRET!,    code,    redirect_uri: redirectUri,    grant_type: \"authorization_code\",    code_verifier: codeVerifier,  }), { headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" } });const { access_token, refresh_token, expires_in } = res.data;  return { accessToken: access_token, refreshToken: refresh_token, expiresIn: expires_in };}\n```\n\nA token is not an identity. The bridge resolves the canonical claims by calling the directory with the delegated token [4]. The delegated path uses /me. The app-only path has to be told which user to look up, which is the first sign it has lost the human.\n\n```\nexport async function getUserProfile(token: string, isAppToken: boolean, userEmail?: string) {  // Delegated token -> /me resolves the authenticated human.  // App-only token -> caller must name the user, because the token has no human in it.  const url = isAppToken    ? `${GRAPH_BASE}/users/${encodeURIComponent(userEmail ?? throwMissingUser())}`    : `${GRAPH_BASE}/me`;  const res = await axios.get(url, { headers: { Authorization: `Bearer ${token}` } });  return {    id: res.data.id,                                       // Entra object id (oid)    displayName: res.data.displayName,    email: res.data.mail ?? res.data.userPrincipalName,    // UPN as fallback  };}\n```\n\nThat fork is worth pausing on. The instant the bridge uses an app-only token, identity resolution requires the caller to *say* who the user is. Self-asserted identity is exactly what the pattern refuses for user-initiated actions.\n\nThe downstream agent is reached through an HTTP-triggered automation flow [5]. It cannot validate a user-audience token, so the bridge does not send one as proof of identity. It sends the resolved claims as explicit context and authenticates the channel itself so the flow can trust the source.\n\n```\nexport async function sendMessageToAgent(input: SendMessageInput, identity: ResolvedIdentity) {  const body = {    message: input.message.trim(),    // Verified identity asserted as explicit per-request context.    userId: identity.id,            // Entra oid, resolved from the directory    userName: identity.displayName,    userEmail: identity.email,  };const url = new URL(process.env.FLOW_URL!);  url.searchParams.set(\"api-version\", \"1\");return axios.post(url.toString(), body, {    headers: {      // The flow trigger is configured for Entra (\"Tenant\") auth, so it can      // verify the call came from this bridge, not an arbitrary poster.      Authorization: `Bearer ${await getChannelToken()}`,      \"Content-Type\": \"application/json\",    },    timeout: 60000,  });}\n```\n\nThe agent now has the human in context. Its flows can route, filter, and personalize on the verified userId and userEmail. Its run history attributes each interaction to a named person rather than to the bridge.\n\nThe decision turns on one axis above all: can the downstream consume a delegated token, and do user-initiated actions need to be attributable to a human?\n\n**Fits when:** the integration sits between a human-facing AI platform and an enterprise agent, individual user attribution matters for authorization or audit, and the enterprise IdP supports a delegated flow.\n\n**Doesn’t fit when:** there is no human principal, the action is provably non-user-specific, or the downstream can validate a delegated token directly and you should use straight token exchange instead.\n\n**Operational considerations:** the delegated flow needs a place to complete an interactive sign-in and somewhere to hold refresh tokens for long sessions. The channel between bridge and agent must be authenticated, or the asserted identity is forgeable. Token-endpoint throttling and refresh rotation apply as they do to any OAuth integration.\n\nThe bridge verifies identity cryptographically, but the downstream agent consumes that identity as an assertion, not as a token it independently validated. The whole guarantee rests on the channel between bridge and agent being authenticated. If the automation flow’s trigger accepts unauthenticated requests, any caller can post the same context fields and impersonate any user. VIAB is only as strong as the trust contract on that hop. Adopters should treat an unauthenticated downstream trigger as a critical defect, not a convenience.\n\nThe pattern also has a gravitational pull back toward the service principal. The moment a user token is missing or expired, the easiest code path is an app-only fallback, and that silently re-terminates identity. The fallback has to be gated and logged as an exception. Left ungated, the system degrades to the very anti-pattern the bridge was built to prevent, and it does so invisibly.\n\nFinally, host-platform constraints can fight the pattern. Some commercial AI platforms manage a single credential per action or per domain, which complicates issuing and refreshing per-user delegated tokens through them. Where the host cannot carry a per-user token, the interactive sign-in has to happen at the bridge directly, and the host platform’s own session becomes a weaker outer layer the bridge does not rely on for identity. VIAB establishes attribution; it does not establish intent. An agent can still be prompted toward actions the user did not mean to authorize, and that gap belongs to human-in-the-loop confirmation and scope minimization, not to the bridge.\n\nHow VIAB relates to the wider pattern family: this is the same identity-propagation discipline as the [Delegated Boundary OAuth](https://medium.com/@natarajaninbox/the-delegated-boundary-oauth-pattern-identity-propagation-across-mcp-gateways-for-enterprise-27983f311c10) pattern [6], applied to a topology that breaks DBO’s central assumption. DBO forwards a user-audience token because the downstream API can validate one. VIAB exists for the case where it cannot, so the bridge verifies the human and vouches for them instead. And the identity the bridge resolves is precisely the key a retrieval layer needs: the verified userId is what the [Security-Trimmed Index](https://medium.com/@natarajaninbox/a-practical-pattern-to-implement-secure-enterprise-ai-search-186212160924) [7] consumes as its security-filter principal, so a question asked through a commercial AI platform still returns only the documents that one human is allowed to see.\n\n[1] Internet Engineering Task Force. [ RFC 7636 — Proof Key for Code Exchange by OAuth Public Clients](https://datatracker.ietf.org/doc/html/rfc7636).\n\n[2] Internet Engineering Task Force. [ RFC 6749 — The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749).\n\n[3] Microsoft. [ Microsoft identity platform and OAuth 2.0 authorization code flow](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow).\n\n[4] Microsoft. [ Microsoft Graph REST API — Get the signed-in user (/me)](https://learn.microsoft.com/graph/api/user-get).\n\n[5] Microsoft. [ Copilot Studio — Trigger a flow from a topic](https://learn.microsoft.com/microsoft-copilot-studio/advanced-flow).\n\n[6] Companion pattern: [ The Delegated Boundary OAuth Pattern](https://medium.com/@natarajaninbox/the-delegated-boundary-oauth-pattern-identity-propagation-across-mcp-gateways-for-enterprise-27983f311c10).\n\n[7] Companion pattern: [ A Practical Pattern to Implement Secure Enterprise AI Search](https://medium.com/@natarajaninbox/a-practical-pattern-to-implement-secure-enterprise-ai-search-186212160924).\n\n[The Verified Identity Agent Bridge](https://pub.towardsai.net/the-verified-identity-agent-bridge-0837c8fb04b1) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/the-verified-identity-agent-bridge", "canonical_source": "https://pub.towardsai.net/the-verified-identity-agent-bridge-0837c8fb04b1?source=rss----98111c9905da---4", "published_at": "2026-06-18 06:11:17+00:00", "updated_at": "2026-06-18 06:28:58.680595+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-policy", "ai-infrastructure", "ai-tools"], "entities": ["ChatGPT Enterprise", "Microsoft Copilot Studio", "Power Automate", "Microsoft Entra ID", "Node.js", "MCP"], "alternates": {"html": "https://wpnews.pro/news/the-verified-identity-agent-bridge", "markdown": "https://wpnews.pro/news/the-verified-identity-agent-bridge.md", "text": "https://wpnews.pro/news/the-verified-identity-agent-bridge.txt", "jsonld": "https://wpnews.pro/news/the-verified-identity-agent-bridge.jsonld"}}