-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjwt.go
148 lines (125 loc) · 3.16 KB
/
jwt.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package auth
import (
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
)
var defaultParser = jwt.NewParser()
// NewJWT function get secret key and options and return a new JWT instance.
//
// Default expiration function is time.Now().Add(time.Hour).Unix().
func NewJWT(opts ...OptionJWT) (*JWT, error) {
o := optionJWT{
expFunc: func() int64 {
return time.Now().Add(time.Hour).Unix()
},
}
for _, opt := range opts {
opt(&o)
}
if o.kid == "" {
return nil, fmt.Errorf("kid is required")
}
if o.method == nil {
return nil, fmt.Errorf("method is required")
}
var secret interface{}
var public interface{}
switch o.method.(type) {
case *jwt.SigningMethodHMAC:
secret = o.secretByte
public = o.secretByte
case *jwt.SigningMethodRSAPSS:
secret = o.secretRSAPrivate
if o.secretRSAPublic != nil {
public = o.secretRSAPublic
} else {
public = o.secretRSAPrivate.Public()
}
case *jwt.SigningMethodRSA:
secret = o.secretRSAPrivate
if o.secretRSAPublic != nil {
public = o.secretRSAPublic
} else {
public = o.secretRSAPrivate.Public()
}
case *jwt.SigningMethodECDSA:
secret = o.secretECDSAPrivate
if o.secretECDSAPublic != nil {
public = o.secretECDSAPublic
} else {
public = o.secretECDSAPrivate.Public()
}
default:
return nil, fmt.Errorf("unsupported method")
}
if secret == nil || public == nil {
return nil, fmt.Errorf("secret and public key is required")
}
return &JWT{
secret: secret,
public: public,
method: o.method,
expFunc: o.expFunc,
kid: o.kid,
}, nil
}
type JWT struct {
secret interface{}
public interface{}
method jwt.SigningMethod
expFunc func() int64
kid string
}
func (t *JWT) ExpFunc() int64 {
return t.expFunc()
}
// Generate function get custom values and add 'exp' as expires at with expDate argument with unix format.
func (t *JWT) Generate(mapClaims map[string]interface{}, expDate int64) (string, error) {
claims := jwt.MapClaims{}
for k := range mapClaims {
claims[k] = mapClaims[k]
}
if expDate > 0 {
claims["exp"] = expDate
}
token := jwt.NewWithClaims(t.method, claims)
// header part
if t.kid != "" {
token.Header["kid"] = t.kid
}
if t.method.Alg() != "" {
token.Header["alg"] = t.method.Alg()
}
tokenString, err := token.SignedString(t.secret)
if err != nil {
err = fmt.Errorf("cannot sign: %w", err)
}
return tokenString, err
}
// Parse is validating and getting claims.
func (t *JWT) Parse(tokenStr string, claims jwt.Claims) (*jwt.Token, error) {
token, err := jwt.ParseWithClaims(
tokenStr,
claims,
func(token *jwt.Token) (interface{}, error) {
return t.public, nil
},
jwt.WithValidMethods([]string{t.method.Alg()}),
)
if err != nil {
return nil, fmt.Errorf("token validate: %w", err)
}
return token, nil
}
// Renew token with not changing claims.
func (t *JWT) Renew(tokenStr string, expDate int64) (string, error) {
claims := jwt.MapClaims{}
if _, err := t.Parse(tokenStr, &claims); err != nil {
return "", fmt.Errorf("renew: %w", err)
}
return t.Generate(claims, expDate)
}
func ParseUnverified(tokenString string, claims jwt.Claims) (*jwt.Token, []string, error) {
return defaultParser.ParseUnverified(tokenString, claims)
}