Skip to content

Commit 7aae521

Browse files
committed
feat(auth): enhance OAuth authentication for HttpStreamTransport and SSEServerTransport with comprehensive tests
1 parent 4113ada commit 7aae521

File tree

5 files changed

+708
-7
lines changed

5 files changed

+708
-7
lines changed

src/transports/http/server.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,28 @@ export class HttpStreamTransport extends AbstractTransport {
165165
await transport.handleRequest(req, res, body);
166166
return;
167167
} else {
168+
if (this._config.auth?.endpoints?.messages !== false) {
169+
const isAuthenticated = await this.handleAuthentication(req, res, 'message');
170+
if (!isAuthenticated) return;
171+
}
172+
168173
this.sendError(res, 400, -32000, 'Bad Request: No valid session ID provided');
169174
return;
170175
}
171176
} else if (!sessionId) {
177+
if (this._config.auth?.endpoints?.messages !== false) {
178+
const isAuthenticated = await this.handleAuthentication(req, res, 'message');
179+
if (!isAuthenticated) return;
180+
}
181+
172182
this.sendError(res, 400, -32000, 'Bad Request: No valid session ID provided');
173183
return;
174184
} else {
185+
if (this._config.auth?.endpoints?.messages !== false) {
186+
const isAuthenticated = await this.handleAuthentication(req, res, 'message');
187+
if (!isAuthenticated) return;
188+
}
189+
175190
this.sendError(res, 404, -32001, 'Session not found');
176191
return;
177192
}
@@ -247,6 +262,9 @@ export class HttpStreamTransport extends AbstractTransport {
247262
if (isApiKey) {
248263
const provider = this._config.auth.provider as APIKeyAuthProvider;
249264
res.setHeader('WWW-Authenticate', `ApiKey realm="MCP Server", header="${provider.getHeaderName()}"`);
265+
} else if (this._config.auth.provider instanceof OAuthAuthProvider) {
266+
const provider = this._config.auth.provider as OAuthAuthProvider;
267+
res.setHeader('WWW-Authenticate', provider.getWWWAuthenticateHeader('invalid_token', 'Missing or invalid authentication token'));
250268
}
251269

252270
res.writeHead(error.status).end(

src/transports/sse/server.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ export class SSEServerTransport extends AbstractTransport {
167167
}
168168

169169
if (req.method === "POST" && url.pathname === this._config.messageEndpoint) {
170+
if (this._config.auth?.endpoints?.messages !== false) {
171+
const isAuthenticated = await this.handleAuthentication(req, res, "message")
172+
if (!isAuthenticated) return
173+
}
174+
170175
// **Connection Validation (User Requested):**
171176
// Check if the 'sessionId' from the POST request URL query parameter
172177
// (which should contain a connectionId provided by the server via the 'endpoint' event)
@@ -178,11 +183,6 @@ export class SSEServerTransport extends AbstractTransport {
178183
return;
179184
}
180185

181-
if (this._config.auth?.endpoints?.messages !== false) {
182-
const isAuthenticated = await this.handleAuthentication(req, res, "message")
183-
if (!isAuthenticated) return
184-
}
185-
186186
await this.handlePostMessage(req, res)
187187
return
188188
}
@@ -222,8 +222,11 @@ export class SSEServerTransport extends AbstractTransport {
222222
if (isApiKey) {
223223
const provider = this._config.auth.provider as APIKeyAuthProvider
224224
res.setHeader("WWW-Authenticate", `ApiKey realm="MCP Server", header="${provider.getHeaderName()}"`)
225+
} else if (this._config.auth.provider instanceof OAuthAuthProvider) {
226+
const provider = this._config.auth.provider as OAuthAuthProvider
227+
res.setHeader("WWW-Authenticate", provider.getWWWAuthenticateHeader('invalid_token', 'Missing or invalid authentication token'))
225228
}
226-
229+
227230
res.writeHead(error.status).end(JSON.stringify({
228231
error: error.message,
229232
status: error.status,

tests/auth/validators/introspection-validator.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ describe('IntrospectionValidator', () => {
230230
await validator.validate(token);
231231
const cachedCallTime = Date.now() - cachedStartTime;
232232

233-
expect(cachedCallTime).toBeLessThan(firstCallTime);
233+
expect(cachedCallTime).toBeLessThanOrEqual(firstCallTime);
234234
});
235235

236236
it('should expire cache after TTL', async () => {

0 commit comments

Comments
 (0)