Skip to content

Commit 34fe20e

Browse files
committed
Implement Redis namespace isolation for auth and MCP keys
1 parent 4a081bc commit 34fe20e

4 files changed

Lines changed: 35 additions & 9 deletions

File tree

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,13 +520,26 @@ The server is designed for horizontal scaling using Redis as the backbone:
520520
- **Automatic Cleanup**: No explicit cleanup required
521521

522522
#### Redis Key Structure
523+
524+
##### MCP Session Keys
523525
```
524526
session:{sessionId}:owner # Session ownership
525527
mcp:shttp:toserver:{sessionId} # Client→Server messages
526528
mcp:shttp:toclient:{sessionId}:{requestId} # Server→Client responses
527529
mcp:control:{sessionId} # Control messages
528530
```
529531

532+
##### OAuth/Auth Keys
533+
```
534+
auth:client:{clientId} # OAuth client registrations
535+
auth:pending:{authCode} # Pending authorizations
536+
auth:installation:{accessToken} # Active MCP installations
537+
auth:exch:{authCode} # Token exchanges
538+
auth:refresh:{refreshToken} # Refresh tokens
539+
```
540+
541+
Note: The `auth:` prefix ensures complete namespace isolation between auth and MCP functions in both integrated and separate modes.
542+
530543
### Transport Methods
531544

532545
#### Streamable HTTP (Recommended)

docs/user-id-system.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,25 @@ Redis stores session ownership information using a structured key system.
127127

128128
### Redis Key Structure
129129

130+
#### MCP Session Keys (MCP Server)
130131
```
131132
session:{sessionId}:owner → userId # Session ownership
132133
mcp:shttp:toserver:{sessionId} → [pub/sub channel] # Client→Server messages (also indicates liveness)
133134
mcp:shttp:toclient:{sessionId}:{requestId} → [pub/sub channel] # Server→Client responses
134135
mcp:control:{sessionId} → [pub/sub channel] # Control messages
135136
```
136137

138+
#### Auth Keys (Auth Server)
139+
```
140+
auth:client:{clientId} → client registration # OAuth client registrations
141+
auth:pending:{authCode} → pending authorization # Pending auth (10 min TTL)
142+
auth:installation:{accessToken} → MCP installation # Active sessions (7 days TTL)
143+
auth:exch:{authCode} → token exchange # Token exchange (10 min TTL)
144+
auth:refresh:{refreshToken} → access token # Refresh tokens (7 days TTL)
145+
```
146+
147+
Note: The `auth:` prefix ensures complete isolation from MCP session keys, allowing both integrated and separate modes to work consistently.
148+
137149
### Redis Operations
138150

139151
| Operation | Key Pattern | Value | Purpose |

shared/redis-auth.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import { logger } from "../src/utils/logger.js";
77

88
/**
99
* Redis key prefixes for different data types
10+
* All auth-related keys use "auth:" prefix to avoid collision with MCP session keys
1011
*/
1112
export const REDIS_KEY_PREFIXES = {
12-
CLIENT_REGISTRATION: "client:",
13-
PENDING_AUTHORIZATION: "pending:",
14-
MCP_AUTHORIZATION: "mcp:",
15-
TOKEN_EXCHANGE: "exch:",
16-
REFRESH_TOKEN: "refresh:",
13+
CLIENT_REGISTRATION: "auth:client:",
14+
PENDING_AUTHORIZATION: "auth:pending:",
15+
MCP_AUTHORIZATION: "auth:installation:", // Changed from "mcp:" to avoid collision
16+
TOKEN_EXCHANGE: "auth:exch:",
17+
REFRESH_TOKEN: "auth:refresh:",
1718
} as const;
1819

1920
/**

src/services/auth.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ describe("auth utils", () => {
124124
// instead of using exchangeToken which changes the value
125125
await saveTokenExchange(authCode, tokenExchange);
126126

127-
// Get the key used by saveTokenExchange
128-
const key = "exch:" + crypto.createHash("sha256").update(authCode).digest("hex");
127+
// Get the key used by saveTokenExchange (now with auth: prefix)
128+
const key = "auth:exch:" + crypto.createHash("sha256").update(authCode).digest("hex");
129129

130130
// Get the encrypted data
131131
const encryptedData = await mockRedis.get(key);
@@ -266,8 +266,8 @@ describe("auth utils", () => {
266266

267267
await revokeMcpInstallation(accessToken);
268268

269-
// Should have called getDel with the correct key
270-
expect(getDel).toHaveBeenCalledWith(expect.stringContaining("mcp:"));
269+
// Should have called getDel with the correct key (now auth:installation:)
270+
expect(getDel).toHaveBeenCalledWith(expect.stringContaining("auth:installation:"));
271271

272272
});
273273

0 commit comments

Comments
 (0)