Skip to content

Commit e0b2354

Browse files
committed
fix(oauth): reject non-Bearer auth schemes and handle malformed tokens
Signed-off-by: Tommy Nguyen <tuannvm@hotmail.com>
1 parent 7131d3b commit e0b2354

File tree

2 files changed

+22
-25
lines changed

2 files changed

+22
-25
lines changed

mcp/oauth.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import (
3939
// The returned handler automatically:
4040
// - Returns 401 with WWW-Authenticate headers if Bearer token missing
4141
// - Passes through OPTIONS requests (CORS pre-flight)
42-
// - Passes through non-Bearer auth schemes (e.g., Basic auth)
42+
// - Rejects non-Bearer auth schemes (OAuth-only endpoint)
4343
//
4444
// The returned oauth.Server instance provides access to:
4545
// - LogStartup() - Log OAuth endpoint information
@@ -76,16 +76,15 @@ func WithOAuth(mux *http.ServeMux, cfg *oauth.Config, mcpServer *mcp.Server) (*o
7676
}
7777

7878
// Check if it's a Bearer token (case-insensitive per OAuth 2.0 spec)
79-
if strings.HasPrefix(authLower, "bearer") {
80-
// Malformed Bearer token (no space after "Bearer")
81-
if !strings.HasPrefix(authLower, "bearer ") {
82-
oauthServer.Return401InvalidToken(w)
83-
return
84-
}
85-
// Valid Bearer format, continue to validation
86-
} else {
87-
// Pass through non-Bearer schemes (e.g., Basic auth)
88-
mcpHandler.ServeHTTP(w, r)
79+
if !strings.HasPrefix(authLower, "bearer") {
80+
// Reject non-Bearer schemes (OAuth endpoints require Bearer tokens only)
81+
oauthServer.Return401(w)
82+
return
83+
}
84+
85+
// Malformed Bearer token (no space after "Bearer")
86+
if !strings.HasPrefix(authLower, "bearer ") {
87+
oauthServer.Return401InvalidToken(w)
8988
return
9089
}
9190

oauth.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,12 @@ func (s *Server) WrapHandlerFunc(next http.HandlerFunc) http.HandlerFunc {
314314
}
315315

316316
// WrapMCPEndpoint wraps an MCP endpoint handler with automatic 401 handling.
317-
// Returns 401 with WWW-Authenticate headers if Bearer token is missing.
317+
// Returns 401 with WWW-Authenticate headers if Bearer token is missing or invalid.
318318
//
319319
// This method provides automatic OAuth discovery for MCP clients by:
320320
// - Passing through OPTIONS requests (CORS pre-flight)
321-
// - Passing through non-Bearer auth schemes (e.g., Basic auth)
322-
// - Returning 401 with proper headers if Bearer token is missing
321+
// - Rejecting non-Bearer auth schemes (OAuth-only endpoint)
322+
// - Returning 401 with proper headers if Bearer token is missing/malformed
323323
// - Extracting token to context and passing to wrapped handler
324324
//
325325
// Usage with mark3labs SDK:
@@ -347,17 +347,15 @@ func (s *Server) WrapMCPEndpoint(handler http.Handler) http.HandlerFunc {
347347
}
348348

349349
// Check if it's a Bearer token (case-insensitive per OAuth 2.0 spec)
350-
if strings.HasPrefix(authLower, "bearer") {
351-
// Malformed Bearer token (no space after "Bearer")
352-
if !strings.HasPrefix(authLower, "bearer ") {
353-
s.Return401InvalidToken(w)
354-
return
355-
}
356-
// Valid Bearer format, extract to context
357-
// (validation happens in downstream middleware)
358-
} else {
359-
// Pass through non-Bearer schemes (e.g., Basic auth)
360-
handler.ServeHTTP(w, r)
350+
if !strings.HasPrefix(authLower, "bearer") {
351+
// Reject non-Bearer schemes (OAuth endpoints require Bearer tokens only)
352+
s.Return401(w)
353+
return
354+
}
355+
356+
// Malformed Bearer token (no space after "Bearer")
357+
if !strings.HasPrefix(authLower, "bearer ") {
358+
s.Return401InvalidToken(w)
361359
return
362360
}
363361

0 commit comments

Comments
 (0)