jwt.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package jwtx
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/golang-jwt/jwt/v5"
  6. )
  7. type Manager struct {
  8. issuer string
  9. secret []byte
  10. ttl time.Duration
  11. }
  12. type AccessClaims struct {
  13. UserID string `json:"uid"`
  14. UserPublicID string `json:"upub"`
  15. jwt.RegisteredClaims
  16. }
  17. func NewManager(issuer, secret string, ttl time.Duration) *Manager {
  18. return &Manager{
  19. issuer: issuer,
  20. secret: []byte(secret),
  21. ttl: ttl,
  22. }
  23. }
  24. func (m *Manager) IssueAccessToken(userID, userPublicID string) (string, time.Time, error) {
  25. expiresAt := time.Now().UTC().Add(m.ttl)
  26. claims := AccessClaims{
  27. UserID: userID,
  28. UserPublicID: userPublicID,
  29. RegisteredClaims: jwt.RegisteredClaims{
  30. Issuer: m.issuer,
  31. Subject: userID,
  32. ExpiresAt: jwt.NewNumericDate(expiresAt),
  33. IssuedAt: jwt.NewNumericDate(time.Now().UTC()),
  34. },
  35. }
  36. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  37. signed, err := token.SignedString(m.secret)
  38. if err != nil {
  39. return "", time.Time{}, err
  40. }
  41. return signed, expiresAt, nil
  42. }
  43. func (m *Manager) ParseAccessToken(tokenString string) (*AccessClaims, error) {
  44. token, err := jwt.ParseWithClaims(tokenString, &AccessClaims{}, func(token *jwt.Token) (any, error) {
  45. if token.Method != jwt.SigningMethodHS256 {
  46. return nil, fmt.Errorf("unexpected signing method")
  47. }
  48. return m.secret, nil
  49. })
  50. if err != nil {
  51. return nil, err
  52. }
  53. claims, ok := token.Claims.(*AccessClaims)
  54. if !ok || !token.Valid {
  55. return nil, fmt.Errorf("invalid token claims")
  56. }
  57. return claims, nil
  58. }