package main import ( "fmt" "time" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" ) const tokenSecret = "tmp" // TODO delete in production const tokenExpiration = time.Hour func TokenCreate(userId uuid.UUID) (string, error) { now := time.Now() signedToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{ Subject: userId.String(), IssuedAt: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(now.Add(tokenExpiration)), }).SignedString([]byte(tokenSecret)) return signedToken, err } func TokenValidateGetId(tokenString string) (uuid.UUID, error) { token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) { if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"]) } return []byte(tokenSecret), nil }) if err != nil { return uuid.UUID{}, err } claims, ok := token.Claims.(jwt.MapClaims) if !ok || !token.Valid { return uuid.UUID{}, fmt.Errorf("invalid token") } exp, ok := claims["exp"].(float64) if !ok || time.Now().Unix() > int64(exp) { return uuid.UUID{}, fmt.Errorf("token expired") } sub, ok := claims["sub"].(string) if !ok { return uuid.UUID{}, fmt.Errorf("invalid subject claim") } id, err := uuid.Parse(sub) if err != nil { return uuid.UUID{}, fmt.Errorf("invalid subject claim") } return id, nil }