package auth import ( "strings" "github.com/gin-gonic/gin" "github.com/geo-platform/tenant-api/internal/shared/response" ) func Middleware(jwtMgr *Manager, sessions *SessionStore) gin.HandlerFunc { return func(c *gin.Context) { raw, err := bearerToken(c.GetHeader("Authorization")) if err != nil { response.Error(c, response.ErrUnauthorized(40101, "missing_bearer_token", "Authorization header is required")) c.Abort() return } claims, err := jwtMgr.Parse(raw) if err != nil || claims.Subject != "access" { response.Error(c, response.ErrUnauthorized(40102, "invalid_access_token", "token is invalid or expired")) c.Abort() return } revoked, _ := sessions.IsBlacklisted(c.Request.Context(), claims.ID) if revoked { response.Error(c, response.ErrUnauthorized(40103, "token_revoked", "token has been logged out")) c.Abort() return } actor := Actor{ UserID: claims.UserID, TenantID: claims.TenantID, Role: claims.Role, } c.Request = c.Request.WithContext(WithActor(c.Request.Context(), actor)) c.Next() } } func bearerToken(header string) (string, error) { parts := strings.SplitN(header, " ", 2) if len(parts) != 2 || !strings.EqualFold(parts[0], "bearer") { return "", response.ErrUnauthorized(40101, "missing_bearer_token", "Authorization header is required") } return parts[1], nil }