| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- package jwtx
- import (
- "fmt"
- "time"
- "github.com/golang-jwt/jwt/v5"
- )
- type Manager struct {
- issuer string
- secret []byte
- ttl time.Duration
- }
- type AccessClaims struct {
- UserID string `json:"uid"`
- UserPublicID string `json:"upub"`
- ActorType string `json:"actorType,omitempty"`
- RoleCode string `json:"roleCode,omitempty"`
- jwt.RegisteredClaims
- }
- func NewManager(issuer, secret string, ttl time.Duration) *Manager {
- return &Manager{
- issuer: issuer,
- secret: []byte(secret),
- ttl: ttl,
- }
- }
- func (m *Manager) IssueAccessToken(userID, userPublicID string) (string, time.Time, error) {
- return m.IssueActorAccessToken(userID, userPublicID, "user", "")
- }
- func (m *Manager) IssueActorAccessToken(userID, userPublicID, actorType, roleCode string) (string, time.Time, error) {
- expiresAt := time.Now().UTC().Add(m.ttl)
- claims := AccessClaims{
- UserID: userID,
- UserPublicID: userPublicID,
- ActorType: actorType,
- RoleCode: roleCode,
- RegisteredClaims: jwt.RegisteredClaims{
- Issuer: m.issuer,
- Subject: userID,
- ExpiresAt: jwt.NewNumericDate(expiresAt),
- IssuedAt: jwt.NewNumericDate(time.Now().UTC()),
- },
- }
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- signed, err := token.SignedString(m.secret)
- if err != nil {
- return "", time.Time{}, err
- }
- return signed, expiresAt, nil
- }
- func (m *Manager) ParseAccessToken(tokenString string) (*AccessClaims, error) {
- token, err := jwt.ParseWithClaims(tokenString, &AccessClaims{}, func(token *jwt.Token) (any, error) {
- if token.Method != jwt.SigningMethodHS256 {
- return nil, fmt.Errorf("unexpected signing method")
- }
- return m.secret, nil
- })
- if err != nil {
- return nil, err
- }
- claims, ok := token.Claims.(*AccessClaims)
- if !ok || !token.Valid {
- return nil, fmt.Errorf("invalid token claims")
- }
- return claims, nil
- }
|