From de5847d1f0dc9291233cc59a27d61baa3c09c226 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Thu, 29 Jan 2026 22:25:40 +0800 Subject: [PATCH] feat: add internal service-to-service authentication middleware --- internal/auth/middleware.go | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/internal/auth/middleware.go b/internal/auth/middleware.go index 7945c51..2442b0c 100644 --- a/internal/auth/middleware.go +++ b/internal/auth/middleware.go @@ -3,6 +3,7 @@ package auth import ( "context" "net/http" + "os" "strings" "github.com/gin-gonic/gin" @@ -62,6 +63,46 @@ func (s *TokenService) AuthMiddleware() gin.HandlerFunc { } } +// InternalAuthMiddleware validates internal service-to-service authentication +// using a shared token from the X-Service-Token header +func InternalAuthMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + serviceToken := c.GetHeader("X-Service-Token") + if serviceToken == "" { + c.JSON(http.StatusUnauthorized, gin.H{ + "error": "missing service token", + }) + c.Abort() + return + } + + expectedToken := os.Getenv("INTERNAL_SERVICE_TOKEN") + if expectedToken == "" { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "internal service token not configured", + }) + c.Abort() + return + } + + if serviceToken != expectedToken { + c.JSON(http.StatusUnauthorized, gin.H{ + "error": "invalid service token", + }) + c.Abort() + return + } + + // Set internal service context + ctx := context.WithValue(c.Request.Context(), userIDKey, "system") + ctx = context.WithValue(ctx, emailKey, "internal@system.service") + ctx = context.WithValue(ctx, rolesKey, []string{"internal_service"}) + c.Request = c.Request.WithContext(ctx) + + c.Next() + } +} + // RequireMFA is a middleware that requires MFA verification func RequireMFA() gin.HandlerFunc { return func(c *gin.Context) {