Files
abuse-registration-api-golang/internal/utils/jwt.go
T

99 lines
2.2 KiB
Go

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))
}