Skip to main content
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:

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

  1. Configuration Received - Satellite receives MCP server config with requires_oauth: true
  2. Token Retrieval - Satellite calls backend to retrieve user’s OAuth tokens
  3. Header Construction - Satellite builds Authorization header with Bearer token
  4. MCP Request - Satellite sends request to MCP server with injected token
  5. 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 response structure:
Example response:

Token Status Check

Before retrieving full tokens, satellite can check if tokens exist and are valid:
Status response structure:
Example responses: Valid tokens:
Expired tokens (can refresh):
No tokens found:

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
Why caching:
  • Reduces backend load (tokens requested for every tool call)
  • Improves performance (no backend round-trip per request)
  • Tokens rarely change during short time windows
Cache validation:

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:
  1. Base headers (Content-Type, User-Agent, MCP-Protocol-Version)
  2. Team configuration headers (from config.headers - API keys, custom headers)
  3. OAuth Authorization header (from token retrieval)
Later headers override earlier ones if keys conflict.

Example Header Merge

Team configuration:
OAuth tokens:
Final headers sent to MCP server:
Important: If team headers include an 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:
Error message to MCP client:
User action: Re-install MCP server and complete OAuth flow.

Expired Tokens (No Refresh Available)

Scenario: Tokens expired and no refresh_token available. Detection:
Error message to MCP client:
User action: Delete and re-install MCP server to get new tokens.

Expired Tokens (Refresh In Progress)

Scenario: Tokens expired but backend is refreshing them (background cron job). Detection:
Handling:
  1. Satellite logs warning about expired token
  2. Backend cron job refreshes tokens automatically (every 5 minutes)
  3. Satellite retries request after short delay (or cache clears automatically after 5 minutes)
Error message (temporary):

Token Retrieval Failure

Scenario: Backend unreachable or token decryption fails. Error handling:
Error message to MCP client:

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
Detection: Check HTTP response from MCP server. Error handling:
User action: Delete and re-install MCP server.

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:
Bad logging (NEVER DO THIS):

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
Why no persistent storage:
  • 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
Manual cleanup:

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
Scope checking happens at:
  1. OAuth authorization (user approves scopes)
  2. Token issuance (OAuth provider validates)
  3. MCP server request (server validates scope)
Satellite does NOT need to validate scopes - it simply injects whatever backend provides.