mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 17:47:51 +00:00
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.
This commit is contained in:
@@ -1,20 +1,35 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InternalAuthMiddleware(expectedToken string) gin.HandlerFunc {
|
||||
// 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 expectedToken == "" {
|
||||
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"})
|
||||
|
||||
Reference in New Issue
Block a user