package middleware import ( "context" "net/http" "time" "git.linuxforward.com/byop/byop-engine/auth" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) // JWT secret key - in production, this should be loaded from environment variables var jwtSecret = []byte("your-secret-key-here") // Claims represents the JWT claims type Claims struct { UserID string `json:"user_id"` Role string `json:"role"` jwt.RegisteredClaims } // Auth middleware that accepts the auth service as dependency func Auth(authService auth.Service) gin.HandlerFunc { return func(c *gin.Context) { // Get token from request token := extractTokenFromHeader(c) if token == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header required"}) c.Abort() return } // Validate token using the auth service clientID, err := authService.ValidateToken(c.Request.Context(), token) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) c.Abort() return } // Set client ID in context for later use c.Set("clientID", clientID) c.Next() } } // GenerateToken creates a new JWT token for a user func GenerateToken(userID, role string) (string, error) { // Set claims with expiration time claims := &Claims{ UserID: userID, Role: role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), // Token expires in 24 hours IssuedAt: jwt.NewNumericDate(time.Now()), Subject: userID, }, } // Create token with claims token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // Sign the token with the secret key tokenString, err := token.SignedString(jwtSecret) if err != nil { return "", err } return tokenString, nil } // GetUserIDFromContext retrieves the user ID from the request context func GetUserIDFromContext(ctx context.Context) string { userID, ok := ctx.Value("user_id").(string) if !ok { return "" } return userID } // GetRoleFromContext retrieves the user role from the request context func GetRoleFromContext(ctx context.Context) string { role, ok := ctx.Value("role").(string) if !ok { return "" } return role } // IsAdmin checks if the user in the context has admin role func IsAdmin(ctx context.Context) bool { role := GetRoleFromContext(ctx) return role == "admin" } // extractTokenFromHeader gets the JWT token from the Authorization header func extractTokenFromHeader(c *gin.Context) string { authHeader := c.GetHeader("Authorization") if authHeader == "" { return "" } // Check if the header has the format "Bearer " if len(authHeader) > 7 && authHeader[:7] == "Bearer " { return authHeader[7:] } return "" }