package jwtutils import ( "time" "git.linuxforward.com/byom/byom-core/logger" "github.com/golang-jwt/jwt/v5" "github.com/sirupsen/logrus" ) // Service is the service that provides JWT functionalities // Custom payload can be added to the token type Service struct { secret string logger *logrus.Entry } func NewService(secret string) *Service { return &Service{ secret: secret, logger: logger.NewLogger("jwt"), } } func (s *Service) GenerateToken(email, role string) (string, error) { now := time.Now() claims := jwt.MapClaims{ "sub": email, "exp": now.Add(24 * time.Hour).Unix(), "iat": now.Unix(), "role": role, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) signedToken, err := token.SignedString([]byte(s.secret)) if err != nil { s.logger.WithError(err).Error("failed to sign token") return "", err } return signedToken, nil } func (s *Service) ValidateToken(token string) (jwt.MapClaims, error) { parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { return []byte(s.secret), nil }) if err != nil { s.logger.WithError(err).Error("failed to parse token") return nil, err } claims, ok := parsedToken.Claims.(jwt.MapClaims) if !ok || !parsedToken.Valid { return nil, jwt.ErrSignatureInvalid } if exp, ok := claims["exp"].(float64); ok { if time.Now().Unix() > int64(exp) { return nil, jwt.ErrTokenExpired } } return claims, nil } func (s *Service) ExtractEmailFromClaims(claims jwt.MapClaims) string { email, ok := claims["sub"].(string) if !ok { return "" } return email }