-
Notifications
You must be signed in to change notification settings - Fork 0
/
jwt.go
109 lines (85 loc) · 2.48 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
package JWT
import (
"math/rand"
"time"
"github.com/bytedance/sonic"
"github.com/cristalhq/jwt/v5"
"github.com/valyala/fasthttp"
"github.com/gohryt/asphyxia-core/random"
)
type (
TokenGeneratorConfiguration struct {
UserValueKey string `json:"user_value_key"`
Expires int `json:"expires"`
}
TokenGeneratorParameters struct {
ErrorHandler func(ctx *fasthttp.RequestCtx, err error)
Signature []byte
}
Claims[T any] struct {
jwt.RegisteredClaims
Data T
}
innerTokenGenerator[T any] struct {
errorHandler func(ctx *fasthttp.RequestCtx, err error)
signature []byte
builder *jwt.Builder
verifier jwt.Verifier
userValueKey string
}
)
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
func Prepare[T any](configuration TokenGeneratorConfiguration, parameters TokenGeneratorParameters) (tokenGenerator *innerTokenGenerator[T], err error) {
if parameters.ErrorHandler == nil {
parameters.ErrorHandler = func(ctx *fasthttp.RequestCtx, err error) {
ctx.SetStatusCode(fasthttp.StatusUnauthorized)
ctx.SetBodyString(err.Error())
}
}
if len(parameters.Signature) == 0 {
parameters.Signature = random.Slice([]byte(charset), 512)
}
signer, err := jwt.NewSignerHS(jwt.HS256, parameters.Signature)
if err != nil {
return
}
builder := jwt.NewBuilder(signer)
verifier, err := jwt.NewVerifierHS(jwt.HS256, parameters.Signature)
if err != nil {
return
}
tokenGenerator = &innerTokenGenerator[T]{
errorHandler: parameters.ErrorHandler,
signature: parameters.Signature,
builder: builder,
verifier: verifier,
userValueKey: configuration.UserValueKey,
}
return
}
func (tokenGenerator *innerTokenGenerator[T]) Handler(source fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
authorization := ctx.Response.Header.Peek(fasthttp.HeaderAuthorization)
token, err := jwt.ParseNoVerify(authorization)
if err != nil {
tokenGenerator.errorHandler(ctx, err)
return
}
err = tokenGenerator.verifier.Verify(token)
if err != nil {
tokenGenerator.errorHandler(ctx, err)
return
}
claims := new(Claims[T])
err = sonic.Unmarshal(token.Claims(), claims)
if err != nil {
tokenGenerator.errorHandler(ctx, err)
return
}
ctx.SetUserValue(tokenGenerator.userValueKey, claims)
source(ctx)
}
}
func (tokenGenerator *innerTokenGenerator[T]) Generate(claims *Claims[T]) (token *jwt.Token, err error) {
return tokenGenerator.builder.Build(claims)
}