<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mcp on Roland Huß</title><link>https://ro14nd.de/tags/mcp/</link><description>Recent content in Mcp on Roland Huß</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>© 2026 Roland Huß</copyright><lastBuildDate>Sun, 14 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ro14nd.de/tags/mcp/index.xml" rel="self" type="application/rss+xml"/><item><title>Three Hops Deep and No Browser in Sight</title><link>https://ro14nd.de/three-hops-deep-and-no-browser-in-sight/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://ro14nd.de/three-hops-deep-and-no-browser-in-sight/</guid><description>&lt;p&gt;You&amp;rsquo;ve seen this screen. If you use Claude Code or Cursor with MCP servers, you&amp;rsquo;ve clicked through it dozens of times. &amp;ldquo;Google MCP Server wants to access your Google Account.&amp;rdquo; You review the scopes, click Allow, a token lands in your local config, and everything works.&lt;/p&gt;
&lt;p&gt;Now imagine the agent that needs your Google Calendar isn&amp;rsquo;t the one you&amp;rsquo;re talking to. It&amp;rsquo;s three agents deep in a multi-agent chain, running in a container with no browser and no way to show you a consent screen.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s what this post is about.&lt;/p&gt;

&lt;figure&gt;
 &lt;img class="my-0 rounded-md" src="https://ro14nd.de/images/three-hops-deep-and-no-browser-in-sight/og.jpg" alt="Watercolor split-screen illustration. Left side labeled &amp;#39;On Your Laptop&amp;#39;: a sheep with glasses sitting at a desk, clicking &amp;#39;Allow&amp;#39; on a consent screen. Right side labeled &amp;#39;Three Hops Deep&amp;#39;: three sheep standing in a dim barn filled with hay bales arranged like server racks, facing a padlocked door with no computer in sight." /&gt;
 
 
 &lt;/figure&gt;

&lt;h2 class="relative group"&gt;Two tokens, two problems
 &lt;div id="two-tokens-two-problems" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#two-tokens-two-problems" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;MCP authentication handles the connection between your client and the MCP server well. The spec&amp;rsquo;s &lt;a href="https://modelcontextprotocol.io/specification/draft/basic/authorization" target="_blank" rel="noreferrer"&gt;OAuth 2.1 flow&lt;/a&gt; works like standard OAuth: your client authenticates with the MCP server&amp;rsquo;s authorization server, gets an access token, and sends it with every request. The server validates the token, serves the request, and holds no per-user state. Stateless. Each request carries its own bearer token.&lt;/p&gt;
&lt;p&gt;The problem starts when the MCP server needs to call an external service on your behalf. The token your client sends authenticates you &lt;em&gt;to the MCP server&lt;/em&gt;. When that server needs to read your Google Calendar, it needs a completely different token. One that Google issued, through Google&amp;rsquo;s own consent flow.&lt;/p&gt;
&lt;p&gt;On your laptop, this is invisible. The local MCP server opens your browser to Google&amp;rsquo;s consent screen, you approve, and the server stores the token in &lt;code&gt;~/.mcp-auth&lt;/code&gt; or a similar local path. One user, one browser, done.&lt;/p&gt;
&lt;p&gt;In any other environment, this falls apart. You could have the user acquire a Google token out of band and pass it to the MCP server. But the MCP spec explicitly calls this &lt;a href="https://modelcontextprotocol.io/specification/draft/basic/authorization" target="_blank" rel="noreferrer"&gt;token passthrough an anti-pattern&lt;/a&gt;: the server accepts a token it didn&amp;rsquo;t issue, can&amp;rsquo;t verify how it was obtained, and has no way to confirm the scope is appropriate.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve configured your identity provider (Keycloak, Entra ID) as a broker for Google, the plumbing can work. The user authenticates through your SSO, Keycloak redirects the browser to Google&amp;rsquo;s consent screen, the user approves, and Google returns an authorization code. Keycloak exchanges that code for Google&amp;rsquo;s access and refresh tokens and stores them. Later, the MCP server can use &lt;a href="https://datatracker.ietf.org/doc/html/rfc8693" target="_blank" rel="noreferrer"&gt;token exchange&lt;/a&gt; to get the stored Google token from Keycloak. The exchange mechanism works. The bottleneck is the consent event that has to happen first.&lt;/p&gt;
&lt;p&gt;Consent doesn&amp;rsquo;t scale across providers. If your agent chain needs Google Calendar, Microsoft Graph, and Slack, each provider requires its own browser redirect, its own consent screen, its own token. You can&amp;rsquo;t batch them. The question is &lt;em&gt;when&lt;/em&gt; to acquire these tokens. At onboarding (&amp;ldquo;connect your accounts&amp;rdquo;), you over-provision because you don&amp;rsquo;t know which services the user will actually need. At first use, you need a browser. Mid-execution of an agent chain, you have neither.&lt;/p&gt;
&lt;p&gt;This is the token gap. The infrastructure for moving tokens between systems exists. What&amp;rsquo;s missing is a way to get the user in front of the right consent screen at the right time, especially when &amp;ldquo;the right time&amp;rdquo; turns out to be three agents deep in a chain that has no browser.&lt;/p&gt;

&lt;figure&gt;
 &lt;img class="my-0 rounded-md" src="https://ro14nd.de/images/three-hops-deep-and-no-browser-in-sight/token-gap.png" alt="Diagram showing the token gap. On the left, the internal trust domain: Keycloak issues an MCP token to the User (Claude Code), who sends requests with the bearer token to the MCP Server. The MCP Server validates against Keycloak. On the right, the external trust domain: Google Calendar API. Between them, a dashed red arrow labeled &amp;#39;needs Google token ???&amp;#39; marks the gap. Below, a dashed box shows the Google Consent Screen that would issue the token, but requires a browser redirect with no path from the MCP server." /&gt;
 
 
 &lt;/figure&gt;
&lt;p&gt;The token gap is really two problems that look like one. Credentials are the plumbing: getting a token that the external provider accepts. The token either exists or it doesn&amp;rsquo;t, and the mechanisms for acquiring it (token exchange, vault lookup, gateway injection) are well understood. Consent is the human problem: the user deciding which scopes to grant, to which agent, for what purpose. No amount of infrastructure replaces that decision.&lt;/p&gt;
&lt;p&gt;On a laptop, the consent screen handles both. You authenticate to Google and approve the scopes in the same flow. Once the MCP server moves off your laptop, these concerns separate. A system where agents hold technically valid tokens that nobody explicitly authorized for the current use isn&amp;rsquo;t a security solution. It&amp;rsquo;s a liability. Every pattern below solves the credential problem at a different level. The harder question is always consent.&lt;/p&gt;

&lt;h2 class="relative group"&gt;The known patterns
 &lt;div id="the-known-patterns" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-known-patterns" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Christian Posta has been writing some of the clearest analysis of MCP security and agent authorization patterns. His &lt;a href="https://blog.christianposta.com/mcp-authorization-patterns-upstream-api-calls/" target="_blank" rel="noreferrer"&gt;taxonomy of MCP authorization patterns for upstream API calls&lt;/a&gt; maps the approaches people use to cross this gap. Rather than retread his analysis (go read it, it&amp;rsquo;s worth your time), I&amp;rsquo;ll summarize where each one breaks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shared admin credential.&lt;/strong&gt; Give the MCP server a single credential for Google. Every user&amp;rsquo;s request goes through the same account. Easiest to implement, worst for security: no per-user scoping, no audit trail tying actions to individuals, and a single credential whose compromise exposes everyone. The MCP spec &lt;a href="https://modelcontextprotocol.io/specification/draft/basic/authorization" target="_blank" rel="noreferrer"&gt;explicitly calls this an anti-pattern&lt;/a&gt;. Don&amp;rsquo;t do it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Credential passthrough.&lt;/strong&gt; The user acquires a Google token out of band and passes it to the MCP server. The spec flags this as an anti-pattern too. The server accepts tokens it didn&amp;rsquo;t issue and can&amp;rsquo;t validate. There&amp;rsquo;s no proof the token came from a proper OAuth flow, no way to verify the scope matches what this server should have.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SSO federation.&lt;/strong&gt; Use your identity provider&amp;rsquo;s brokering capability (Keycloak&amp;rsquo;s identity broker, Entra ID&amp;rsquo;s external identities) to federate with Google. If the user has already linked their Google account through the IdP, this works without any browser interaction at request time. The IdP stores the Google tokens, and token exchange surfaces them to the MCP server. This solves the credential problem cleanly.&lt;/p&gt;
&lt;p&gt;It doesn&amp;rsquo;t solve the consent problem. When you configure Google as a broker in Keycloak, you specify which scopes to request up front: &lt;code&gt;openid&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;profile&lt;/code&gt; for identity, plus whatever API scopes your MCP servers need (&lt;code&gt;calendar.readonly&lt;/code&gt;, &lt;code&gt;drive.readonly&lt;/code&gt;). These lock in at configuration time. If a new MCP server needs a scope you didn&amp;rsquo;t anticipate, you update the config and send the user through Google&amp;rsquo;s consent screen again. Google shows all scopes at once, so you can&amp;rsquo;t incrementally add one without a new consent event. And token exchange hands over the full stored token with all granted scopes. There&amp;rsquo;s no built-in way to give one MCP server &lt;code&gt;calendar.readonly&lt;/code&gt; and another &lt;code&gt;drive.readonly&lt;/code&gt; from the same token.&lt;/p&gt;
&lt;p&gt;This is the pre-flight consent problem in infrastructure clothing: pre-configure scopes and hope they cover everything agents will need. When they don&amp;rsquo;t, you need a browser. Two IETF drafts, &lt;a href="https://datatracker.ietf.org/doc/draft-ietf-oauth-identity-chaining/" target="_blank" rel="noreferrer"&gt;Identity Assertion Authorization Grant&lt;/a&gt; and &lt;a href="https://datatracker.ietf.org/doc/draft-ietf-oauth-identity-chaining/" target="_blank" rel="noreferrer"&gt;OAuth Identity Chaining Across Domains&lt;/a&gt;, aim to enable cross-domain token exchange without per-provider consent flows. Neither is widely implemented yet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;URL elicitation.&lt;/strong&gt; The MCP spec&amp;rsquo;s &lt;a href="https://modelcontextprotocol.io/seps/1036-url-mode-elicitation-for-secure-out-of-band-intera" target="_blank" rel="noreferrer"&gt;elicitation mechanism&lt;/a&gt; (SEP-1036) has two modes. &lt;code&gt;form&lt;/code&gt; handles in-band data entry where the response passes through the MCP client. &lt;code&gt;url&lt;/code&gt; bypasses the client entirely. In URL mode, the MCP server sends a URL to the client, the client shows it to the user, the user opens it in a browser. That URL initiates a standard OAuth authorization flow with Google. The callback redirects back to the MCP server, which receives the authorization code and exchanges it for tokens server-side. The user just clicks a link and approves. Tokens never touch the client or the model.&lt;/p&gt;
&lt;p&gt;This works for multiple users, since each completes their own consent flow and the server stores per-user tokens. But it makes the MCP server stateful: it now manages external token storage, refresh rotation, and revocation. And it still requires a user with a browser at the other end of the chain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agent gateway.&lt;/strong&gt; A gateway sits in front of MCP servers, controlling who can access which servers and tools. Projects like &lt;a href="https://github.com/Kuadrant/mcp-gateway" target="_blank" rel="noreferrer"&gt;Kuadrant&amp;rsquo;s MCP gateway&lt;/a&gt; enforce authN/authZ via JWT validation and CEL-based (Common Expression Language) policies at this layer. Christian&amp;rsquo;s &lt;a href="https://blog.christianposta.com/mcp-authorization-patterns-upstream-api-calls/#pattern-5-offload-out-of-band-elicitation-to-secure-infrastructure" target="_blank" rel="noreferrer"&gt;Pattern 5&lt;/a&gt; extends this: the gateway also acquires and manages credentials for upstream APIs, injecting external tokens into outbound calls so the MCP server never touches them. But a gateway operates within the platform&amp;rsquo;s trust domain. It can block access to an MCP server, but it can&amp;rsquo;t downscope an already-granted Google token or make consent decisions on the user&amp;rsquo;s behalf. Platform authorization and external-service consent are orthogonal.&lt;/p&gt;
&lt;p&gt;Each of these patterns assumes something about the environment: that a user is present, that a browser is reachable, or that the credential-acquiring component knows which user to act for. Those assumptions hold on a developer laptop. They start failing when the MCP server runs remotely, in a cluster, or in any environment where no browser is directly reachable. They collapse entirely when agents call other agents.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Where it gets harder: multi-agent chains
 &lt;div id="where-it-gets-harder-multi-agent-chains" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#where-it-gets-harder-multi-agent-chains" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;figure&gt;
 &lt;img class="my-0 rounded-md" src="https://ro14nd.de/images/three-hops-deep-and-no-browser-in-sight/multi-agent-chain.png" alt="Diagram showing a multi-agent chain. User (Claude Code) with a browser sends &amp;#39;schedule meeting&amp;#39; to a Planning Agent (hop 1, no browser), which sends &amp;#39;find slots&amp;#39; to a Calendar Agent (hop 2, no browser), which sends &amp;#39;read calendar&amp;#39; to a Google MCP Server (hop 3, no browser). The MCP Server needs a Google token to reach the Google Calendar API but has no path to the user&amp;#39;s browser." /&gt;
 
 
 &lt;/figure&gt;
&lt;p&gt;Take a concrete scenario. A planning agent receives a request: &amp;ldquo;Schedule a meeting with the team and attach the latest design doc.&amp;rdquo; The planning agent calls a calendar agent to find your available slots. The calendar agent calls a Google MCP server to read your calendar. That MCP server needs a Google OAuth token for your account.&lt;/p&gt;
&lt;p&gt;You made the original request three hops ago. The Google MCP server has no connection to a browser. URL elicitation can&amp;rsquo;t work because there&amp;rsquo;s no client to show the URL to. The calendar agent doesn&amp;rsquo;t even know it was invoked by a human. It just received a tool call from the planning agent.&lt;/p&gt;
&lt;p&gt;Three approaches keep coming up. None of them work well.&lt;/p&gt;

&lt;figure&gt;
 &lt;img class="my-0 rounded-md" src="https://ro14nd.de/images/three-hops-deep-and-no-browser-in-sight/error-propagation.png" alt="Two diagrams comparing error propagation approaches. Top (red, unreliable): -32042 error flows from MCP Server through LLM agents back to user, but may get lost or rephrased at each hop. Bottom (green, reliable): same error intercepted at the harness transport layer, propagated through infrastructure without the LLM seeing it." /&gt;
 
 
 &lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Error propagation.&lt;/strong&gt; The MCP spec has a mechanism for direct connections: the Google MCP server returns error code &lt;code&gt;-32042&lt;/code&gt; (&lt;code&gt;URLElicitationRequiredError&lt;/code&gt;) with a consent URL embedded in the response. The client recognizes the error, shows the URL, the user completes the OAuth flow, the callback lands on the MCP server, and the client retries.&lt;/p&gt;
&lt;p&gt;In a multi-agent chain, this falls apart. The error goes to the calendar agent, not to the user&amp;rsquo;s client. For the consent URL to reach the user, every intermediate agent would need to recognize it and propagate it up the chain. LLM-based agents are unreliable at this. They might rephrase the error, attempt workarounds, or lose the URL entirely. Even if the URL reaches the user and they complete the consent flow, the &amp;ldquo;retry&amp;rdquo; signal needs to travel back down through the same chain.&lt;/p&gt;
&lt;p&gt;A more promising approach would handle this at the harness level. The runtime that makes MCP calls intercepts the &lt;code&gt;-32042&lt;/code&gt; at the transport layer before the LLM sees it, propagates the consent URL back through the infrastructure chain, and retries transparently once the user completes the flow. The LLM never sees the auth error. But this requires every harness in the chain to support the protocol, and no agent framework standardizes this today.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Async notification.&lt;/strong&gt; Instead of propagating the consent URL through the agent chain, the MCP server delivers it via a side channel: email, Slack message, push notification. The user clicks the link, completes the same OAuth consent flow in their browser, and the callback lands on the MCP server just like in URL elicitation. The OAuth flow is identical. Only the delivery mechanism for the consent URL is different.&lt;/p&gt;
&lt;p&gt;This decouples consent from the agent chain but introduces its own problems. The MCP server needs to know how to reach the user (email address? Slack handle?) and needs to identify which user to contact from the bearer token on the original request. Timeouts are ugly: the agent chain blocks while waiting, with no guarantee that consent ever arrives.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pre-flight consent.&lt;/strong&gt; Before the agent chain starts, the platform collects all the tokens the chain &lt;em&gt;might&lt;/em&gt; need. The user consents to Google Calendar, Google Drive, Slack, and Jira up front. The platform stores tokens in a vault and injects them as needed.&lt;/p&gt;
&lt;p&gt;This front-loads the UX problem but creates over-provisioning. The platform doesn&amp;rsquo;t know which external services the chain will actually use because agent behavior is non-deterministic. Asking for every possible scope up front violates least privilege. Users learn to click &amp;ldquo;Allow&amp;rdquo; without reading the scopes, which is exactly the pattern OAuth was designed to prevent.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.coalitionforsecureai.org/wp-content/uploads/2026/04/agentic-identity-and-access-control.pdf" target="_blank" rel="noreferrer"&gt;CoSAI&amp;rsquo;s Agentic IAM paper&lt;/a&gt; (March 2026) establishes the right principles for multi-agent delegation: scope narrows at each hop, never expands. Delegation tokens carry explicit actor and subject claims so the chain of custody stays auditable. These principles describe what the token &lt;em&gt;should look like&lt;/em&gt; once it exists. Getting the user&amp;rsquo;s consent in the first place, when the user is three hops away, is a different problem entirely.&lt;/p&gt;
&lt;p&gt;The most interesting architectural proposal I&amp;rsquo;ve seen is &lt;a href="https://aauth.dev" target="_blank" rel="noreferrer"&gt;AAuth&lt;/a&gt;, a delegation protocol from Dick Hardt (the author of OAuth 2.0) that rethinks the problem from scratch. It&amp;rsquo;s an &lt;a href="https://datatracker.ietf.org/doc/draft-hardt-aauth-protocol/" target="_blank" rel="noreferrer"&gt;IETF draft&lt;/a&gt; in the OAuth working group. Instead of one-time consent grants that get reused indefinitely, AAuth introduces a Person Server that acts as an ongoing consent oracle. Dasith Wijesiriwardena&amp;rsquo;s &lt;a href="https://dasith.me/2026/06/10/the-errand-agentic-delegation/" target="_blank" rel="noreferrer"&gt;errand analogy&lt;/a&gt; is the most accessible explanation, and Christian wrote a &lt;a href="https://blog.christianposta.com/aauth-full-demo/" target="_blank" rel="noreferrer"&gt;hands-on demo walkthrough&lt;/a&gt;. The agent doesn&amp;rsquo;t hold your Google token. It carries an unsigned request from the resource to the Person Server, the Person Server checks with you (or evaluates against a pre-approved &amp;ldquo;mission&amp;rdquo;), and returns a signed authorization. The Person Server evaluates each request individually. The agent shuttles tokens between parties but never holds standing credentials.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;mission&amp;rdquo; concept is what makes this click. A mission is a written-down, approved intent that the Person Server holds on behalf of the user. Think of it as a scoped work order: &amp;ldquo;schedule a meeting with the team and attach the latest design doc.&amp;rdquo; The agent proposes the mission, the user approves it, and every subsequent request gets evaluated against the mission&amp;rsquo;s stated purpose. Read a calendar to find available slots? In scope, approved silently. Send an email to someone not on the team? Out of scope, escalated to the user.&lt;/p&gt;
&lt;p&gt;The Person Server sees all requests across all resources under that mission, which makes it the one party positioned to detect when the agent&amp;rsquo;s behavior drifts from the original intent. Missions have a lifecycle: active or terminated. Tokens issued under them are short-lived. That&amp;rsquo;s a cleaner answer to the pre-flight consent problem than asking for every possible scope up front and hoping for the best.&lt;/p&gt;
&lt;p&gt;AAuth also handles sub-agent chains explicitly. Each hop gets its own identity for audit and revocation, authority flows through the parent agent, and the full delegation chain back to the person is preserved. The protocol is early (the &lt;a href="https://datatracker.ietf.org/doc/draft-hardt-aauth-protocol/" target="_blank" rel="noreferrer"&gt;spec&lt;/a&gt;, an &lt;a href="https://explorer.aauth.dev/" target="_blank" rel="noreferrer"&gt;interactive explorer&lt;/a&gt;, and a .NET SDK are available), and the architecture addresses the right problems. It also makes the credentials-vs-consent split structural: the Person Server handles consent (did the user approve this action?), while the resource&amp;rsquo;s Access Server enforces its own policies independently. Two gates, both must pass.&lt;/p&gt;
&lt;p&gt;The catch: AAuth requires the resource to participate in the protocol. The Person Server issues AAuth tokens, not Google OAuth tokens. For existing providers like Google, Microsoft, or Slack that only accept their own OAuth tokens, you still need their consent flow to get a token they&amp;rsquo;ll accept. AAuth solves consent and delegation for resources that speak AAuth. For everything else, the consent screen problem stays until major API providers adopt the protocol.&lt;/p&gt;

&lt;h2 class="relative group"&gt;What remains open
 &lt;div id="what-remains-open" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-remains-open" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The token gap has patterns. Multi-agent consent doesn&amp;rsquo;t. Here&amp;rsquo;s what I think still needs solving.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where do tokens live?&lt;/strong&gt; Per-user external tokens need to persist across agent invocations but shouldn&amp;rsquo;t be accessible to agents that don&amp;rsquo;t need them. A vault with fine-grained access policies is the obvious answer, but the lifecycle is tricky. Who provisions the vault entry? Who rotates it? What happens when the user revokes consent through Google&amp;rsquo;s security settings? Who cleans up the stale token?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do you reach the user?&lt;/strong&gt; In a multi-agent chain, the consent request needs to travel back to a human who can open a browser. Today this is ad hoc: error propagation, push notifications, Slack messages. There&amp;rsquo;s no standard channel for &amp;ldquo;an agent three hops deep needs your approval.&amp;rdquo; Building one means defining a consent backpropagation protocol that agent frameworks understand.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What happens when consent drifts?&lt;/strong&gt; A user approves &lt;code&gt;calendar.readonly&lt;/code&gt; for a scheduling task. Six months later, a different agent chain uses the same token to read calendar details for a completely different purpose. The token is technically valid. The consent is contextually stale. AAuth&amp;rsquo;s mission model addresses this by scoping consent to a specific task with a defined lifecycle. But deciding what counts as &amp;ldquo;in scope&amp;rdquo; is left to the Person Server&amp;rsquo;s policy engine, and that policy engine doesn&amp;rsquo;t exist yet as a general-purpose solution. Of the open problems, this is the one that worries me most. A valid token with stale consent is indistinguishable from a properly authorized one until something goes wrong.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://thehackernews.com/2026/04/vercel-breach-tied-to-context-ai-hack.html" target="_blank" rel="noreferrer"&gt;Vercel/Context.ai incident&lt;/a&gt; in April 2026 showed what happens when these problems aren&amp;rsquo;t addressed. An infostealer on a Context.ai employee&amp;rsquo;s machine compromised OAuth tokens that Context.ai held on behalf of its users. One of those tokens belonged to a Vercel employee who had connected Context.ai to their enterprise Google Workspace with broad permissions. The attacker used that token to access the employee&amp;rsquo;s Google Workspace account, and from there found credentials that let them into Vercel&amp;rsquo;s internal environments, including dashboards, API keys, and environment variables that weren&amp;rsquo;t marked as sensitive. A single OAuth grant on a third-party AI tool became the first hop in a chain that reached deep into an enterprise. Every token in that chain was valid and every access was authorized, but the usage was not what anyone intended.&lt;/p&gt;
&lt;p&gt;The IETF drafts on identity chaining and assertion grants are the right long-term direction. When they reach production implementations, they&amp;rsquo;ll provide a standards-based way to exchange internal tokens for external ones without the user clicking through a consent screen every time. But &amp;ldquo;12-24 months to RFC&amp;rdquo; means organizations deploying multi-agent systems today need interim solutions.&lt;/p&gt;
&lt;p&gt;The fundamental tension remains: agents are non-deterministic, but OAuth consent is interactive. Agents compose dynamically, but consent is granted statically. Protocols like &lt;a href="https://aauth.dev" target="_blank" rel="noreferrer"&gt;AAuth&lt;/a&gt; and standards like the IETF identity chaining drafts are attacking this from different angles, but neither is production-ready today. Until the consent model catches up to agent composition, the gap between &amp;ldquo;the agent has a valid token&amp;rdquo; and &amp;ldquo;the user approved this specific use&amp;rdquo; will keep growing.&lt;/p&gt;
&lt;p&gt;On your laptop, that gap doesn&amp;rsquo;t matter. Three hops deep and no browser in sight, it&amp;rsquo;s the whole problem.&lt;/p&gt;
&lt;div class="ai-attribution"&gt;
&lt;p&gt;Author: Roland Huß &lt;a href="https://aiattribution.github.io/statements/AIA-HAb-CeNc-Hin-R-?model=Claude%20Opus%204.6-v1.0" target="_blank" rel="noreferrer"&gt;AIA HAb CeNc Hin R Claude Opus 4.6 v1.0&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description></item></channel></rss>