Skip to content

Commit 54cd936

Browse files
Copilotpelikhan
andcommitted
Add root-level OAuth discovery endpoint returning 404
- Add handler at /.well-known/oauth-authorization-server for both unified and routed modes - Prevents requests from hanging by returning immediate 404 response - Add comprehensive tests for both root and MCP-prefixed OAuth discovery paths - Fixes timeout issues with Codex MCP client OAuth discovery attempts Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent bf42aae commit 54cd936

4 files changed

Lines changed: 80 additions & 4 deletions

File tree

internal/server/routed.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ func CreateHTTPServerForRoutedMode(addr string, unifiedServer *UnifiedServer, ap
8282
logRouted.Printf("Creating HTTP server for routed mode: addr=%s", addr)
8383
mux := http.NewServeMux()
8484

85-
// OAuth discovery endpoint - return 404 since we don't use OAuth
85+
// OAuth discovery endpoints - return 404 since we don't use OAuth
86+
// Standard path for OAuth discovery (per RFC 8414)
87+
mux.Handle("/.well-known/oauth-authorization-server", withResponseLogging(handleOAuthDiscovery()))
88+
// MCP-prefixed path for backward compatibility
8689
mux.Handle("/mcp/.well-known/oauth-authorization-server", withResponseLogging(handleOAuthDiscovery()))
8790

8891
// Create routes for all backends, plus sys only if DIFC is enabled

internal/server/routed_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,3 +553,61 @@ func TestCreateFilteredServer_EdgeCases(t *testing.T) {
553553
assert.Equal(t, "tool2", backend2Tools[0].Name)
554554
})
555555
}
556+
557+
// TestCreateHTTPServerForRoutedMode_OAuth tests OAuth discovery endpoint in routed mode
558+
func TestCreateHTTPServerForRoutedMode_OAuth(t *testing.T) {
559+
tests := []struct {
560+
name string
561+
path string
562+
method string
563+
wantStatusCode int
564+
}{
565+
{
566+
name: "OAuthDiscovery_GET_MCPPath",
567+
path: "/mcp/.well-known/oauth-authorization-server",
568+
method: "GET",
569+
wantStatusCode: http.StatusNotFound,
570+
},
571+
{
572+
name: "OAuthDiscovery_POST_MCPPath",
573+
path: "/mcp/.well-known/oauth-authorization-server",
574+
method: "POST",
575+
wantStatusCode: http.StatusNotFound,
576+
},
577+
{
578+
name: "OAuthDiscovery_GET_RootPath",
579+
path: "/.well-known/oauth-authorization-server",
580+
method: "GET",
581+
wantStatusCode: http.StatusNotFound,
582+
},
583+
{
584+
name: "OAuthDiscovery_POST_RootPath",
585+
path: "/.well-known/oauth-authorization-server",
586+
method: "POST",
587+
wantStatusCode: http.StatusNotFound,
588+
},
589+
}
590+
591+
// Create minimal unified server
592+
ctx := context.Background()
593+
cfg := &config.Config{
594+
Servers: map[string]*config.ServerConfig{},
595+
}
596+
us, err := NewUnified(ctx, cfg)
597+
require.NoError(t, err)
598+
defer us.Close()
599+
600+
// Create HTTP server in routed mode without API key
601+
httpServer := CreateHTTPServerForRoutedMode(":0", us, "")
602+
603+
for _, tt := range tests {
604+
t.Run(tt.name, func(t *testing.T) {
605+
req := httptest.NewRequest(tt.method, tt.path, nil)
606+
w := httptest.NewRecorder()
607+
608+
httpServer.Handler.ServeHTTP(w, req)
609+
610+
assert.Equal(t, tt.wantStatusCode, w.Code, "Should return 404 for OAuth discovery")
611+
})
612+
}
613+
}

internal/server/transport.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ func CreateHTTPServerForMCP(addr string, unifiedServer *UnifiedServer, apiKey st
6060
logTransport.Printf("Creating HTTP server for MCP: addr=%s, auth_enabled=%v", addr, apiKey != "")
6161
mux := http.NewServeMux()
6262

63-
// OAuth discovery endpoint - return 404 since we don't use OAuth
63+
// OAuth discovery endpoints - return 404 since we don't use OAuth
64+
// Standard path for OAuth discovery (per RFC 8414)
65+
mux.Handle("/.well-known/oauth-authorization-server", withResponseLogging(handleOAuthDiscovery()))
66+
// MCP-prefixed path for backward compatibility
6467
mux.Handle("/mcp/.well-known/oauth-authorization-server", withResponseLogging(handleOAuthDiscovery()))
6568

6669
logTransport.Print("Registering streamable HTTP handler for MCP protocol")

internal/server/transport_test.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,17 +233,29 @@ func TestCreateHTTPServerForMCP_OAuth(t *testing.T) {
233233
wantStatusCode int
234234
}{
235235
{
236-
name: "OAuthDiscovery_GET",
236+
name: "OAuthDiscovery_GET_MCPPath",
237237
path: "/mcp/.well-known/oauth-authorization-server",
238238
method: "GET",
239239
wantStatusCode: http.StatusNotFound,
240240
},
241241
{
242-
name: "OAuthDiscovery_POST",
242+
name: "OAuthDiscovery_POST_MCPPath",
243243
path: "/mcp/.well-known/oauth-authorization-server",
244244
method: "POST",
245245
wantStatusCode: http.StatusNotFound,
246246
},
247+
{
248+
name: "OAuthDiscovery_GET_RootPath",
249+
path: "/.well-known/oauth-authorization-server",
250+
method: "GET",
251+
wantStatusCode: http.StatusNotFound,
252+
},
253+
{
254+
name: "OAuthDiscovery_POST_RootPath",
255+
path: "/.well-known/oauth-authorization-server",
256+
method: "POST",
257+
wantStatusCode: http.StatusNotFound,
258+
},
247259
}
248260

249261
// Create minimal unified server

0 commit comments

Comments
 (0)