Skip to main content
Version: Latest (1.9.x dev)

Exchange a caller's token for one the upstream accepts

A DELEGATED MCP server or A2A agent acts for the person or app that called DVARA, so the upstream applies that caller's own permissions. Until now DVARA did this one way: it sent the caller's token to the upstream unchanged.

That has two problems. The upstream sees a token that was not issued for it. And nothing in the token says DVARA acted for the caller. The MCP specification forbids a server from passing on the token its client gave it, for these reasons.

From 1.9.0, a DELEGATED server or agent says how the caller's token reaches the upstream:

  • Token exchange (offered first). DVARA trades the caller's token at your authorization server for a new token made for this upstream, and sends only the new token. This is OAuth 2.0 token exchange (RFC 8693).
  • Pass-through. DVARA sends the caller's own token unchanged. Use it only for an upstream whose authorization server has no token exchange. You must choose it, and every such call is recorded as pass-through.

A DELEGATED server or agent with neither is refused when you save it, when you import it, and by the gateway before anything is sent.

Set up token exchange​

On the MCP server's page or the A2A agent's page in Flightdeck:

  1. Set Auth Mode to DELEGATED and Delegation to Exchange the caller's token.
  2. In OAuth Client Credentials, fill in the token endpoint and the client DVARA signs in as: Token URL, Client ID, Client Secret Reference, and if your authorization server wants them, Scopes, Audience and Resource. These describe the token the upstream should get.
  3. In Token Exchange, set Grant to Token exchange.

The other Token Exchange fields have safe defaults:

FieldDefaultWhat it does
Caller Token (MCP only)The X-Dvara-Delegated-Authorization headerWhich token to exchange. On an MCP server you can choose the caller's own OAuth access token instead: the token the caller signed in to DVARA with, which DVARA has already checked.
Caller Token TypeAccess tokenWhat kind of token the caller's is: an access token, a JWT or an ID token.
Requested Token TypeAccess tokenWhat kind of token to ask for: an access token or a JWT.
How the Gateway Shows It Is the ActorClient authentication onlyDVARA signs in to the token endpoint as its client, so the authorization server knows who is acting. You can also have DVARA send its own client credentials token as the actor token. DVARA never makes a token of its own.
Issued JWT Must Name the ActorYesA JWT that does not say DVARA acted for the caller (no act claim) is refused.

On an A2A agent the caller always sends its token in the X-Dvara-Delegated-Authorization header, because A2A callers sign in to DVARA with an API key.

What DVARA checks​

DVARA uses the new token only if:

  • it is a bearer token, of type access token or JWT;
  • its scope is not wider than the scope you asked for (a narrower one is fine);
  • if it is a JWT, it names DVARA as the actor (unless you turned that off).

Otherwise the call is refused and nothing is sent.

How tokens are kept​

  • Each caller gets their own exchanged token. One caller's token is never sent for another caller, even if both call through the same API key.
  • A token lives only in the memory of the gateway that asked for it, and is never written to a database, a log, a record or an export.
  • It is used until shortly before it expires, and never longer than the caller's own token is valid.

When the exchange fails​

DVARA refuses the call, and sends neither the caller's token nor anything else.

What happenedThe caller gets
The authorization server refused the caller's token (expired, revoked or not allowed)MCP_TOKEN_EXCHANGE_DENIED or A2A_TOKEN_EXCHANGE_DENIED (403)
Anything else: wrong client secret, endpoint unreachable, an answer DVARA will not useMCP_UPSTREAM_OAUTH_FAILED or A2A_UPSTREAM_OAUTH_FAILED (502)
An MCP server exchanges the caller's own OAuth token, but the caller used an API keyMCP_DELEGATED_TOKEN_REQUIRED (401)

Your own API key is never sent to a peer​

If a caller puts the API key it used to call DVARA in the X-Dvara-Delegated-Authorization header, an A2A call is refused with A2A_TOKEN_PASSTHROUGH (400), on every kind of call. MCP refuses the same thing with MCP_TOKEN_PASSTHROUGH.

What the records show​

Each call records how the caller's token reached the upstream (delegation_mode: exchange or passthrough). For an exchange it also records:

  • fingerprints of the caller's token and of the new token, never the tokens;
  • who acted (DVARA's client id, and the actor the new token names);
  • the caller, only when DVARA checked the caller's token itself;
  • the audience, resource and scopes of the new token, and when it expires.

Saving a server or agent with pass-through records a warning. Exports carry the setting and write the client secret's reference as ***.

Who can set it​

Platform administrators set it on MCP servers. Platform and workspace administrators set it on A2A agents. The client secret must be a credential that belongs to the server's or agent's workspace.

See also Let DVARA get OAuth tokens for a server or agent that uses its own token rather than the caller's.