package utils import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "errors" "fmt" "strings" "time" "abuse_registration_poc/internal/config" ) func getAPIKey() (string, error) { apiKey := config.ApiKey if apiKey == "" { return "", fmt.Errorf("API key is not set in the configuration") } return apiKey, nil } func GenerateToken(userName string, userID int64, role string) (string, error) { apiKey, err := getAPIKey() if err != nil { return "", err } header := map[string]string{"alg": "HS256", "typ": "JWT"} claims := map[string]any{ "userName": userName, "userId": userID, "role": role, "exp": time.Now().UTC().Add(2 * time.Hour).Unix(), } headerBytes, err := json.Marshal(header) if err != nil { return "", err } claimsBytes, err := json.Marshal(claims) if err != nil { return "", err } unsigned := base64.RawURLEncoding.EncodeToString(headerBytes) + "." + base64.RawURLEncoding.EncodeToString(claimsBytes) return unsigned + "." + sign(unsigned, apiKey), nil } func VerifyToken(token string) (int64, string, error) { apiKey, err := getAPIKey() if err != nil { return 0, "", err } parts := strings.Split(token, ".") if len(parts) != 3 { return 0, "", errors.New("invalid token") } unsigned := parts[0] + "." + parts[1] expected := sign(unsigned, apiKey) if !hmac.Equal([]byte(expected), []byte(parts[2])) { return 0, "", errors.New("invalid signature") } payload, err := base64.RawURLEncoding.DecodeString(parts[1]) if err != nil { return 0, "", err } var claims map[string]any if err := json.Unmarshal(payload, &claims); err != nil { return 0, "", err } role, ok := claims["role"].(string) if !ok { return 0, "", errors.New("invalid role claim") } userIDFloat, ok := claims["userId"].(float64) if !ok { return 0, "", errors.New("invalid userId claim") } exp, ok := claims["exp"].(float64) if !ok || time.Now().UTC().Unix() > int64(exp) { return 0, "", errors.New("token expired") } return int64(userIDFloat), role, nil } func sign(unsigned string, apiKey string) string { mac := hmac.New(sha256.New, []byte(apiKey)) mac.Write([]byte(unsigned)) return base64.RawURLEncoding.EncodeToString(mac.Sum(nil)) }