-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtoken_manager.go
76 lines (60 loc) · 1.71 KB
/
token_manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package jwt
import (
"errors"
"fmt"
"strings"
"github.com/golang-jwt/jwt/v5"
)
const (
scheme = "bearer"
)
type TokenManager struct {
key []byte
method jwt.SigningMethod
}
func New(opts ...Option) (*TokenManager, error) {
t := &TokenManager{
method: jwt.SigningMethodHS256,
}
for _, opt := range opts {
opt.apply(t)
}
if len(t.key) == 0 {
return nil, fmt.Errorf("secret key must be set, use With* option")
}
return t, nil
}
// CreateWithClaims creates and returns a complete, signed JWT.
func (t *TokenManager) CreateWithClaims(claims jwt.Claims) (string, error) {
token := jwt.NewWithClaims(t.method, claims)
s, err := token.SignedString(t.key)
if err != nil {
return "", fmt.Errorf("%w: %w", ErrTokenSigned, err)
}
return s, nil
}
// ParseWithClaims parses, validates, verifies the signature and returns the parsed expClaims.
func (t *TokenManager) ParseWithClaims(tokenString string, claims jwt.Claims) error {
splits := strings.SplitN(tokenString, " ", 2)
if len(splits) < 2 {
return fmt.Errorf("%w: split token string < 2", ErrInvalidToken)
}
if !strings.EqualFold(splits[0], scheme) {
return fmt.Errorf("%w: token string must contains bearer scheme", ErrInvalidScheme)
}
token, err := jwt.ParseWithClaims(splits[1], claims, func(_ *jwt.Token) (interface{}, error) { return t.key, nil })
if err != nil {
switch {
case errors.Is(err, jwt.ErrSignatureInvalid):
return fmt.Errorf("%w: %w", ErrInvalidSignature, err)
case errors.Is(err, jwt.ErrTokenInvalidClaims):
return fmt.Errorf("%w: %w", ErrTokenRestriction, err)
default:
return fmt.Errorf("%w: %w", ErrInvalidToken, err)
}
}
if !token.Valid {
return fmt.Errorf("%w: invalid token", ErrInvalidToken)
}
return nil
}