jwt.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. ActorType string `json:"actorType,omitempty"`
  16. RoleCode string `json:"roleCode,omitempty"`
  17. jwt.RegisteredClaims
  18. }
  19. func NewManager(issuer, secret string, ttl time.Duration) *Manager {
  20. return &Manager{
  21. issuer: issuer,
  22. secret: []byte(secret),
  23. ttl: ttl,
  24. }
  25. }
  26. func (m *Manager) IssueAccessToken(userID, userPublicID string) (string, time.Time, error) {
  27. return m.IssueActorAccessToken(userID, userPublicID, "user", "")
  28. }
  29. func (m *Manager) IssueActorAccessToken(userID, userPublicID, actorType, roleCode string) (string, time.Time, error) {
  30. expiresAt := time.Now().UTC().Add(m.ttl)
  31. claims := AccessClaims{
  32. UserID: userID,
  33. UserPublicID: userPublicID,
  34. ActorType: actorType,
  35. RoleCode: roleCode,
  36. RegisteredClaims: jwt.RegisteredClaims{
  37. Issuer: m.issuer,
  38. Subject: userID,
  39. ExpiresAt: jwt.NewNumericDate(expiresAt),
  40. IssuedAt: jwt.NewNumericDate(time.Now().UTC()),
  41. },
  42. }
  43. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  44. signed, err := token.SignedString(m.secret)
  45. if err != nil {
  46. return "", time.Time{}, err
  47. }
  48. return signed, expiresAt, nil
  49. }
  50. func (m *Manager) ParseAccessToken(tokenString string) (*AccessClaims, error) {
  51. token, err := jwt.ParseWithClaims(tokenString, &AccessClaims{}, func(token *jwt.Token) (any, error) {
  52. if token.Method != jwt.SigningMethodHS256 {
  53. return nil, fmt.Errorf("unexpected signing method")
  54. }
  55. return m.secret, nil
  56. })
  57. if err != nil {
  58. return nil, err
  59. }
  60. claims, ok := token.Claims.(*AccessClaims)
  61. if !ok || !token.Valid {
  62. return nil, fmt.Errorf("invalid token claims")
  63. }
  64. return claims, nil
  65. }