Skip to content

Commit fd8cd69

Browse files
Adjusted parser_test.go to include RSA and ECDSA tokens (#106)
1 parent 02bc1ac commit fd8cd69

File tree

3 files changed

+130
-25
lines changed

3 files changed

+130
-25
lines changed

parser_test.go

Lines changed: 101 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package jwt_test
22

33
import (
4+
"crypto"
45
"crypto/rsa"
56
"encoding/json"
67
"fmt"
@@ -15,25 +16,36 @@ import (
1516
var errKeyFuncError error = fmt.Errorf("error loading key")
1617

1718
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
2328
)
2429

2530
func init() {
31+
// Load public keys
2632
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")
2738
}
2839

2940
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
3749
}{
3850
{
3951
"basic",
@@ -43,6 +55,7 @@ var jwtTestData = []struct {
4355
true,
4456
0,
4557
nil,
58+
jwt.SigningMethodRS256,
4659
},
4760
{
4861
"basic expired",
@@ -52,6 +65,7 @@ var jwtTestData = []struct {
5265
false,
5366
jwt.ValidationErrorExpired,
5467
nil,
68+
jwt.SigningMethodRS256,
5569
},
5670
{
5771
"basic nbf",
@@ -61,6 +75,7 @@ var jwtTestData = []struct {
6175
false,
6276
jwt.ValidationErrorNotValidYet,
6377
nil,
78+
jwt.SigningMethodRS256,
6479
},
6580
{
6681
"expired and nbf",
@@ -70,6 +85,7 @@ var jwtTestData = []struct {
7085
false,
7186
jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired,
7287
nil,
88+
jwt.SigningMethodRS256,
7389
},
7490
{
7591
"basic invalid",
@@ -79,6 +95,7 @@ var jwtTestData = []struct {
7995
false,
8096
jwt.ValidationErrorSignatureInvalid,
8197
nil,
98+
jwt.SigningMethodRS256,
8299
},
83100
{
84101
"basic nokeyfunc",
@@ -88,6 +105,7 @@ var jwtTestData = []struct {
88105
false,
89106
jwt.ValidationErrorUnverifiable,
90107
nil,
108+
jwt.SigningMethodRS256,
91109
},
92110
{
93111
"basic nokey",
@@ -97,6 +115,7 @@ var jwtTestData = []struct {
97115
false,
98116
jwt.ValidationErrorSignatureInvalid,
99117
nil,
118+
jwt.SigningMethodRS256,
100119
},
101120
{
102121
"basic errorkey",
@@ -106,6 +125,7 @@ var jwtTestData = []struct {
106125
false,
107126
jwt.ValidationErrorUnverifiable,
108127
nil,
128+
jwt.SigningMethodRS256,
109129
},
110130
{
111131
"invalid signing method",
@@ -115,15 +135,37 @@ var jwtTestData = []struct {
115135
false,
116136
jwt.ValidationErrorSignatureInvalid,
117137
&jwt.Parser{ValidMethods: []string{"HS256"}},
138+
jwt.SigningMethodRS256,
118139
},
119140
{
120-
"valid signing method",
141+
"valid RSA signing method",
121142
"",
122143
defaultKeyFunc,
123144
jwt.MapClaims{"foo": "bar"},
124145
true,
125146
0,
126147
&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,
127169
},
128170
{
129171
"JSON Number",
@@ -133,6 +175,7 @@ var jwtTestData = []struct {
133175
true,
134176
0,
135177
&jwt.Parser{UseJSONNumber: true},
178+
jwt.SigningMethodRS256,
136179
},
137180
{
138181
"Standard Claims",
@@ -144,6 +187,7 @@ var jwtTestData = []struct {
144187
true,
145188
0,
146189
&jwt.Parser{UseJSONNumber: true},
190+
jwt.SigningMethodRS256,
147191
},
148192
{
149193
"JSON Number - basic expired",
@@ -153,6 +197,7 @@ var jwtTestData = []struct {
153197
false,
154198
jwt.ValidationErrorExpired,
155199
&jwt.Parser{UseJSONNumber: true},
200+
jwt.SigningMethodRS256,
156201
},
157202
{
158203
"JSON Number - basic nbf",
@@ -162,6 +207,7 @@ var jwtTestData = []struct {
162207
false,
163208
jwt.ValidationErrorNotValidYet,
164209
&jwt.Parser{UseJSONNumber: true},
210+
jwt.SigningMethodRS256,
165211
},
166212
{
167213
"JSON Number - expired and nbf",
@@ -171,6 +217,7 @@ var jwtTestData = []struct {
171217
false,
172218
jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired,
173219
&jwt.Parser{UseJSONNumber: true},
220+
jwt.SigningMethodRS256,
174221
},
175222
{
176223
"SkipClaimsValidation during token parsing",
@@ -180,6 +227,7 @@ var jwtTestData = []struct {
180227
true,
181228
0,
182229
&jwt.Parser{UseJSONNumber: true, SkipClaimsValidation: true},
230+
jwt.SigningMethodRS256,
183231
},
184232
{
185233
"RFC7519 Claims",
@@ -191,6 +239,7 @@ var jwtTestData = []struct {
191239
true,
192240
0,
193241
&jwt.Parser{UseJSONNumber: true},
242+
jwt.SigningMethodRS256,
194243
},
195244
{
196245
"RFC7519 Claims - single aud",
@@ -202,6 +251,7 @@ var jwtTestData = []struct {
202251
true,
203252
0,
204253
&jwt.Parser{UseJSONNumber: true},
254+
jwt.SigningMethodRS256,
205255
},
206256
{
207257
"RFC7519 Claims - multiple aud",
@@ -213,6 +263,7 @@ var jwtTestData = []struct {
213263
true,
214264
0,
215265
&jwt.Parser{UseJSONNumber: true},
266+
jwt.SigningMethodRS256,
216267
},
217268
{
218269
"RFC7519 Claims - single aud with wrong type",
@@ -224,6 +275,7 @@ var jwtTestData = []struct {
224275
false,
225276
jwt.ValidationErrorMalformed,
226277
&jwt.Parser{UseJSONNumber: true},
278+
jwt.SigningMethodRS256,
227279
},
228280
{
229281
"RFC7519 Claims - multiple aud with wrong types",
@@ -235,18 +287,33 @@ var jwtTestData = []struct {
235287
false,
236288
jwt.ValidationErrorMalformed,
237289
&jwt.Parser{UseJSONNumber: true},
290+
jwt.SigningMethodRS256,
238291
},
239292
}
240293

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+
241308
func TestParser_Parse(t *testing.T) {
242-
privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key")
243309

244310
// Iterate over test data set and run tests
245311
for _, data := range jwtTestData {
246312
t.Run(data.name, func(t *testing.T) {
313+
247314
// If the token string is blank, use helper function to generate string
248315
if data.tokenString == "" {
249-
data.tokenString = test.MakeSampleToken(data.claims, privateKey)
316+
data.tokenString = signToken(data.claims, data.signingMethod)
250317
}
251318

252319
// Parse the token
@@ -285,7 +352,7 @@ func TestParser_Parse(t *testing.T) {
285352

286353
if data.errors != 0 {
287354
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)
289356
} else {
290357

291358
ve := err.(*jwt.ValidationError)
@@ -299,15 +366,20 @@ func TestParser_Parse(t *testing.T) {
299366
}
300367
}
301368
}
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+
}
304377
}
305378
})
306379
}
307380
}
308381

309382
func TestParser_ParseUnverified(t *testing.T) {
310-
privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key")
311383

312384
// Iterate over test data set and run tests
313385
for _, data := range jwtTestData {
@@ -319,7 +391,7 @@ func TestParser_ParseUnverified(t *testing.T) {
319391
t.Run(data.name, func(t *testing.T) {
320392
// If the token string is blank, use helper function to generate string
321393
if data.tokenString == "" {
322-
data.tokenString = test.MakeSampleToken(data.claims, privateKey)
394+
data.tokenString = signToken(data.claims, data.signingMethod)
323395
}
324396

325397
// Parse the token
@@ -351,18 +423,25 @@ func TestParser_ParseUnverified(t *testing.T) {
351423
if data.valid && err != nil {
352424
t.Errorf("[%v] Error while verifying token: %T:%v", data.name, err, err)
353425
}
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+
}
354434
})
355435
}
356436
}
357437

358438
func BenchmarkParseUnverified(b *testing.B) {
359-
privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key")
360439

361440
// Iterate over test data set and run tests
362441
for _, data := range jwtTestData {
363442
// If the token string is blank, use helper function to generate string
364443
if data.tokenString == "" {
365-
data.tokenString = test.MakeSampleToken(data.claims, privateKey)
444+
data.tokenString = signToken(data.claims, data.signingMethod)
366445
}
367446

368447
// Parse the token

request/request_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func TestParseRequest(t *testing.T) {
6565
// Bearer token request
6666
for _, data := range requestTestData {
6767
// Make token from claims
68-
tokenString := test.MakeSampleToken(data.claims, privateKey)
68+
tokenString := test.MakeSampleToken(data.claims, jwt.SigningMethodRS256, privateKey)
6969

7070
// Make query string
7171
for k, vv := range data.query {

0 commit comments

Comments
 (0)