auth.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package middleware
  2. import (
  3. "net/http"
  4. "strings"
  5. "github.com/celestia-trace/backend/config"
  6. "github.com/gin-gonic/gin"
  7. "github.com/golang-jwt/jwt/v5"
  8. )
  9. // Auth middleware validates JWT token
  10. func Auth(cfg *config.Config) gin.HandlerFunc {
  11. return func(c *gin.Context) {
  12. authHeader := c.GetHeader("Authorization")
  13. if authHeader == "" {
  14. c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "missing authorization header"})
  15. c.Abort()
  16. return
  17. }
  18. parts := strings.Split(authHeader, " ")
  19. if len(parts) != 2 || parts[0] != "Bearer" {
  20. c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid authorization header format"})
  21. c.Abort()
  22. return
  23. }
  24. tokenString := parts[1]
  25. token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
  26. if token.Method.Alg() != jwt.SigningMethodHS256.Alg() {
  27. return nil, jwt.ErrSignatureInvalid
  28. }
  29. return []byte(cfg.JWTSecret), nil
  30. }, jwt.WithIssuer("celestia-trace"), jwt.WithExpirationRequired())
  31. if err != nil || !token.Valid {
  32. c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid token"})
  33. c.Abort()
  34. return
  35. }
  36. claims, ok := token.Claims.(jwt.MapClaims)
  37. if !ok {
  38. c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid token claims"})
  39. c.Abort()
  40. return
  41. }
  42. userID, ok := claims["sub"].(string)
  43. if !ok {
  44. c.JSON(http.StatusUnauthorized, gin.H{"code": 401, "message": "invalid subject in token"})
  45. c.Abort()
  46. return
  47. }
  48. // Set user ID for downstream handlers
  49. c.Set("userID", userID)
  50. if sessionID, ok := claims["sid"].(string); ok {
  51. c.Set("sessionID", sessionID)
  52. }
  53. c.Next()
  54. }
  55. }