Files
Tomas Dvorak 823fabee02 de day #74
2025-10-28 22:38:27 +01:00

104 lines
2.6 KiB
Go

package utils
import (
"errors"
"os"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
)
// JWTClaims represents the JWT claims structure
type JWTClaims struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
Role string `json:"role"`
jwt.RegisteredClaims
}
// GenerateJWT generates a new JWT token for the given user
func GenerateJWT(userID uint, email, role string) (string, error) {
// Respect configurable expiration via JWT_EXPIRATION_HOURS; default 24h
expHours := 24
if v := os.Getenv("JWT_EXPIRATION_HOURS"); v != "" {
if n, err := strconv.Atoi(v); err == nil && n > 0 && n <= 24*365 {
expHours = n
}
}
expirationTime := time.Now().Add(time.Duration(expHours) * time.Hour)
claims := &JWTClaims{
UserID: userID,
Email: email,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(expirationTime),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
Issuer: "fotbal-club",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(GetJWTSecret()))
if err != nil {
return "", err
}
return tokenString, nil
}
// ParseJWT parses and validates a JWT token
func ParseJWT(tokenString string) (*JWTClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(GetJWTSecret()), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*JWTClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("invalid token")
}
// GetJWTSecret returns the JWT secret from environment variable or a default value
func GetJWTSecret() string {
secret := os.Getenv("JWT_SECRET")
if secret == "" {
return "default-secret-key-change-in-production"
}
return secret
}
// GetUserFromContext gets the authenticated user from Gin context
func GetUserFromContext(c *gin.Context) (*JWTClaims, error) {
// Preferred: claims set by auth middleware
if v, ok := c.Get("claims"); ok {
if cl, ok2 := v.(*JWTClaims); ok2 {
return cl, nil
}
}
// Fallback: parse Authorization header (Bearer <token>)
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
return nil, errors.New("authorization header missing")
}
parts := strings.Split(authHeader, " ")
if len(parts) != 2 || parts[0] != "Bearer" {
return nil, errors.New("invalid authorization header format")
}
token := parts[1]
cl, err := ParseJWT(token)
if err != nil {
return nil, err
}
return cl, nil
}