7
7
"strings"
8
8
)
9
9
10
- type Parser struct {
10
+ type parserOpts struct {
11
11
// If populated, only these methods will be considered valid.
12
12
validMethods []string
13
13
@@ -20,44 +20,54 @@ type Parser struct {
20
20
validator * validator
21
21
}
22
22
23
+ type Parser [T Claims ] struct {
24
+ opts parserOpts
25
+ }
26
+
23
27
// NewParser creates a new Parser with the specified options
24
- func NewParser (options ... ParserOption ) * Parser {
25
- p := & Parser {
26
- validator : & validator {},
28
+ func NewParser (options ... ParserOption ) * Parser [ MapClaims ] {
29
+ p := & Parser [ MapClaims ] {
30
+ opts : parserOpts { validator : & validator {} },
27
31
}
28
32
29
33
// Loop through our parsing options and apply them
30
34
for _ , option := range options {
31
- option (p )
35
+ option (& p . opts )
32
36
}
33
37
34
38
return p
35
39
}
36
40
37
- // Parse parses, validates, verifies the signature and returns the parsed token.
38
- // keyFunc will receive the parsed token and should return the key for validating.
39
- func (p * Parser ) Parse (tokenString string , keyFunc Keyfunc ) (* Token , error ) {
40
- return p .ParseWithClaims (tokenString , MapClaims {}, keyFunc )
41
+ func NewParserFor [T Claims ](options ... ParserOption ) * Parser [T ] {
42
+ p := & Parser [T ]{
43
+ opts : parserOpts {validator : & validator {}},
44
+ }
45
+
46
+ // Loop through our parsing options and apply them
47
+ for _ , option := range options {
48
+ option (& p .opts )
49
+ }
50
+
51
+ return p
41
52
}
42
53
43
- // ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
44
- // interface. This provides default values which can be overridden and allows a caller to use their own type, rather
45
- // than the default MapClaims implementation of Claims.
54
+ // Parse parses, validates, verifies the signature and returns the parsed token.
55
+ // keyFunc will receive the parsed token and should return the key for validating.
46
56
//
47
57
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
48
58
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
49
59
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
50
- func (p * Parser ) ParseWithClaims (tokenString string , claims Claims , keyFunc Keyfunc ) (* Token , error ) {
51
- token , parts , err := p .ParseUnverified (tokenString , claims )
60
+ func (p * Parser [ T ]) Parse (tokenString string , keyFunc Keyfunc [ T ] ) (* Token [ T ] , error ) {
61
+ token , parts , err := p .ParseUnverified (tokenString )
52
62
if err != nil {
53
63
return token , err
54
64
}
55
65
56
66
// Verify signing method is in the required set
57
- if p .validMethods != nil {
58
- var signingMethodValid = false
59
- var alg = token .Method .Alg ()
60
- for _ , m := range p .validMethods {
67
+ if p .opts . validMethods != nil {
68
+ signingMethodValid : = false
69
+ alg : = token .Method .Alg ()
70
+ for _ , m := range p .opts . validMethods {
61
71
if m == alg {
62
72
signingMethodValid = true
63
73
break
@@ -86,13 +96,13 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
86
96
vErr := & ValidationError {}
87
97
88
98
// Validate Claims
89
- if ! p .skipClaimsValidation {
99
+ if ! p .opts . skipClaimsValidation {
90
100
// Make sure we have at least a default validator
91
- if p .validator == nil {
92
- p .validator = newValidator ()
101
+ if p .opts . validator == nil {
102
+ p .opts . validator = newValidator ()
93
103
}
94
104
95
- if err := p .validator .Validate (claims ); err != nil {
105
+ if err := p .opts . validator .Validate (token . Claims ); err != nil {
96
106
// If the Claims Valid returned an error, check if it is a validation error,
97
107
// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
98
108
if e , ok := err .(* ValidationError ); ! ok {
@@ -124,13 +134,13 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
124
134
//
125
135
// It's only ever useful in cases where you know the signature is valid (because it has
126
136
// been checked previously in the stack) and you want to extract values from it.
127
- func (p * Parser ) ParseUnverified (tokenString string , claims Claims ) (token * Token , parts []string , err error ) {
137
+ func (p * Parser [ T ] ) ParseUnverified (tokenString string ) (token * Token [ T ] , parts []string , err error ) {
128
138
parts = strings .Split (tokenString , "." )
129
139
if len (parts ) != 3 {
130
140
return nil , parts , NewValidationError ("token contains an invalid number of segments" , ValidationErrorMalformed )
131
141
}
132
142
133
- token = & Token {Raw : tokenString }
143
+ token = & Token [ T ] {Raw : tokenString }
134
144
135
145
// parse Header
136
146
var headerBytes []byte
@@ -146,23 +156,17 @@ func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Toke
146
156
147
157
// parse Claims
148
158
var claimBytes []byte
149
- token .Claims = claims
150
-
151
159
if claimBytes , err = DecodeSegment (parts [1 ]); err != nil {
152
160
return token , parts , & ValidationError {Inner : err , Errors : ValidationErrorMalformed }
153
161
}
162
+
154
163
dec := json .NewDecoder (bytes .NewBuffer (claimBytes ))
155
- if p .useJSONNumber {
164
+ if p .opts . useJSONNumber {
156
165
dec .UseNumber ()
157
166
}
158
- // JSON Decode. Special case for map type to avoid weird pointer behavior
159
- if c , ok := token .Claims .(MapClaims ); ok {
160
- err = dec .Decode (& c )
161
- } else {
162
- err = dec .Decode (& claims )
163
- }
167
+
164
168
// Handle decode error
165
- if err != nil {
169
+ if err = dec . Decode ( & token . Claims ); err != nil {
166
170
return token , parts , & ValidationError {Inner : err , Errors : ValidationErrorMalformed }
167
171
}
168
172
0 commit comments