Files
ez-api/internal/middleware/internal_auth.go
zenfun 4cd9b66a84 feat(auth): enhance token validation and internal access control
Refactor the `Whoami` handler to validate token metadata (status, expiration,
revocation) against Redis before database lookup, ensuring consistency with
balancer logic. Add `allow_ips`, `deny_ips`, and `expires_at` fields to
authentication responses.

Update internal middleware to support explicit anonymous access configuration
and harden security for unconfigured tokens.

Remove legacy fallback logic for master keys without digests.

BREAKING CHANGE: Internal endpoints now reject requests by default if no stats token is configured. To allow unauthenticated access, set `internal.allow_anonymous` to true.
BREAKING CHANGE: Support for legacy master keys without stored digests has been removed.
2026-01-03 16:04:04 +08:00

42 lines
1.1 KiB
Go

package middleware
import (
"log/slog"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// InternalAuthMiddleware protects internal endpoints.
// - If allowAnonymous is true, bypass all token checks and log INFO.
// - If allowAnonymous is false and expectedToken is empty, reject all requests.
// - Otherwise, require X-Internal-Token header to match expectedToken.
func InternalAuthMiddleware(expectedToken string, allowAnonymous bool) gin.HandlerFunc {
expectedToken = strings.TrimSpace(expectedToken)
return func(c *gin.Context) {
if allowAnonymous {
slog.Info("internal endpoint accessed anonymously",
"path", c.Request.URL.Path,
"remote_addr", c.ClientIP())
c.Next()
return
}
// If token is empty and anonymous is not allowed, reject
if expectedToken == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "internal authentication required but not configured"})
c.Abort()
return
}
token := strings.TrimSpace(c.GetHeader("X-Internal-Token"))
if token == "" || token != expectedToken {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid internal token"})
c.Abort()
return
}
c.Next()
}
}