💡 “I Already Have a Token — Why Do I Need Another One?”
(And how this idea quietly powers patterns like MCP Server Auth)

Token Exchange (RFC 8693)
💡 “I Already Have a Token Why Do I Need Another One?”
(And how this idea quietly powers patterns like MCP Server Auth)
Understanding Token Exchange (RFC 8693) Through a Simple Service A → Service B Story
In OAuth conversations, we’ve all heard about the authorization code exchange the classic login flow where a user signs in, your app receives an authorization code, and the backend exchanges it for tokens.
But then you stumble upon something newer sounding: Token Exchange.
And the immediate reaction is usually:
“Wait… if I already have an access token, why would I ever need another one?”
This guide explains that in the simplest possible way one user, two services, one diagram and a quick nod to how this same principle shows up in MCP Server Auth patterns.
🧩 The Setup: One User, Two Services
Let’s consider:
- Service A the application the user interacts with
- Service B a backend service that performs a sensitive action
- Authorization Server issues and validates tokens
- User who logs in through the normal authorization code flow
When the user logs into Service A, the application receives an access token:
audience: Service A
scope: profile.read
Great Service A can now read the user’s profile.
But what happens when Service A needs to call Service B to perform something more sensitive like:
scope: payment.write
That’s where Token Exchange comes in.
📊 Sequence Diagram

Token Exchange in Action (RFC 8693)
🔄 Token Exchange in Action (RFC 8693)
OAuth 2.0 Token Exchange, defined in RFC 8693 → https://www.rfc-editor.org/rfc/rfc8693, lets you trade one token for another often with:
- different scopes
- different audiences
- different delegation semantics
Service A sends a request like this:
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
subject_token=<access_token_for_ServiceA>
subject_token_type=access_token
requested_token_type=access_token
audience=ServiceB
scope=payment.write
Here’s what’s happening:
subject_token → the original access token issued to Service A
audience=ServiceB → the new token must be valid for Service B
scope=payment.write → Service A needs higher privilege
The Authorization Server then:
1. Validates the subject_token
Checks:
- signature & expiry
- token was issued to Service A
- token hasn’t been revoked
2. Validates requested scope & audience
Makes sure:
- Service A is allowed to request
payment.write audiencematches Service B
3. Optionally checks the user
Only if the system needs to enforce:
- user permissions
- user consent
- policy & compliance rules
If everything is valid, the Authorization Server returns:
new access_token
scope: payment.write
audience: ServiceB
Now Service A can call Service B safely “on behalf of the user.”
🚫 Why You Can’t Reuse the Access Token Issued to Service A
This is the big question and probably the reason you’re reading this:
“If a user is already authenticated, why can’t I just use the same token to call Service B?”
Four important reasons.
1. Wrong Audience
The first token was issued for Service A.
Service B should reject it otherwise a token meant for one system would magically work everywhere. That is a massive security flaw.
2. Wrong Scope
The original token probably has:
scope: profile.read
But Service B requires:
scope: payment.write
These scopes describe different privileges. Reusing the original token breaks the least privilege principle.
3. Different Security Boundaries
Service A and Service B represent different trust zones.
You need a token that was explicitly minted for Service B’s environment, policies, and audit requirements.
4. Proper Delegation
Tokens issued via Token Exchange can embed:
- who the user is (
sub) - which service is performing the action (
act) - what the user is allowed to do
- what the service is allowed to do
This gives rich audit trails:
“User X initiated the payment, but the call was made by Service A using a token explicitly issued for Service B.”
🧠 The Cleanest Way to Think About It
Authorization Code Exchange
Used during login. Input: authorization code. Output: tokens for Service A.
Token Exchange
Used during backend delegation. Input: existing access token. Output: a new access token for Service B.
One is for user authentication. One is for service-to-service authorization.
⚡ A Quick Nod to MCP Server Auth
If you’ve looked at MCP servers lately, you might notice a similar philosophy:
Capabilities and tokens in MCP are scoped to the specific tool, resource, or action and you can’t reuse a capability across unrelated boundaries.
Just like Token Exchange prevents one token from being reused across services, MCP prevents a capability from leaking across tools.
Similar principle, different implementation.
🪄 In One Sentence
The access token from login was never meant for Service B Token Exchange (RFC 8693) gives us a clean, safe, standardized way to obtain the right token for the right service with the right scopes.
메타데이터
- post_id
- 84d0a461e28b
- slug
- i-already-have-a-token-why-do-i-need-another-one-84d0a461e28b
- url
- https://javascript.plainenglish.io/i-already-have-a-token-why-do-i-need-another-one-84d0a461e28b
- canonical_url
- https://javascript.plainenglish.io/i-already-have-a-token-why-do-i-need-another-one-84d0a461e28b
- author_url
- https://medium.com/@apoorva.gcet
- status
- ok
- fetched_at
- 2026-08-01 13:20:37