1
1
package jwt_test
2
2
3
3
import (
4
+ "crypto"
4
5
"crypto/rsa"
5
6
"encoding/json"
6
7
"fmt"
@@ -15,25 +16,36 @@ import (
15
16
var errKeyFuncError error = fmt .Errorf ("error loading key" )
16
17
17
18
var (
18
- jwtTestDefaultKey * rsa.PublicKey
19
- defaultKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return jwtTestDefaultKey , nil }
20
- emptyKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return nil , nil }
21
- errorKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return nil , errKeyFuncError }
22
- nilKeyFunc jwt.Keyfunc = nil
19
+ jwtTestDefaultKey * rsa.PublicKey
20
+ jwtTestRSAPrivateKey * rsa.PrivateKey
21
+ jwtTestEC256PublicKey crypto.PublicKey
22
+ jwtTestEC256PrivateKey crypto.PrivateKey
23
+ defaultKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return jwtTestDefaultKey , nil }
24
+ ecdsaKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return jwtTestEC256PublicKey , nil }
25
+ emptyKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return nil , nil }
26
+ errorKeyFunc jwt.Keyfunc = func (t * jwt.Token ) (interface {}, error ) { return nil , errKeyFuncError }
27
+ nilKeyFunc jwt.Keyfunc = nil
23
28
)
24
29
25
30
func init () {
31
+ // Load public keys
26
32
jwtTestDefaultKey = test .LoadRSAPublicKeyFromDisk ("test/sample_key.pub" )
33
+ jwtTestEC256PublicKey = test .LoadECPublicKeyFromDisk ("test/ec256-public.pem" )
34
+
35
+ // Load private keys
36
+ jwtTestRSAPrivateKey = test .LoadRSAPrivateKeyFromDisk ("test/sample_key" )
37
+ jwtTestEC256PrivateKey = test .LoadECPrivateKeyFromDisk ("test/ec256-private.pem" )
27
38
}
28
39
29
40
var jwtTestData = []struct {
30
- name string
31
- tokenString string
32
- keyfunc jwt.Keyfunc
33
- claims jwt.Claims
34
- valid bool
35
- errors uint32
36
- parser * jwt.Parser
41
+ name string
42
+ tokenString string
43
+ keyfunc jwt.Keyfunc
44
+ claims jwt.Claims
45
+ valid bool
46
+ errors uint32
47
+ parser * jwt.Parser
48
+ signingMethod jwt.SigningMethod // The method to sign the JWT token for test purpose
37
49
}{
38
50
{
39
51
"basic" ,
@@ -43,6 +55,7 @@ var jwtTestData = []struct {
43
55
true ,
44
56
0 ,
45
57
nil ,
58
+ jwt .SigningMethodRS256 ,
46
59
},
47
60
{
48
61
"basic expired" ,
@@ -52,6 +65,7 @@ var jwtTestData = []struct {
52
65
false ,
53
66
jwt .ValidationErrorExpired ,
54
67
nil ,
68
+ jwt .SigningMethodRS256 ,
55
69
},
56
70
{
57
71
"basic nbf" ,
@@ -61,6 +75,7 @@ var jwtTestData = []struct {
61
75
false ,
62
76
jwt .ValidationErrorNotValidYet ,
63
77
nil ,
78
+ jwt .SigningMethodRS256 ,
64
79
},
65
80
{
66
81
"expired and nbf" ,
@@ -70,6 +85,7 @@ var jwtTestData = []struct {
70
85
false ,
71
86
jwt .ValidationErrorNotValidYet | jwt .ValidationErrorExpired ,
72
87
nil ,
88
+ jwt .SigningMethodRS256 ,
73
89
},
74
90
{
75
91
"basic invalid" ,
@@ -79,6 +95,7 @@ var jwtTestData = []struct {
79
95
false ,
80
96
jwt .ValidationErrorSignatureInvalid ,
81
97
nil ,
98
+ jwt .SigningMethodRS256 ,
82
99
},
83
100
{
84
101
"basic nokeyfunc" ,
@@ -88,6 +105,7 @@ var jwtTestData = []struct {
88
105
false ,
89
106
jwt .ValidationErrorUnverifiable ,
90
107
nil ,
108
+ jwt .SigningMethodRS256 ,
91
109
},
92
110
{
93
111
"basic nokey" ,
@@ -97,6 +115,7 @@ var jwtTestData = []struct {
97
115
false ,
98
116
jwt .ValidationErrorSignatureInvalid ,
99
117
nil ,
118
+ jwt .SigningMethodRS256 ,
100
119
},
101
120
{
102
121
"basic errorkey" ,
@@ -106,6 +125,7 @@ var jwtTestData = []struct {
106
125
false ,
107
126
jwt .ValidationErrorUnverifiable ,
108
127
nil ,
128
+ jwt .SigningMethodRS256 ,
109
129
},
110
130
{
111
131
"invalid signing method" ,
@@ -115,15 +135,37 @@ var jwtTestData = []struct {
115
135
false ,
116
136
jwt .ValidationErrorSignatureInvalid ,
117
137
& jwt.Parser {ValidMethods : []string {"HS256" }},
138
+ jwt .SigningMethodRS256 ,
118
139
},
119
140
{
120
- "valid signing method" ,
141
+ "valid RSA signing method" ,
121
142
"" ,
122
143
defaultKeyFunc ,
123
144
jwt.MapClaims {"foo" : "bar" },
124
145
true ,
125
146
0 ,
126
147
& jwt.Parser {ValidMethods : []string {"RS256" , "HS256" }},
148
+ jwt .SigningMethodRS256 ,
149
+ },
150
+ {
151
+ "ECDSA signing method not accepted" ,
152
+ "" ,
153
+ ecdsaKeyFunc ,
154
+ jwt.MapClaims {"foo" : "bar" },
155
+ false ,
156
+ jwt .ValidationErrorSignatureInvalid ,
157
+ & jwt.Parser {ValidMethods : []string {"RS256" , "HS256" }},
158
+ jwt .SigningMethodES256 ,
159
+ },
160
+ {
161
+ "valid ECDSA signing method" ,
162
+ "" ,
163
+ ecdsaKeyFunc ,
164
+ jwt.MapClaims {"foo" : "bar" },
165
+ true ,
166
+ 0 ,
167
+ & jwt.Parser {ValidMethods : []string {"HS256" , "ES256" }},
168
+ jwt .SigningMethodES256 ,
127
169
},
128
170
{
129
171
"JSON Number" ,
@@ -133,6 +175,7 @@ var jwtTestData = []struct {
133
175
true ,
134
176
0 ,
135
177
& jwt.Parser {UseJSONNumber : true },
178
+ jwt .SigningMethodRS256 ,
136
179
},
137
180
{
138
181
"Standard Claims" ,
@@ -144,6 +187,7 @@ var jwtTestData = []struct {
144
187
true ,
145
188
0 ,
146
189
& jwt.Parser {UseJSONNumber : true },
190
+ jwt .SigningMethodRS256 ,
147
191
},
148
192
{
149
193
"JSON Number - basic expired" ,
@@ -153,6 +197,7 @@ var jwtTestData = []struct {
153
197
false ,
154
198
jwt .ValidationErrorExpired ,
155
199
& jwt.Parser {UseJSONNumber : true },
200
+ jwt .SigningMethodRS256 ,
156
201
},
157
202
{
158
203
"JSON Number - basic nbf" ,
@@ -162,6 +207,7 @@ var jwtTestData = []struct {
162
207
false ,
163
208
jwt .ValidationErrorNotValidYet ,
164
209
& jwt.Parser {UseJSONNumber : true },
210
+ jwt .SigningMethodRS256 ,
165
211
},
166
212
{
167
213
"JSON Number - expired and nbf" ,
@@ -171,6 +217,7 @@ var jwtTestData = []struct {
171
217
false ,
172
218
jwt .ValidationErrorNotValidYet | jwt .ValidationErrorExpired ,
173
219
& jwt.Parser {UseJSONNumber : true },
220
+ jwt .SigningMethodRS256 ,
174
221
},
175
222
{
176
223
"SkipClaimsValidation during token parsing" ,
@@ -180,6 +227,7 @@ var jwtTestData = []struct {
180
227
true ,
181
228
0 ,
182
229
& jwt.Parser {UseJSONNumber : true , SkipClaimsValidation : true },
230
+ jwt .SigningMethodRS256 ,
183
231
},
184
232
{
185
233
"RFC7519 Claims" ,
@@ -191,6 +239,7 @@ var jwtTestData = []struct {
191
239
true ,
192
240
0 ,
193
241
& jwt.Parser {UseJSONNumber : true },
242
+ jwt .SigningMethodRS256 ,
194
243
},
195
244
{
196
245
"RFC7519 Claims - single aud" ,
@@ -202,6 +251,7 @@ var jwtTestData = []struct {
202
251
true ,
203
252
0 ,
204
253
& jwt.Parser {UseJSONNumber : true },
254
+ jwt .SigningMethodRS256 ,
205
255
},
206
256
{
207
257
"RFC7519 Claims - multiple aud" ,
@@ -213,6 +263,7 @@ var jwtTestData = []struct {
213
263
true ,
214
264
0 ,
215
265
& jwt.Parser {UseJSONNumber : true },
266
+ jwt .SigningMethodRS256 ,
216
267
},
217
268
{
218
269
"RFC7519 Claims - single aud with wrong type" ,
@@ -224,6 +275,7 @@ var jwtTestData = []struct {
224
275
false ,
225
276
jwt .ValidationErrorMalformed ,
226
277
& jwt.Parser {UseJSONNumber : true },
278
+ jwt .SigningMethodRS256 ,
227
279
},
228
280
{
229
281
"RFC7519 Claims - multiple aud with wrong types" ,
@@ -235,18 +287,33 @@ var jwtTestData = []struct {
235
287
false ,
236
288
jwt .ValidationErrorMalformed ,
237
289
& jwt.Parser {UseJSONNumber : true },
290
+ jwt .SigningMethodRS256 ,
238
291
},
239
292
}
240
293
294
+ // signToken creates and returns a signed JWT token using signingMethod.
295
+ func signToken (claims jwt.Claims , signingMethod jwt.SigningMethod ) string {
296
+ var privateKey interface {}
297
+ switch signingMethod {
298
+ case jwt .SigningMethodRS256 :
299
+ privateKey = jwtTestRSAPrivateKey
300
+ case jwt .SigningMethodES256 :
301
+ privateKey = jwtTestEC256PrivateKey
302
+ default :
303
+ return ""
304
+ }
305
+ return test .MakeSampleToken (claims , signingMethod , privateKey )
306
+ }
307
+
241
308
func TestParser_Parse (t * testing.T ) {
242
- privateKey := test .LoadRSAPrivateKeyFromDisk ("test/sample_key" )
243
309
244
310
// Iterate over test data set and run tests
245
311
for _ , data := range jwtTestData {
246
312
t .Run (data .name , func (t * testing.T ) {
313
+
247
314
// If the token string is blank, use helper function to generate string
248
315
if data .tokenString == "" {
249
- data .tokenString = test . MakeSampleToken (data .claims , privateKey )
316
+ data .tokenString = signToken (data .claims , data . signingMethod )
250
317
}
251
318
252
319
// Parse the token
@@ -285,7 +352,7 @@ func TestParser_Parse(t *testing.T) {
285
352
286
353
if data .errors != 0 {
287
354
if err == nil {
288
- t .Errorf ("[%v] Expecting error. Didn't get one." , data .name )
355
+ t .Errorf ("[%v] Expecting error. Didn't get one." , data .name )
289
356
} else {
290
357
291
358
ve := err .(* jwt.ValidationError )
@@ -299,15 +366,20 @@ func TestParser_Parse(t *testing.T) {
299
366
}
300
367
}
301
368
}
302
- if data .valid && token .Signature == "" {
303
- t .Errorf ("[%v] Signature is left unpopulated after parsing" , data .name )
369
+ if data .valid {
370
+ if token .Signature == "" {
371
+ t .Errorf ("[%v] Signature is left unpopulated after parsing" , data .name )
372
+ }
373
+ if ! token .Valid {
374
+ // The 'Valid' field should be set to true when invoking Parse()
375
+ t .Errorf ("[%v] Token.Valid field mismatch. Expecting true, got %v" , data .name , token .Valid )
376
+ }
304
377
}
305
378
})
306
379
}
307
380
}
308
381
309
382
func TestParser_ParseUnverified (t * testing.T ) {
310
- privateKey := test .LoadRSAPrivateKeyFromDisk ("test/sample_key" )
311
383
312
384
// Iterate over test data set and run tests
313
385
for _ , data := range jwtTestData {
@@ -319,7 +391,7 @@ func TestParser_ParseUnverified(t *testing.T) {
319
391
t .Run (data .name , func (t * testing.T ) {
320
392
// If the token string is blank, use helper function to generate string
321
393
if data .tokenString == "" {
322
- data .tokenString = test . MakeSampleToken (data .claims , privateKey )
394
+ data .tokenString = signToken (data .claims , data . signingMethod )
323
395
}
324
396
325
397
// Parse the token
@@ -351,18 +423,25 @@ func TestParser_ParseUnverified(t *testing.T) {
351
423
if data .valid && err != nil {
352
424
t .Errorf ("[%v] Error while verifying token: %T:%v" , data .name , err , err )
353
425
}
426
+ if token .Valid {
427
+ // The 'Valid' field should not be set to true when invoking ParseUnverified()
428
+ t .Errorf ("[%v] Token.Valid field mismatch. Expecting false, got %v" , data .name , token .Valid )
429
+ }
430
+ if token .Signature != "" {
431
+ // The signature was not validated, hence the 'Signature' field is not populated.
432
+ t .Errorf ("[%v] Token.Signature field mismatch. Expecting '', got %v" , data .name , token .Signature )
433
+ }
354
434
})
355
435
}
356
436
}
357
437
358
438
func BenchmarkParseUnverified (b * testing.B ) {
359
- privateKey := test .LoadRSAPrivateKeyFromDisk ("test/sample_key" )
360
439
361
440
// Iterate over test data set and run tests
362
441
for _ , data := range jwtTestData {
363
442
// If the token string is blank, use helper function to generate string
364
443
if data .tokenString == "" {
365
- data .tokenString = test . MakeSampleToken (data .claims , privateKey )
444
+ data .tokenString = signToken (data .claims , data . signingMethod )
366
445
}
367
446
368
447
// Parse the token
0 commit comments