diff --git a/README.md b/README.md index 8e86273..c924f96 100644 --- a/README.md +++ b/README.md @@ -520,6 +520,8 @@ The server is designed for horizontal scaling using Redis as the backbone: - **Automatic Cleanup**: No explicit cleanup required #### Redis Key Structure + +##### MCP Session Keys ``` session:{sessionId}:owner # Session ownership mcp:shttp:toserver:{sessionId} # Client→Server messages @@ -527,6 +529,17 @@ mcp:shttp:toclient:{sessionId}:{requestId} # Server→Client responses mcp:control:{sessionId} # Control messages ``` +##### OAuth/Auth Keys +``` +auth:client:{clientId} # OAuth client registrations +auth:pending:{authCode} # Pending authorizations +auth:installation:{accessToken} # Active MCP installations +auth:exch:{authCode} # Token exchanges +auth:refresh:{refreshToken} # Refresh tokens +``` + +Note: The `auth:` prefix ensures complete namespace isolation between auth and MCP functions in both integrated and separate modes. + ### Transport Methods #### Streamable HTTP (Recommended) diff --git a/docs/user-id-system.md b/docs/user-id-system.md index eb4daff..917b41c 100644 --- a/docs/user-id-system.md +++ b/docs/user-id-system.md @@ -127,6 +127,7 @@ Redis stores session ownership information using a structured key system. ### Redis Key Structure +#### MCP Session Keys (MCP Server) ``` session:{sessionId}:owner → userId # Session ownership mcp:shttp:toserver:{sessionId} → [pub/sub channel] # Client→Server messages (also indicates liveness) @@ -134,6 +135,17 @@ mcp:shttp:toclient:{sessionId}:{requestId} → [pub/sub channel] # Server→Clie mcp:control:{sessionId} → [pub/sub channel] # Control messages ``` +#### Auth Keys (Auth Server) +``` +auth:client:{clientId} → client registration # OAuth client registrations +auth:pending:{authCode} → pending authorization # Pending auth (10 min TTL) +auth:installation:{accessToken} → MCP installation # Active sessions (7 days TTL) +auth:exch:{authCode} → token exchange # Token exchange (10 min TTL) +auth:refresh:{refreshToken} → access token # Refresh tokens (7 days TTL) +``` + +Note: The `auth:` prefix ensures complete isolation from MCP session keys, allowing both integrated and separate modes to work consistently. + ### Redis Operations | Operation | Key Pattern | Value | Purpose | diff --git a/shared/redis-auth.ts b/shared/redis-auth.ts index 7539c10..fc4d636 100644 --- a/shared/redis-auth.ts +++ b/shared/redis-auth.ts @@ -7,13 +7,14 @@ import { logger } from "../src/utils/logger.js"; /** * Redis key prefixes for different data types + * All auth-related keys use "auth:" prefix to avoid collision with MCP session keys */ export const REDIS_KEY_PREFIXES = { - CLIENT_REGISTRATION: "client:", - PENDING_AUTHORIZATION: "pending:", - MCP_AUTHORIZATION: "mcp:", - TOKEN_EXCHANGE: "exch:", - REFRESH_TOKEN: "refresh:", + CLIENT_REGISTRATION: "auth:client:", + PENDING_AUTHORIZATION: "auth:pending:", + MCP_AUTHORIZATION: "auth:installation:", // Changed from "mcp:" to avoid collision + TOKEN_EXCHANGE: "auth:exch:", + REFRESH_TOKEN: "auth:refresh:", } as const; /** diff --git a/src/services/auth.test.ts b/src/services/auth.test.ts index 6a761bd..4964031 100644 --- a/src/services/auth.test.ts +++ b/src/services/auth.test.ts @@ -124,8 +124,8 @@ describe("auth utils", () => { // instead of using exchangeToken which changes the value await saveTokenExchange(authCode, tokenExchange); - // Get the key used by saveTokenExchange - const key = "exch:" + crypto.createHash("sha256").update(authCode).digest("hex"); + // Get the key used by saveTokenExchange (now with auth: prefix) + const key = "auth:exch:" + crypto.createHash("sha256").update(authCode).digest("hex"); // Get the encrypted data const encryptedData = await mockRedis.get(key); @@ -266,8 +266,8 @@ describe("auth utils", () => { await revokeMcpInstallation(accessToken); - // Should have called getDel with the correct key - expect(getDel).toHaveBeenCalledWith(expect.stringContaining("mcp:")); + // Should have called getDel with the correct key (now auth:installation:) + expect(getDel).toHaveBeenCalledWith(expect.stringContaining("auth:installation:")); });