OAuth System Clarification: This document covers User → MCP Server OAuth token injection (how satellites inject tokens for Notion/Box/Linear access).For MCP Client → Satellite authentication (how VS Code/Cursor/Claude.ai authenticate to DeployStack), see:
- Backend Implementation: OAuth2 Server
- Satellite Integration: Satellite OAuth Authentication
Overview
This document covers how DeployStack satellites retrieve OAuth tokens from the backend and inject them into HTTP/SSE MCP servers that require user authorization (Notion, Box, Linear, GitHub Copilot).When Token Injection is Needed
OAuth token injection happens when:- MCP server requires OAuth authentication (
requires_oauth: true) - MCP server uses HTTP or SSE transport (not stdio)
- User has authorized the MCP server via OAuth flow
- Satellite needs to connect to MCP server on behalf of user
Token Injection Flow
- Configuration Received - Satellite receives MCP server config with
requires_oauth: true - Token Retrieval - Satellite calls backend to retrieve user’s OAuth tokens
- Header Construction - Satellite builds
Authorizationheader with Bearer token - MCP Request - Satellite sends request to MCP server with injected token
- Response - MCP server validates token and returns tools/results
Architecture Overview
The token injection system includes:- OAuthTokenService - Retrieves tokens from backend with 5-minute caching
- MCP Server Wrapper - Injects tokens into tool execution requests
- Remote Tool Discovery Manager - Injects tokens into tool discovery requests
- Backend Token Endpoint - Decrypts and returns user’s OAuth tokens
- Token Status Endpoint - Lightweight endpoint to check token validity
Token Retrieval Process
OAuthTokenService
File: services/satellite/src/services/oauth-token-service.ts Purpose: Retrieves OAuth tokens from backend and caches them for 5 minutes.Token Retrieval
Token Status Check
Before retrieving full tokens, satellite can check if tokens exist and are valid:Caching Strategy
Cache key format:${installationId}:${userId}:${teamId}
Cache TTL: 5 minutes
Cache invalidation:
- Automatic expiration after 5 minutes
- Token expiration detected (expires_at passed)
- Manual cache clear on token refresh
- Manual cache clear on user logout
- Reduces backend load (tokens requested for every tool call)
- Improves performance (no backend round-trip per request)
- Tokens rarely change during short time windows
HTTP/SSE Token Injection
Tool Execution Injection
File: services/satellite/src/core/mcp-server-wrapper.ts Purpose: Injects OAuth tokens when executing tools on HTTP/SSE MCP servers.Header Construction
1
Initialize Empty Headers
Start with empty headers object.
2
Add Team/User Headers
Merge custom headers from team and user configuration.
3
Check OAuth Requirement
Verify if MCP server requires OAuth and has necessary context.
4
Check Token Status
Verify tokens exist and are valid before retrieving.
5
Retrieve OAuth Tokens
Fetch user’s tokens from backend (uses cache if available).
6
Inject Authorization Header
Add OAuth token as Authorization Bearer header.
7
Send MCP Request
Forward request to MCP server with injected token.
Implementation Example
Tool Discovery Injection
File: services/satellite/src/services/remote-tool-discovery-manager.ts Purpose: Injects OAuth tokens when discovering available tools from HTTP/SSE MCP servers.Discovery with OAuth
Header Merging Priority
When building HTTP requests to OAuth MCP servers, headers are merged in this order:- Base headers (Content-Type, User-Agent, MCP-Protocol-Version)
- Team configuration headers (from
config.headers- API keys, custom headers) - OAuth Authorization header (from token retrieval)
Example Header Merge
Team configuration:Authorization header, it will be overridden by the OAuth token. This ensures OAuth authentication takes precedence.
Error Handling
Missing Tokens (User Not Authorized)
Scenario: User installed MCP server but never authorized OAuth. Detection:Expired Tokens (No Refresh Available)
Scenario: Tokens expired and no refresh_token available. Detection:Expired Tokens (Refresh In Progress)
Scenario: Tokens expired but backend is refreshing them (background cron job). Detection:- Satellite logs warning about expired token
- Backend cron job refreshes tokens automatically (every 5 minutes)
- Satellite retries request after short delay (or cache clears automatically after 5 minutes)
Token Retrieval Failure
Scenario: Backend unreachable or token decryption fails. Error handling:MCP Server Rejects Token
Scenario: MCP server returns 401 Unauthorized despite valid token. Possible causes:- Token revoked by user at OAuth provider
- MCP server changed OAuth configuration
- Token scope insufficient for requested operation
Security Considerations
Token Transmission
HTTPS required: All token transmissions between satellite and backend occur over HTTPS. No token logging: Satellite NEVER logs full access tokens, only metadata. Good logging:Token Storage
Satellite does NOT store tokens persistently:- Tokens cached in memory only (5-minute TTL)
- Cache cleared on satellite restart
- Cache cleared on user logout
- Tokens retrieved fresh from backend on cache miss
- Reduces attack surface (no encryption key management in satellite)
- Backend handles encryption/decryption
- Satellite process restart clears all tokens
Memory Cleanup
Automatic cleanup:- Cache TTL (5 minutes) removes old entries
- Token expiration detected and cache invalidated
- User logout clears user-specific cache entries
Token Scope Validation
Satellite trusts backend token validation:- Backend ensures tokens have required scopes
- Backend auto-refreshes expired tokens
- Satellite focuses on injection, not validation
- OAuth authorization (user approves scopes)
- Token issuance (OAuth provider validates)
- MCP server request (server validates scope)
Related Documentation
- MCP Server OAuth - Backend OAuth implementation (authorization, callback, token storage)
- MCP Transport - HTTP/SSE transport architecture
- Satellite OAuth Authentication - MCP client authentication (different system)
- MCP OAuth User Guide - User-facing documentation

