package middleware import ( "net/http" "strings" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // HeaderInternalAPIKey is the header name for Stream Server callback authentication const HeaderInternalAPIKey = "X-Internal-API-Key" // StreamCallbackAuth returns a Gin middleware that validates X-Internal-API-Key // for the stream-ready callback route. Used to authenticate callbacks from the Stream Server. // If expectedKey is empty, all requests are rejected (fail-secure). func StreamCallbackAuth(expectedKey string, logger *zap.Logger) gin.HandlerFunc { return func(c *gin.Context) { if expectedKey == "" { logger.Warn("Stream callback auth: STREAM_SERVER_INTERNAL_API_KEY not configured, rejecting request") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "error": gin.H{ "code": 1001, "message": "Internal API key required", }, }) c.Abort() return } provided := c.GetHeader(HeaderInternalAPIKey) if provided == "" { provided = c.GetHeader("X-Stream-Server-API-Key") } provided = strings.TrimSpace(provided) if provided != expectedKey { logger.Warn("Stream callback auth: invalid or missing API key", zap.String("path", c.Request.URL.Path), ) c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "error": gin.H{ "code": 1001, "message": "Invalid or missing internal API key", }, }) c.Abort() return } c.Next() } }