ProxyCLI / internal /api /middleware /anthropic_auth.go
PHhTTPS's picture
Replace hardcoded OAuth secrets with placeholders
4998bdc
package middleware
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)
// AuthenticateAnthropicRequest creates a middleware that authenticates requests
// for the Anthropic API using multiple methods (Bearer, X-API-Key, Query).
// It validates the extracted key against the provided list of allowed keys.
func AuthenticateAnthropicRequest(allowedKeys []string) gin.HandlerFunc {
// Convert allowed keys to a map for O(1) lookup
allowedKeyMap := make(map[string]struct{})
for _, key := range allowedKeys {
if key != "" {
allowedKeyMap[key] = struct{}{}
}
}
return func(c *gin.Context) {
var apiKey string
var authMethod string
// 1. Check Authorization Header (Bearer)
authHeader := c.GetHeader("Authorization")
if authHeader != "" {
parts := strings.SplitN(authHeader, " ", 2)
if len(parts) == 2 && strings.EqualFold(parts[0], "Bearer") {
apiKey = strings.TrimSpace(parts[1])
authMethod = "Bearer"
}
}
// 2. Check X-API-Key Header
if apiKey == "" {
apiKey = c.GetHeader("x-api-key")
if apiKey != "" {
authMethod = "X-API-Key"
}
}
// 3. Check Query Parameter
if apiKey == "" {
apiKey = c.Query("api_key")
if apiKey != "" {
authMethod = "QueryParam"
}
}
// Validate
if apiKey == "" {
log.Debug("Anthropic Auth: No credentials provided")
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": map[string]string{
"type": "authentication_error",
"message": "No API key provided",
},
})
return
}
// Check if key is allowed
valid := false
if len(allowedKeyMap) > 0 {
if _, ok := allowedKeyMap[apiKey]; ok {
valid = true
}
} else {
// If no keys configured in proxy, log warning and deny
log.Warn("Anthropic Auth: No allowed keys configured in proxy")
valid = false
}
if !valid {
maskedKey := apiKey
if len(apiKey) > 4 {
maskedKey = apiKey[:4] + "..."
}
log.WithFields(log.Fields{
"method": authMethod,
"key_prefix": maskedKey,
}).Debug("Anthropic Auth: Invalid API key")
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": map[string]string{
"type": "authentication_error",
"message": "Invalid API key",
},
})
return
}
log.WithFields(log.Fields{
"method": authMethod,
}).Debug("Anthropic Auth: Successful")
// Set context variables for downstream handlers
c.Set("apiKey", apiKey)
c.Set("accessProvider", "anthropic")
c.Next()
}
}