package main import ( "errors" "fmt" "strconv" "time" "github.com/golang-jwt/jwt/v5" ) var secretKey = []byte("replace-with-env-variable") type UserClaims struct { Name string `json:"name"` Color string `json:"color"` jwt.RegisteredClaims } func GetToken(user *User) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims{ Name: user.Name, Color: string(user.Color[:]), RegisteredClaims: jwt.RegisteredClaims{ Subject: strconv.Itoa(int(user.Id)), ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, }, ) return token.SignedString(secretKey) } func GetUserFromToken(tokenString string) (User, error) { token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, 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 secretKey, nil }) if err != nil { return User{}, err } claims, ok := token.Claims.(*UserClaims) if !ok || !token.Valid { return User{}, errors.New("invalid token") } id, err := strconv.ParseUint(claims.Subject, 10, 64) if err != nil { return User{}, fmt.Errorf("invalid subject: %w", err) } var color [3]byte copy(color[:], claims.Color) return User{ Id: id, Name: claims.Name, Color: color, }, nil }