99 lines
2.2 KiB
Go
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))
|
|
}
|