fix(brain-mcp): static Bearer short-circuits before OAuth challenge
Reorders BearerAuth so a valid BRAIN_MCP_TOKEN match wins instantly and never emits WWW-Authenticate. Adds RFC 9728 resource_metadata challenge header on 401 (only when MCP_RESOURCE_URL is configured) so claude.ai's OAuth-discovery path still works. Why: claude CLI on koala/flamingo with `.mcp.json` `Authorization: Bearer $BRAIN_MCP_TOKEN` was being kicked into RFC 7591 dynamic client registration against Dex (static-only) and dying. Cause was the auth middleware running JWT validation first and emitting an OAuth challenge on the fall-through 401 even when the caller had a valid static token. Inverting the precedence and gating the challenge on resourceMetadataURL keeps the LAN/Tailscale CLI path silent and only invites OAuth discovery on actually-unauthenticated requests. Regression guards in the test file: - valid static Bearer 200 has no WWW-Authenticate - 401 with resourceMetadataURL set carries the challenge - 401 with empty resourceMetadataURL emits no challenge Closes hyperguild#9 in code. Live verification (claude CLI on koala listing brain tools) blocked on ingestion image rebuild + redeploy.
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mathiasbq/hyperguild/ingestion/internal/api"
|
||||
@@ -112,14 +113,21 @@ func main() {
|
||||
logger.Info("jwt auth enabled", "issuer", dexURL)
|
||||
}
|
||||
|
||||
mux.Handle("/mcp", mcp.BearerAuth(mcpToken, jwtValidator, mcpSrv))
|
||||
|
||||
// Resource-metadata URL is only emitted on 401 when Dex OAuth is
|
||||
// configured. Static-Bearer-only deployments leave this empty so
|
||||
// clients never see an OAuth challenge.
|
||||
var resourceMetadataURL string
|
||||
if dexURL := os.Getenv("DEX_ISSUER_URL"); dexURL != "" {
|
||||
resourceURL := os.Getenv("MCP_RESOURCE_URL")
|
||||
mux.HandleFunc("GET /.well-known/oauth-protected-resource",
|
||||
auth.ProtectedResourceHandler(resourceURL, os.Getenv("DEX_ISSUER_URL")))
|
||||
auth.ProtectedResourceHandler(resourceURL, dexURL))
|
||||
if resourceURL != "" {
|
||||
resourceMetadataURL = strings.TrimRight(resourceURL, "/") + "/.well-known/oauth-protected-resource"
|
||||
}
|
||||
}
|
||||
|
||||
mux.Handle("/mcp", mcp.BearerAuth(mcpToken, jwtValidator, resourceMetadataURL, mcpSrv))
|
||||
|
||||
addr := ":" + port
|
||||
watchIntervalLog := "disabled"
|
||||
if watchInterval > 0 {
|
||||
|
||||
Reference in New Issue
Block a user