feat(auth): per-caller Gitea PAT pass-through (#59)
Replaces the shared GITEA_MCP_DEFAULT_TOKEN for all callers. When a request's bearer validates directly against Gitea's own /api/v1/user, that token is used for every upstream call this request makes instead of the service PAT, and the caller identity comes from Gitea's own login rather than the proxy header. Any other bearer (static token, JWT, none) falls through unchanged to the existing chassis auth. Prep: Authentik now SSOs into Gitea (infra a32801c), so each real user can mint their own PAT from their own linked account. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.d-ma.be/mathias/gitea-mcp/internal/gitea"
|
||||
)
|
||||
|
||||
// TokenValidator asks the upstream service who a bearer token belongs to.
|
||||
type TokenValidator interface {
|
||||
ValidateToken(ctx context.Context, token string) (username string, ok bool)
|
||||
}
|
||||
|
||||
// PassthroughMiddleware lets a caller authenticate with their own Gitea PAT:
|
||||
// if the request's bearer token validates directly against Gitea, it's used
|
||||
// as-is for every upstream call this request makes (gitea-mcp#59), instead of
|
||||
// the server's shared default token. Any other bearer (static token, JWT, or
|
||||
// none) falls through to fallback unchanged — this only adds a capability, it
|
||||
// never removes the existing auth paths.
|
||||
func PassthroughMiddleware(validator TokenValidator, onValid, fallback http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
authz := r.Header.Get("Authorization")
|
||||
token, hasBearer := strings.CutPrefix(authz, "Bearer ")
|
||||
if hasBearer && token != "" {
|
||||
if login, ok := validator.ValidateToken(r.Context(), token); ok {
|
||||
ctx := withCaller(r.Context(), login)
|
||||
ctx = gitea.WithToken(ctx, token)
|
||||
onValid.ServeHTTP(w, r.WithContext(ctx))
|
||||
return
|
||||
}
|
||||
}
|
||||
fallback.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user