Previously BearerMiddleware allowed requests with no Authorization
header to pass through whenever GITEA_MCP_DEFAULT_TOKEN was set. The
intent was "fall back to the service PAT for upstream Gitea calls,"
but the side effect was that anyone could hit /mcp anonymously and the
server would happily proxy requests as the service account.
Drop that path. Auth on /mcp now requires either:
- a valid Dex-issued JWT, or
- a Bearer matching GITEA_MCP_STATIC_TOKEN.
The Gitea service PAT (GITEA_MCP_DEFAULT_TOKEN) is no longer wired
into BearerMiddleware at all — it stays an upstream-client concern,
used by gitea.NewClient for outbound API calls only. This decouples
"can this caller invoke a tool" from "what credentials does the tool
use against Gitea".
Tests updated: drop the NoAuthHeader_WithDefault permissive case, add
NoAuthHeader_RejectsEvenWhenStaticConfigured to lock in the new
behavior.
Closes part of mathias/infra#2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- internal/auth/jwt.go: JWTValidator via lestrrat-go/jwx/v2, JWKS auto-refresh
- internal/auth/bearer.go: replace Gitea PAT validation with JWT->static->default chain
- internal/gitea/client.go: always use service PAT; remove TokenFromContext lookup
- internal/config/config.go: add DexIssuerURL, MCPAudience, MCPResourceURL, StaticToken
- cmd/gitea-mcp/main.go: wire validator, fix /.well-known to return real AS list
- bearer_test.go: rewrite for new API
claude.ai connectors call the server with no Authorization header (confirmed
via request logging). Add a configurable default Gitea PAT so unauthenticated
clients (like claude.ai) can still reach the server.
Claude Code continues to pass per-request PATs; defaultToken="" preserves
the existing strict behaviour when the env var is unset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Callers now supply their own Gitea PAT as a Bearer token; the server validates
it against GET /api/v1/user and threads it through context to all downstream
Gitea API calls. GITEA_API_TOKEN env var and the GiteaAPIToken config field are
removed.