github.com/lestrrat-go/jwx/v2@v2.0.21/jwt/jwt_test.go (about) 1 package jwt_test 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/ecdsa" 7 "crypto/ed25519" 8 "crypto/rand" 9 "crypto/rsa" 10 "encoding/base64" 11 "errors" 12 "fmt" 13 "net/http" 14 "net/http/httptest" 15 "net/url" 16 "os" 17 "strconv" 18 "strings" 19 "sync" 20 "testing" 21 "time" 22 23 "github.com/lestrrat-go/jwx/v2/internal/ecutil" 24 "github.com/lestrrat-go/jwx/v2/internal/json" 25 "github.com/lestrrat-go/jwx/v2/internal/jwxtest" 26 "github.com/lestrrat-go/jwx/v2/jwe" 27 "github.com/lestrrat-go/jwx/v2/jwt/internal/types" 28 29 "github.com/lestrrat-go/jwx/v2/jwa" 30 "github.com/lestrrat-go/jwx/v2/jwk" 31 "github.com/lestrrat-go/jwx/v2/jws" 32 "github.com/lestrrat-go/jwx/v2/jwt" 33 "github.com/stretchr/testify/assert" 34 "github.com/stretchr/testify/require" 35 ) 36 37 /* This is commented out, because it is intended to cause compilation errors */ 38 /* 39 func TestOption(t *testing.T) { 40 var p jwt.ParseOption 41 var v jwt.ValidateOption 42 var o jwt.Option 43 p = o // should be error 44 v = o // should be error 45 _ = p 46 _ = v 47 } 48 */ 49 50 func TestJWTParse(t *testing.T) { 51 t.Parallel() 52 53 alg := jwa.RS256 54 55 key, err := jwxtest.GenerateRsaKey() 56 if !assert.NoError(t, err, `jwxtest.GenerateRsaKey should succeed`) { 57 return 58 } 59 t1 := jwt.New() 60 signed, err := jwt.Sign(t1, jwt.WithKey(alg, key)) 61 if !assert.NoError(t, err, `jwt.Sign should succeed`) { 62 return 63 } 64 65 t.Logf("%s", signed) 66 67 t.Run("Parse (no signature verification)", func(t *testing.T) { 68 t.Parallel() 69 t2, err := jwt.ParseInsecure(signed) 70 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 71 return 72 } 73 if !assert.True(t, jwt.Equal(t1, t2), `t1 == t2`) { 74 return 75 } 76 }) 77 t.Run("ParseString (no signature verification)", func(t *testing.T) { 78 t.Parallel() 79 t2, err := jwt.ParseString(string(signed), jwt.WithVerify(false), jwt.WithValidate(false)) 80 if !assert.NoError(t, err, `jwt.ParseString should succeed`) { 81 return 82 } 83 if !assert.True(t, jwt.Equal(t1, t2), `t1 == t2`) { 84 return 85 } 86 }) 87 t.Run("ParseReader (no signature verification)", func(t *testing.T) { 88 t.Parallel() 89 t2, err := jwt.ParseReader(bytes.NewReader(signed), jwt.WithVerify(false), jwt.WithValidate(false)) 90 if !assert.NoError(t, err, `jwt.ParseReader should succeed`) { 91 return 92 } 93 if !assert.True(t, jwt.Equal(t1, t2), `t1 == t2`) { 94 return 95 } 96 }) 97 t.Run("Parse (correct signature key)", func(t *testing.T) { 98 t.Parallel() 99 t2, err := jwt.Parse(signed, jwt.WithKey(alg, &key.PublicKey)) 100 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 101 return 102 } 103 if !assert.True(t, jwt.Equal(t1, t2), `t1 == t2`) { 104 return 105 } 106 }) 107 t.Run("parse (wrong signature algorithm)", func(t *testing.T) { 108 t.Parallel() 109 _, err := jwt.Parse(signed, jwt.WithKey(jwa.RS512, &key.PublicKey)) 110 if !assert.Error(t, err, `jwt.Parse should fail`) { 111 return 112 } 113 }) 114 t.Run("parse (wrong signature key)", func(t *testing.T) { 115 t.Parallel() 116 pubkey := key.PublicKey 117 pubkey.E = 0 // bogus value 118 _, err := jwt.Parse(signed, jwt.WithKey(alg, &pubkey)) 119 if !assert.Error(t, err, `jwt.Parse should fail`) { 120 return 121 } 122 }) 123 } 124 125 func TestJWTParseVerify(t *testing.T) { 126 t.Parallel() 127 128 keys := make([]interface{}, 0, 6) 129 130 keys = append(keys, []byte("abracadabra")) 131 132 rsaPrivKey, err := jwxtest.GenerateRsaKey() 133 if !assert.NoError(t, err, "RSA key generated") { 134 return 135 } 136 keys = append(keys, rsaPrivKey) 137 138 for _, alg := range []jwa.EllipticCurveAlgorithm{jwa.P256, jwa.P384, jwa.P521} { 139 ecdsaPrivKey, err := jwxtest.GenerateEcdsaKey(alg) 140 if !assert.NoError(t, err, "jwxtest.GenerateEcdsaKey should succeed for %s", alg) { 141 return 142 } 143 keys = append(keys, ecdsaPrivKey) 144 } 145 146 ed25519PrivKey, err := jwxtest.GenerateEd25519Key() 147 if !assert.NoError(t, err, `jwxtest.GenerateEd25519Key should succeed`) { 148 return 149 } 150 keys = append(keys, ed25519PrivKey) 151 152 for _, key := range keys { 153 key := key 154 t.Run(fmt.Sprintf("Key=%T", key), func(t *testing.T) { 155 t.Parallel() 156 algs, err := jws.AlgorithmsForKey(key) 157 if !assert.NoError(t, err, `jwas.AlgorithmsForKey should succeed`) { 158 return 159 } 160 161 var dummyRawKey interface{} 162 switch pk := key.(type) { 163 case *rsa.PrivateKey: 164 dummyRawKey, err = jwxtest.GenerateRsaKey() 165 if !assert.NoError(t, err, `jwxtest.GenerateRsaKey should succeed`) { 166 return 167 } 168 case *ecdsa.PrivateKey: 169 curveAlg, ok := ecutil.AlgorithmForCurve(pk.Curve) 170 if !assert.True(t, ok, `ecutil.AlgorithmForCurve should succeed`) { 171 return 172 } 173 dummyRawKey, err = jwxtest.GenerateEcdsaKey(curveAlg) 174 if !assert.NoError(t, err, `jwxtest.GenerateEcdsaKey should succeed`) { 175 return 176 } 177 case ed25519.PrivateKey: 178 dummyRawKey, err = jwxtest.GenerateEd25519Key() 179 if !assert.NoError(t, err, `jwxtest.GenerateEd25519Key should succeed`) { 180 return 181 } 182 case []byte: 183 dummyRawKey = jwxtest.GenerateSymmetricKey() 184 default: 185 assert.Fail(t, fmt.Sprintf("Unhandled key type %T", key)) 186 return 187 } 188 189 testcases := []struct { 190 SetAlgorithm bool 191 SetKid bool 192 InferAlgorithm bool 193 Error bool 194 }{ 195 { 196 SetAlgorithm: true, 197 SetKid: true, 198 InferAlgorithm: true, 199 }, 200 { 201 SetAlgorithm: true, 202 SetKid: true, 203 InferAlgorithm: false, 204 }, 205 { 206 SetAlgorithm: true, 207 SetKid: false, 208 InferAlgorithm: true, 209 Error: true, 210 }, 211 { 212 SetAlgorithm: false, 213 SetKid: true, 214 InferAlgorithm: true, 215 }, 216 { 217 SetAlgorithm: false, 218 SetKid: true, 219 InferAlgorithm: false, 220 Error: true, 221 }, 222 { 223 SetAlgorithm: false, 224 SetKid: false, 225 InferAlgorithm: true, 226 Error: true, 227 }, 228 { 229 SetAlgorithm: true, 230 SetKid: false, 231 InferAlgorithm: false, 232 Error: true, 233 }, 234 { 235 SetAlgorithm: false, 236 SetKid: false, 237 InferAlgorithm: false, 238 Error: true, 239 }, 240 } 241 for _, alg := range algs { 242 alg := alg 243 for _, tc := range testcases { 244 tc := tc 245 t.Run(fmt.Sprintf("Algorithm=%s, SetAlgorithm=%t, SetKid=%t, InferAlgorithm=%t, Expect Error=%t", alg, tc.SetAlgorithm, tc.SetKid, tc.InferAlgorithm, tc.Error), func(t *testing.T) { 246 t.Parallel() 247 248 const kid = "test-jwt-parse-verify-kid" 249 const dummyKid = "test-jwt-parse-verify-dummy-kid" 250 hdrs := jws.NewHeaders() 251 hdrs.Set(jws.KeyIDKey, kid) 252 253 t1 := jwt.New() 254 signed, err := jwt.Sign(t1, jwt.WithKey(alg, key, jws.WithProtectedHeaders(hdrs))) 255 if !assert.NoError(t, err, "token.Sign should succeed") { 256 return 257 } 258 259 pubkey, err := jwk.PublicKeyOf(key) 260 if !assert.NoError(t, err, `jwk.PublicKeyOf should succeed`) { 261 return 262 } 263 264 if tc.SetAlgorithm { 265 pubkey.Set(jwk.AlgorithmKey, alg) 266 } 267 268 dummyKey, err := jwk.PublicKeyOf(dummyRawKey) 269 if !assert.NoError(t, err, `jwk.PublicKeyOf should succeed`) { 270 return 271 } 272 273 if tc.SetKid { 274 pubkey.Set(jwk.KeyIDKey, kid) 275 dummyKey.Set(jwk.KeyIDKey, dummyKid) 276 } 277 278 // Permute on the location of the correct key, to check for possible 279 // cases where we loop too little or too much. 280 for i := 0; i < 6; i++ { 281 var name string 282 set := jwk.NewSet() 283 switch i { 284 case 0: 285 name = "Lone key" 286 set.AddKey(pubkey) 287 case 1: 288 name = "Two keys, correct one at the end" 289 set.AddKey(dummyKey) 290 set.AddKey(pubkey) 291 case 2: 292 name = "Two keys, correct one at the beginning" 293 set.AddKey(pubkey) 294 set.AddKey(dummyKey) 295 case 3: 296 name = "Three keys, correct one at the end" 297 set.AddKey(dummyKey) 298 set.AddKey(dummyKey) 299 set.AddKey(pubkey) 300 case 4: 301 name = "Three keys, correct one at the middle" 302 set.AddKey(dummyKey) 303 set.AddKey(pubkey) 304 set.AddKey(dummyKey) 305 case 5: 306 name = "Three keys, correct one at the beginning" 307 set.AddKey(pubkey) 308 set.AddKey(dummyKey) 309 set.AddKey(dummyKey) 310 } 311 312 t.Run(name, func(t *testing.T) { 313 options := []jwt.ParseOption{ 314 jwt.WithKeySet(set, jws.WithInferAlgorithmFromKey(tc.InferAlgorithm)), 315 } 316 t2, err := jwt.Parse(signed, options...) 317 318 if tc.Error { 319 assert.Error(t, err, `jwt.Parse should fail`) 320 return 321 } 322 323 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 324 return 325 } 326 327 if !assert.True(t, jwt.Equal(t1, t2), `t1 == t2`) { 328 return 329 } 330 }) 331 } 332 }) 333 } 334 } 335 }) 336 } 337 t.Run("Miscellaneous", func(t *testing.T) { 338 key, err := jwxtest.GenerateRsaKey() 339 if !assert.NoError(t, err, "RSA key generated") { 340 return 341 } 342 const alg = jwa.RS256 343 const kid = "my-very-special-key" 344 hdrs := jws.NewHeaders() 345 hdrs.Set(jws.KeyIDKey, kid) 346 t1 := jwt.New() 347 signed, err := jwt.Sign(t1, jwt.WithKey(alg, key, jws.WithProtectedHeaders(hdrs))) 348 if !assert.NoError(t, err, "token.Sign should succeed") { 349 return 350 } 351 352 t.Run("Alg does not match", func(t *testing.T) { 353 t.Parallel() 354 pubkey, err := jwk.PublicKeyOf(key) 355 if !assert.NoError(t, err) { 356 return 357 } 358 359 pubkey.Set(jwk.AlgorithmKey, jwa.HS256) 360 pubkey.Set(jwk.KeyIDKey, kid) 361 set := jwk.NewSet() 362 set.AddKey(pubkey) 363 364 _, err = jwt.Parse(signed, jwt.WithKeySet(set, jws.WithInferAlgorithmFromKey(true), jws.WithUseDefault(true))) 365 if !assert.Error(t, err, `jwt.Parse should fail`) { 366 return 367 } 368 }) 369 t.Run("UseDefault with a key set with 1 key", func(t *testing.T) { 370 t.Parallel() 371 pubkey, err := jwk.PublicKeyOf(key) 372 if !assert.NoError(t, err) { 373 return 374 } 375 376 pubkey.Set(jwk.AlgorithmKey, alg) 377 pubkey.Set(jwk.KeyIDKey, kid) 378 signedNoKid, err := jwt.Sign(t1, jwt.WithKey(alg, key)) 379 if err != nil { 380 t.Fatal("Failed to sign JWT") 381 } 382 set := jwk.NewSet() 383 set.AddKey(pubkey) 384 t2, err := jwt.Parse(signedNoKid, jwt.WithKeySet(set, jws.WithUseDefault(true))) 385 if !assert.NoError(t, err, `jwt.Parse with key set should succeed`) { 386 return 387 } 388 if !assert.True(t, jwt.Equal(t1, t2), `t1 == t2`) { 389 return 390 } 391 }) 392 t.Run("UseDefault with multiple keys should fail", func(t *testing.T) { 393 t.Parallel() 394 pubkey1, err := jwk.FromRaw(&key.PublicKey) 395 if !assert.NoError(t, err) { 396 return 397 } 398 pubkey2, err := jwk.FromRaw(&key.PublicKey) 399 if !assert.NoError(t, err) { 400 return 401 } 402 403 pubkey1.Set(jwk.KeyIDKey, kid) 404 pubkey2.Set(jwk.KeyIDKey, "test-jwt-parse-verify-kid-2") 405 signedNoKid, err := jwt.Sign(t1, jwt.WithKey(alg, key)) 406 if err != nil { 407 t.Fatal("Failed to sign JWT") 408 } 409 set := jwk.NewSet() 410 set.AddKey(pubkey1) 411 set.AddKey(pubkey2) 412 _, err = jwt.Parse(signedNoKid, jwt.WithKeySet(set, jws.WithUseDefault(true))) 413 if !assert.Error(t, err, `jwt.Parse should fail`) { 414 return 415 } 416 }) 417 // This is a test to check if we allow alg: none in the protected header section. 418 // But in truth, since we delegate everything to jws.Verify anyways, it's really 419 // a test to see if jws.Verify returns an error if alg: none is specified in the 420 // header section. Move this test to jws if need be. 421 t.Run("Check alg=none", func(t *testing.T) { 422 t.Parallel() 423 // Create a signed payload, but use alg=none 424 _, payload, signature, err := jws.SplitCompact(signed) 425 if !assert.NoError(t, err, `jws.SplitCompact should succeed`) { 426 return 427 } 428 429 dummyHeader := jws.NewHeaders() 430 ctx, cancel := context.WithCancel(context.Background()) 431 defer cancel() 432 for iter := hdrs.Iterate(ctx); iter.Next(ctx); { 433 pair := iter.Pair() 434 dummyHeader.Set(pair.Key.(string), pair.Value) 435 } 436 dummyHeader.Set(jws.AlgorithmKey, jwa.NoSignature) 437 438 dummyMarshaled, err := json.Marshal(dummyHeader) 439 if !assert.NoError(t, err, `json.Marshal should succeed`) { 440 return 441 } 442 dummyEncoded := make([]byte, base64.RawURLEncoding.EncodedLen(len(dummyMarshaled))) 443 base64.RawURLEncoding.Encode(dummyEncoded, dummyMarshaled) 444 445 signedButNot := bytes.Join([][]byte{dummyEncoded, payload, signature}, []byte{'.'}) 446 447 pubkey, err := jwk.FromRaw(&key.PublicKey) 448 if !assert.NoError(t, err) { 449 return 450 } 451 452 pubkey.Set(jwk.KeyIDKey, kid) 453 454 set := jwk.NewSet() 455 set.AddKey(pubkey) 456 _, err = jwt.Parse(signedButNot, jwt.WithKeySet(set)) 457 // This should fail 458 if !assert.Error(t, err, `jwt.Parse with key set + alg=none should fail`) { 459 return 460 } 461 }) 462 }) 463 } 464 465 func TestValidateClaims(t *testing.T) { 466 t.Parallel() 467 // GitHub issue #37: tokens are invalid in the second they are created (because Now() is not after IssuedAt()) 468 t.Run("Empty fields", func(t *testing.T) { 469 token := jwt.New() 470 471 if !assert.Error(t, jwt.Validate(token, jwt.WithIssuer("foo")), `token.Validate should fail`) { 472 return 473 } 474 if !assert.Error(t, jwt.Validate(token, jwt.WithJwtID("foo")), `token.Validate should fail`) { 475 return 476 } 477 if !assert.Error(t, jwt.Validate(token, jwt.WithSubject("foo")), `token.Validate should fail`) { 478 return 479 } 480 }) 481 t.Run(jwt.IssuedAtKey+"+skew", func(t *testing.T) { 482 t.Parallel() 483 token := jwt.New() 484 now := time.Now().UTC() 485 token.Set(jwt.IssuedAtKey, now) 486 487 const DefaultSkew = 0 488 489 args := []jwt.ValidateOption{ 490 jwt.WithClock(jwt.ClockFunc(func() time.Time { return now })), 491 jwt.WithAcceptableSkew(DefaultSkew), 492 } 493 494 if !assert.NoError(t, jwt.Validate(token, args...), "token.Validate should validate tokens in the same second they are created") { 495 if now.Equal(token.IssuedAt()) { 496 t.Errorf("iat claim failed: iat == now") 497 } 498 return 499 } 500 }) 501 } 502 503 const aLongLongTimeAgo = 233431200 504 const aLongLongTimeAgoString = "233431200" 505 506 func TestUnmarshal(t *testing.T) { 507 t.Parallel() 508 testcases := []struct { 509 Title string 510 Source string 511 Expected func() jwt.Token 512 ExpectedJSON string 513 }{ 514 { 515 Title: "single aud", 516 Source: `{"aud":"foo"}`, 517 Expected: func() jwt.Token { 518 t := jwt.New() 519 t.Set("aud", "foo") 520 return t 521 }, 522 ExpectedJSON: `{"aud":["foo"]}`, 523 }, 524 { 525 Title: "multiple aud's", 526 Source: `{"aud":["foo","bar"]}`, 527 Expected: func() jwt.Token { 528 t := jwt.New() 529 t.Set("aud", []string{"foo", "bar"}) 530 return t 531 }, 532 ExpectedJSON: `{"aud":["foo","bar"]}`, 533 }, 534 { 535 Title: "issuedAt", 536 Source: `{"` + jwt.IssuedAtKey + `":` + aLongLongTimeAgoString + `}`, 537 Expected: func() jwt.Token { 538 t := jwt.New() 539 t.Set(jwt.IssuedAtKey, aLongLongTimeAgo) 540 return t 541 }, 542 ExpectedJSON: `{"` + jwt.IssuedAtKey + `":` + aLongLongTimeAgoString + `}`, 543 }, 544 } 545 546 for _, tc := range testcases { 547 tc := tc 548 t.Run(tc.Title, func(t *testing.T) { 549 t.Parallel() 550 token := jwt.New() 551 if !assert.NoError(t, json.Unmarshal([]byte(tc.Source), &token), `json.Unmarshal should succeed`) { 552 return 553 } 554 if !assert.Equal(t, tc.Expected(), token, `token should match expected value`) { 555 return 556 } 557 558 var buf bytes.Buffer 559 if !assert.NoError(t, json.NewEncoder(&buf).Encode(token), `json.Marshal should succeed`) { 560 return 561 } 562 if !assert.Equal(t, tc.ExpectedJSON, strings.TrimSpace(buf.String()), `json should match`) { 563 return 564 } 565 }) 566 } 567 } 568 569 func TestGH52(t *testing.T) { 570 if testing.Short() { 571 t.SkipNow() 572 } 573 574 t.Parallel() 575 priv, err := jwxtest.GenerateEcdsaKey(jwa.P521) 576 if !assert.NoError(t, err) { 577 return 578 } 579 580 pub := &priv.PublicKey 581 if !assert.NoError(t, err) { 582 return 583 } 584 const max = 100 585 var wg sync.WaitGroup 586 wg.Add(max) 587 for i := 0; i < max; i++ { 588 // Do not use t.Run here as it will clutter up the outpuA 589 go func(t *testing.T, priv *ecdsa.PrivateKey, i int) { 590 defer wg.Done() 591 tok := jwt.New() 592 593 s, err := jwt.Sign(tok, jwt.WithKey(jwa.ES256, priv)) 594 if !assert.NoError(t, err) { 595 return 596 } 597 598 if _, err = jws.Verify(s, jws.WithKey(jwa.ES256, pub)); !assert.NoError(t, err, `test should pass (run %d)`, i) { 599 return 600 } 601 }(t, priv, i) 602 } 603 wg.Wait() 604 } 605 606 func TestUnmarshalJSON(t *testing.T) { 607 t.Parallel() 608 t.Run("Unmarshal audience with multiple values", func(t *testing.T) { 609 t.Parallel() 610 t1 := jwt.New() 611 if !assert.NoError(t, json.Unmarshal([]byte(`{"aud":["foo", "bar", "baz"]}`), &t1), `jwt.Parse should succeed`) { 612 return 613 } 614 aud, ok := t1.Get(jwt.AudienceKey) 615 if !assert.True(t, ok, `jwt.Get(jwt.AudienceKey) should succeed`) { 616 t.Logf("%#v", t1) 617 return 618 } 619 620 if !assert.Equal(t, aud.([]string), []string{"foo", "bar", "baz"}, "audience should match. got %v", aud) { 621 return 622 } 623 }) 624 } 625 626 func TestSignErrors(t *testing.T) { 627 t.Parallel() 628 priv, err := jwxtest.GenerateEcdsaKey(jwa.P521) 629 if !assert.NoError(t, err, `jwxtest.GenerateEcdsaKey should succeed`) { 630 return 631 } 632 633 tok := jwt.New() 634 _, err = jwt.Sign(tok, jwt.WithKey(jwa.SignatureAlgorithm("BOGUS"), priv)) 635 if !assert.Error(t, err) { 636 return 637 } 638 639 if !assert.Contains(t, err.Error(), `unsupported signature algorithm "BOGUS"`) { 640 return 641 } 642 643 _, err = jwt.Sign(tok, jwt.WithKey(jwa.ES256, nil)) 644 if !assert.Error(t, err) { 645 return 646 } 647 648 if !assert.Contains(t, err.Error(), "missing private key") { 649 return 650 } 651 } 652 653 func TestSignJWK(t *testing.T) { 654 t.Parallel() 655 priv, err := jwxtest.GenerateRsaKey() 656 assert.Nil(t, err) 657 658 key, err := jwk.FromRaw(priv) 659 assert.Nil(t, err) 660 661 key.Set(jwk.KeyIDKey, "test") 662 key.Set(jwk.AlgorithmKey, jwa.RS256) 663 664 tok := jwt.New() 665 signed, err := jwt.Sign(tok, jwt.WithKey(key.Algorithm(), key)) 666 assert.Nil(t, err) 667 668 header, err := jws.ParseString(string(signed)) 669 assert.Nil(t, err) 670 671 signatures := header.LookupSignature("test") 672 assert.Len(t, signatures, 1) 673 } 674 675 func getJWTHeaders(jwt []byte) (jws.Headers, error) { 676 msg, err := jws.Parse(jwt) 677 if err != nil { 678 return nil, err 679 } 680 return msg.Signatures()[0].ProtectedHeaders(), nil 681 } 682 683 func TestSignTyp(t *testing.T) { 684 t.Parallel() 685 key, err := jwxtest.GenerateRsaKey() 686 if !assert.NoError(t, err) { 687 return 688 } 689 690 t.Run(`"typ" header parameter should be set to JWT by default`, func(t *testing.T) { 691 t.Parallel() 692 t1 := jwt.New() 693 signed, err := jwt.Sign(t1, jwt.WithKey(jwa.RS256, key)) 694 if !assert.NoError(t, err) { 695 return 696 } 697 got, err := getJWTHeaders(signed) 698 if !assert.NoError(t, err) { 699 return 700 } 701 if !assert.Equal(t, `JWT`, got.Type(), `"typ" header parameter should be set to JWT`) { 702 return 703 } 704 }) 705 706 t.Run(`"typ" header parameter should be customizable by WithHeaders`, func(t *testing.T) { 707 t.Parallel() 708 t1 := jwt.New() 709 hdrs := jws.NewHeaders() 710 hdrs.Set(`typ`, `custom-typ`) 711 signed, err := jwt.Sign(t1, jwt.WithKey(jwa.RS256, key, jws.WithProtectedHeaders(hdrs))) 712 if !assert.NoError(t, err) { 713 return 714 } 715 got, err := getJWTHeaders(signed) 716 if !assert.NoError(t, err) { 717 return 718 } 719 if !assert.Equal(t, `custom-typ`, got.Type(), `"typ" header parameter should be set to the custom value`) { 720 return 721 } 722 }) 723 } 724 725 func TestReadFile(t *testing.T) { 726 t.Parallel() 727 728 f, err := os.CreateTemp("", "test-read-file-*.jwt") 729 if !assert.NoError(t, err, `os.CreateTemp should succeed`) { 730 return 731 } 732 defer f.Close() 733 734 token := jwt.New() 735 token.Set(jwt.IssuerKey, `lestrrat`) 736 if !assert.NoError(t, json.NewEncoder(f).Encode(token), `json.NewEncoder.Encode should succeed`) { 737 return 738 } 739 740 if _, err := jwt.ReadFile(f.Name(), jwt.WithVerify(false), jwt.WithValidate(true), jwt.WithIssuer("lestrrat")); !assert.NoError(t, err, `jwt.ReadFile should succeed`) { 741 return 742 } 743 if _, err := jwt.ReadFile(f.Name(), jwt.WithVerify(false), jwt.WithValidate(true), jwt.WithIssuer("lestrrrrrat")); !assert.Error(t, err, `jwt.ReadFile should fail`) { 744 return 745 } 746 } 747 748 func TestCustomField(t *testing.T) { 749 // XXX has global effect!!! 750 jwt.RegisterCustomField(`x-birthday`, time.Time{}) 751 defer jwt.RegisterCustomField(`x-birthday`, nil) 752 753 expected := time.Date(2015, 11, 4, 5, 12, 52, 0, time.UTC) 754 bdaybytes, _ := expected.MarshalText() // RFC3339 755 756 var b strings.Builder 757 b.WriteString(`{"iss": "github.com/lesstrrat-go/jwx", "x-birthday": "`) 758 b.Write(bdaybytes) 759 b.WriteString(`"}`) 760 src := b.String() 761 762 t.Run("jwt.Parse", func(t *testing.T) { 763 token, err := jwt.ParseInsecure([]byte(src)) 764 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 765 t.Logf("%q", src) 766 return 767 } 768 769 v, ok := token.Get(`x-birthday`) 770 if !assert.True(t, ok, `token.Get("x-birthday") should succeed`) { 771 return 772 } 773 774 if !assert.Equal(t, expected, v, `values should match`) { 775 return 776 } 777 }) 778 t.Run("json.Unmarshal", func(t *testing.T) { 779 token := jwt.New() 780 if !assert.NoError(t, json.Unmarshal([]byte(src), token), `json.Unmarshal should succeed`) { 781 return 782 } 783 784 v, ok := token.Get(`x-birthday`) 785 if !assert.True(t, ok, `token.Get("x-birthday") should succeed`) { 786 return 787 } 788 789 if !assert.Equal(t, expected, v, `values should match`) { 790 return 791 } 792 }) 793 } 794 795 func TestParseRequest(t *testing.T) { 796 const u = "https://github.com/lestrrat-gow/jwx/jwt" 797 798 privkey, _ := jwxtest.GenerateEcdsaJwk() 799 privkey.Set(jwk.AlgorithmKey, jwa.ES256) 800 privkey.Set(jwk.KeyIDKey, `my-awesome-key`) 801 pubkey, _ := jwk.PublicKeyOf(privkey) 802 pubkey.Set(jwk.AlgorithmKey, jwa.ES256) 803 804 tok := jwt.New() 805 tok.Set(jwt.IssuerKey, u) 806 tok.Set(jwt.IssuedAtKey, time.Now().Round(0)) 807 808 signed, _ := jwt.Sign(tok, jwt.WithKey(jwa.ES256, privkey)) 809 810 testcases := []struct { 811 Request func() *http.Request 812 Parse func(*http.Request) (jwt.Token, error) 813 Name string 814 Error bool 815 }{ 816 { 817 Name: "Token not present (w/ multiple options)", 818 Request: func() *http.Request { 819 return httptest.NewRequest(http.MethodGet, u, nil) 820 }, 821 Parse: func(req *http.Request) (jwt.Token, error) { 822 return jwt.ParseRequest(req, 823 jwt.WithHeaderKey("Authorization"), 824 jwt.WithHeaderKey("x-authorization"), 825 jwt.WithFormKey("access_token"), 826 jwt.WithFormKey("token"), 827 jwt.WithKey(jwa.ES256, pubkey)) 828 }, 829 Error: true, 830 }, 831 { 832 Name: "Token not present (w/o options)", 833 Request: func() *http.Request { 834 return httptest.NewRequest(http.MethodGet, u, nil) 835 }, 836 Parse: func(req *http.Request) (jwt.Token, error) { 837 return jwt.ParseRequest(req, jwt.WithKey(jwa.ES256, pubkey)) 838 }, 839 Error: true, 840 }, 841 { 842 Name: "Token in Authorization header (w/o extra options)", 843 Request: func() *http.Request { 844 req := httptest.NewRequest(http.MethodGet, u, nil) 845 req.Header.Add("Authorization", "Bearer "+string(signed)) 846 return req 847 }, 848 Parse: func(req *http.Request) (jwt.Token, error) { 849 return jwt.ParseRequest(req, jwt.WithKey(jwa.ES256, pubkey)) 850 }, 851 }, 852 { 853 Name: "Token in Authorization header (w/o extra options, using jwk.Set)", 854 Request: func() *http.Request { 855 req := httptest.NewRequest(http.MethodGet, u, nil) 856 req.Header.Add("Authorization", "Bearer "+string(signed)) 857 return req 858 }, 859 Parse: func(req *http.Request) (jwt.Token, error) { 860 set := jwk.NewSet() 861 set.AddKey(pubkey) 862 return jwt.ParseRequest(req, jwt.WithKeySet(set)) 863 }, 864 }, 865 { 866 Name: "Token in Authorization header but we specified another header key", 867 Request: func() *http.Request { 868 req := httptest.NewRequest(http.MethodGet, u, nil) 869 req.Header.Add("Authorization", "Bearer "+string(signed)) 870 return req 871 }, 872 Parse: func(req *http.Request) (jwt.Token, error) { 873 return jwt.ParseRequest(req, jwt.WithHeaderKey("x-authorization"), jwt.WithKey(jwa.ES256, pubkey)) 874 }, 875 Error: true, 876 }, 877 { 878 Name: "Token in x-authorization header (w/ option)", 879 Request: func() *http.Request { 880 req := httptest.NewRequest(http.MethodGet, u, nil) 881 req.Header.Add("x-authorization", string(signed)) 882 return req 883 }, 884 Parse: func(req *http.Request) (jwt.Token, error) { 885 return jwt.ParseRequest(req, jwt.WithHeaderKey("x-authorization"), jwt.WithKey(jwa.ES256, pubkey)) 886 }, 887 }, 888 { 889 Name: "Invalid token in x-authorization header", 890 Request: func() *http.Request { 891 req := httptest.NewRequest(http.MethodGet, u, nil) 892 req.Header.Add("x-authorization", string(signed)+"foobarbaz") 893 return req 894 }, 895 Parse: func(req *http.Request) (jwt.Token, error) { 896 return jwt.ParseRequest(req, jwt.WithHeaderKey("x-authorization"), jwt.WithKey(jwa.ES256, pubkey)) 897 }, 898 Error: true, 899 }, 900 { 901 Name: "Token in access_token form field (w/ option)", 902 Request: func() *http.Request { 903 req := httptest.NewRequest(http.MethodPost, u, nil) 904 // for whatever reason, I can't populate req.Body and get this to work 905 // so populating req.Form directly instead 906 req.Form = url.Values{} 907 req.Form.Add("access_token", string(signed)) 908 return req 909 }, 910 Parse: func(req *http.Request) (jwt.Token, error) { 911 return jwt.ParseRequest(req, jwt.WithFormKey("access_token"), jwt.WithKey(jwa.ES256, pubkey)) 912 }, 913 }, 914 { 915 Name: "Token in access_token form field (w/o option)", 916 Request: func() *http.Request { 917 req := httptest.NewRequest(http.MethodPost, u, nil) 918 // for whatever reason, I can't populate req.Body and get this to work 919 // so populating req.Form directly instead 920 req.Form = url.Values{} 921 req.Form.Add("access_token", string(signed)) 922 return req 923 }, 924 Parse: func(req *http.Request) (jwt.Token, error) { 925 return jwt.ParseRequest(req, jwt.WithKey(jwa.ES256, pubkey)) 926 }, 927 Error: true, 928 }, 929 { 930 Name: "Invalid token in access_token form field", 931 Request: func() *http.Request { 932 req := httptest.NewRequest(http.MethodPost, u, nil) 933 // for whatever reason, I can't populate req.Body and get this to work 934 // so populating req.Form directly instead 935 req.Form = url.Values{} 936 req.Form.Add("access_token", string(signed)+"foobarbarz") 937 return req 938 }, 939 Parse: func(req *http.Request) (jwt.Token, error) { 940 return jwt.ParseRequest(req, jwt.WithKey(jwa.ES256, pubkey), jwt.WithFormKey("access_token")) 941 }, 942 Error: true, 943 }, 944 } 945 946 for _, tc := range testcases { 947 tc := tc 948 t.Run(tc.Name, func(t *testing.T) { 949 got, err := tc.Parse(tc.Request()) 950 if tc.Error { 951 t.Logf("%s", err) 952 assert.Error(t, err, `tc.Parse should fail`) 953 return 954 } 955 956 if !assert.NoError(t, err, `tc.Parse should succeed`) { 957 return 958 } 959 960 if !assert.True(t, jwt.Equal(tok, got), `tokens should match`) { 961 { 962 buf, _ := json.MarshalIndent(tok, "", " ") 963 t.Logf("expected: %s", buf) 964 } 965 { 966 buf, _ := json.MarshalIndent(got, "", " ") 967 t.Logf("got: %s", buf) 968 } 969 return 970 } 971 }) 972 } 973 } 974 975 func TestGHIssue368(t *testing.T) { 976 // DO NOT RUN THIS IN PARALLEL 977 t.Run("Per-object control of flatten audience", func(t *testing.T) { 978 for _, globalFlatten := range []bool{true, false} { 979 globalFlatten := globalFlatten 980 for _, perObjectFlatten := range []bool{true, false} { 981 perObjectFlatten := perObjectFlatten 982 // per-object settings always wins 983 t.Run(fmt.Sprintf("Global=%t, Per-Object=%t", globalFlatten, perObjectFlatten), func(t *testing.T) { 984 defer jwt.Settings(jwt.WithFlattenAudience(false)) 985 jwt.Settings(jwt.WithFlattenAudience(globalFlatten)) 986 987 tok, _ := jwt.NewBuilder(). 988 Audience([]string{"hello"}). 989 Build() 990 991 if perObjectFlatten { 992 tok.Options().Enable(jwt.FlattenAudience) 993 } else { 994 tok.Options().Disable(jwt.FlattenAudience) 995 } 996 buf, err := json.MarshalIndent(tok, "", " ") 997 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) { 998 return 999 } 1000 1001 var expected string 1002 if perObjectFlatten { 1003 expected = `{ 1004 "aud": "hello" 1005 }` 1006 } else { 1007 expected = `{ 1008 "aud": [ 1009 "hello" 1010 ] 1011 }` 1012 } 1013 1014 if !assert.Equal(t, expected, string(buf), `output should match`) { 1015 return 1016 } 1017 }) 1018 } 1019 } 1020 }) 1021 1022 for _, flatten := range []bool{true, false} { 1023 flatten := flatten 1024 t.Run(fmt.Sprintf("Test serialization (WithFlattenAudience(%t))", flatten), func(t *testing.T) { 1025 jwt.Settings(jwt.WithFlattenAudience(flatten)) 1026 1027 t.Run("Single Key", func(t *testing.T) { 1028 tok := jwt.New() 1029 _ = tok.Set(jwt.AudienceKey, "hello") 1030 1031 buf, err := json.MarshalIndent(tok, "", " ") 1032 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) { 1033 return 1034 } 1035 1036 var expected string 1037 if flatten { 1038 expected = `{ 1039 "aud": "hello" 1040 }` 1041 } else { 1042 expected = `{ 1043 "aud": [ 1044 "hello" 1045 ] 1046 }` 1047 } 1048 1049 if !assert.Equal(t, expected, string(buf), `output should match`) { 1050 return 1051 } 1052 }) 1053 t.Run("Multiple Keys", func(t *testing.T) { 1054 tok, err := jwt.NewBuilder(). 1055 Audience([]string{"hello", "world"}). 1056 Build() 1057 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1058 return 1059 } 1060 1061 buf, err := json.MarshalIndent(tok, "", " ") 1062 if !assert.NoError(t, err, `json.MarshalIndent should succeed`) { 1063 return 1064 } 1065 1066 const expected = `{ 1067 "aud": [ 1068 "hello", 1069 "world" 1070 ] 1071 }` 1072 1073 if !assert.Equal(t, expected, string(buf), `output should match`) { 1074 return 1075 } 1076 }) 1077 }) 1078 } 1079 } 1080 1081 func TestGH375(t *testing.T) { 1082 key, err := jwxtest.GenerateRsaJwk() 1083 if !assert.NoError(t, err, `jwxtest.GenerateRsaJwk should succeed`) { 1084 return 1085 } 1086 key.Set(jwk.KeyIDKey, `test`) 1087 1088 token, err := jwt.NewBuilder(). 1089 Issuer(`foobar`). 1090 Build() 1091 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1092 return 1093 } 1094 1095 signAlg := jwa.RS512 1096 signed, err := jwt.Sign(token, jwt.WithKey(signAlg, key)) 1097 if !assert.NoError(t, err, `jwt.Sign should succeed`) { 1098 return 1099 } 1100 1101 verifyKey, err := jwk.PublicKeyOf(key) 1102 if !assert.NoError(t, err, `jwk.PublicKeyOf should succeed`) { 1103 return 1104 } 1105 1106 verifyKey.Set(jwk.KeyIDKey, `test`) 1107 verifyKey.Set(jwk.AlgorithmKey, jwa.RS256) // != jwa.RS512 1108 1109 ks := jwk.NewSet() 1110 ks.AddKey(verifyKey) 1111 1112 _, err = jwt.Parse(signed, jwt.WithKeySet(ks)) 1113 if !assert.Error(t, err, `jwt.Parse should fail`) { 1114 return 1115 } 1116 } 1117 1118 type Claim struct { 1119 Foo string 1120 Bar int 1121 } 1122 1123 func TestJWTParseWithTypedClaim(t *testing.T) { 1124 testcases := []struct { 1125 Name string 1126 Options []jwt.ParseOption 1127 PostProcess func(*testing.T, interface{}) (*Claim, error) 1128 }{ 1129 { 1130 Name: "Basic", 1131 Options: []jwt.ParseOption{jwt.WithTypedClaim("typed-claim", Claim{})}, 1132 PostProcess: func(t *testing.T, claim interface{}) (*Claim, error) { 1133 t.Helper() 1134 v, ok := claim.(Claim) 1135 if !ok { 1136 return nil, fmt.Errorf(`claim value should be of type "Claim", but got %T`, claim) 1137 } 1138 return &v, nil 1139 }, 1140 }, 1141 { 1142 Name: "json.RawMessage", 1143 Options: []jwt.ParseOption{jwt.WithTypedClaim("typed-claim", json.RawMessage{})}, 1144 PostProcess: func(t *testing.T, claim interface{}) (*Claim, error) { 1145 t.Helper() 1146 v, ok := claim.(json.RawMessage) 1147 if !ok { 1148 return nil, fmt.Errorf(`claim value should be of type "json.RawMessage", but got %T`, claim) 1149 } 1150 1151 var c Claim 1152 if err := json.Unmarshal(v, &c); err != nil { 1153 return nil, fmt.Errorf(`json.Unmarshal failed: %w`, err) 1154 } 1155 1156 return &c, nil 1157 }, 1158 }, 1159 } 1160 1161 expected := &Claim{Foo: "Foo", Bar: 0xdeadbeef} 1162 key, err := jwxtest.GenerateRsaKey() 1163 if !assert.NoError(t, err, `jwxtest.GenerateRsaKey should succeed`) { 1164 return 1165 } 1166 1167 var signed []byte 1168 { 1169 token := jwt.New() 1170 if !assert.NoError(t, token.Set("typed-claim", expected), `expected.Set should succeed`) { 1171 return 1172 } 1173 v, err := jwt.Sign(token, jwt.WithKey(jwa.RS256, key)) 1174 if !assert.NoError(t, err, `jwt.Sign should succeed`) { 1175 return 1176 } 1177 signed = v 1178 } 1179 1180 for _, tc := range testcases { 1181 tc := tc 1182 t.Run(tc.Name, func(t *testing.T) { 1183 options := append(tc.Options, jwt.WithVerify(false)) 1184 got, err := jwt.Parse(signed, options...) 1185 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 1186 return 1187 } 1188 1189 v, ok := got.Get("typed-claim") 1190 if !assert.True(t, ok, `got.Get() should succeed`) { 1191 return 1192 } 1193 claim, err := tc.PostProcess(t, v) 1194 if !assert.NoError(t, err, `tc.PostProcess should succeed`) { 1195 return 1196 } 1197 1198 if !assert.Equal(t, claim, expected, `claim should match expected value`) { 1199 return 1200 } 1201 }) 1202 } 1203 } 1204 1205 func TestGH393(t *testing.T) { 1206 t.Run("Non-existent required claims", func(t *testing.T) { 1207 tok := jwt.New() 1208 if !assert.Error(t, jwt.Validate(tok, jwt.WithRequiredClaim(jwt.IssuedAtKey)), `jwt.Validate should fail`) { 1209 return 1210 } 1211 }) 1212 t.Run("exp - iat < WithMaxDelta(10 secs)", func(t *testing.T) { 1213 now := time.Now() 1214 tok, err := jwt.NewBuilder(). 1215 IssuedAt(now). 1216 Expiration(now.Add(5 * time.Second)). 1217 Build() 1218 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1219 return 1220 } 1221 1222 if !assert.Error(t, jwt.Validate(tok, jwt.WithMaxDelta(2*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey)), `jwt.Validate should fail`) { 1223 return 1224 } 1225 1226 if !assert.NoError(t, jwt.Validate(tok, jwt.WithMaxDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey)), `jwt.Validate should succeed`) { 1227 return 1228 } 1229 }) 1230 t.Run("iat - exp (5 secs) < WithMinDelta(10 secs)", func(t *testing.T) { 1231 now := time.Now() 1232 tok, err := jwt.NewBuilder(). 1233 IssuedAt(now). 1234 Expiration(now.Add(5 * time.Second)). 1235 Build() 1236 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1237 return 1238 } 1239 1240 if !assert.Error(t, jwt.Validate(tok, jwt.WithMinDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey)), `jwt.Validate should fail`) { 1241 return 1242 } 1243 }) 1244 t.Run("iat - exp (5 secs) > WithMinDelta(10 secs)", func(t *testing.T) { 1245 now := time.Now() 1246 tok, err := jwt.NewBuilder(). 1247 IssuedAt(now). 1248 Expiration(now.Add(5 * time.Second)). 1249 Build() 1250 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1251 return 1252 } 1253 1254 if !assert.NoError(t, jwt.Validate(tok, jwt.WithMinDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey), jwt.WithAcceptableSkew(5*time.Second)), `jwt.Validate should succeed`) { 1255 return 1256 } 1257 }) 1258 t.Run("now - iat < WithMaxDelta(10 secs)", func(t *testing.T) { 1259 now := time.Now() 1260 tok, err := jwt.NewBuilder(). 1261 IssuedAt(now). 1262 Build() 1263 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1264 return 1265 } 1266 1267 if !assert.NoError(t, jwt.Validate(tok, jwt.WithMaxDelta(10*time.Second, "", jwt.IssuedAtKey), jwt.WithClock(jwt.ClockFunc(func() time.Time { return now.Add(5 * time.Second) }))), `jwt.Validate should succeed`) { 1268 return 1269 } 1270 }) 1271 t.Run("invalid claim name (c1)", func(t *testing.T) { 1272 now := time.Now() 1273 tok, err := jwt.NewBuilder(). 1274 Claim("foo", now). 1275 Expiration(now.Add(5 * time.Second)). 1276 Build() 1277 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1278 return 1279 } 1280 1281 if !assert.Error(t, jwt.Validate(tok, jwt.WithMinDelta(10*time.Second, jwt.ExpirationKey, "foo"), jwt.WithAcceptableSkew(5*time.Second)), `jwt.Validate should fail`) { 1282 return 1283 } 1284 }) 1285 t.Run("invalid claim name (c2)", func(t *testing.T) { 1286 now := time.Now() 1287 tok, err := jwt.NewBuilder(). 1288 Claim("foo", now.Add(5*time.Second)). 1289 IssuedAt(now). 1290 Build() 1291 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1292 return 1293 } 1294 1295 if !assert.Error(t, jwt.Validate(tok, jwt.WithMinDelta(10*time.Second, "foo", jwt.IssuedAtKey), jwt.WithAcceptableSkew(5*time.Second)), `jwt.Validate should fail`) { 1296 return 1297 } 1298 }) 1299 1300 // Following tests deviate a little from the original issue, but 1301 // since they were added for the same issue, we just bundle the 1302 // tests together 1303 t.Run(`WithRequiredClaim fails for non-existent claim`, func(t *testing.T) { 1304 tok := jwt.New() 1305 if !assert.Error(t, jwt.Validate(tok, jwt.WithRequiredClaim("foo")), `jwt.Validate should fail`) { 1306 return 1307 } 1308 }) 1309 t.Run(`WithRequiredClaim succeeds for existing claim`, func(t *testing.T) { 1310 tok, err := jwt.NewBuilder(). 1311 Claim(`foo`, 1). 1312 Build() 1313 if !assert.NoError(t, err, `jwt.Builder should succeed`) { 1314 return 1315 } 1316 if !assert.NoError(t, jwt.Validate(tok, jwt.WithRequiredClaim("foo")), `jwt.Validate should fail`) { 1317 return 1318 } 1319 }) 1320 } 1321 1322 func TestGH430(t *testing.T) { 1323 t1 := jwt.New() 1324 err := t1.Set("payload", map[string]interface{}{ 1325 "name": "someone", 1326 }) 1327 if !assert.NoError(t, err, `t1.Set should succeed`) { 1328 return 1329 } 1330 1331 key := []byte("secret") 1332 signed, err := jwt.Sign(t1, jwt.WithKey(jwa.HS256, key)) 1333 if !assert.NoError(t, err, `jwt.Sign should succeed`) { 1334 return 1335 } 1336 1337 if _, err = jwt.Parse(signed, jwt.WithKey(jwa.HS256, key)); !assert.NoError(t, err, `jwt.Parse should succeed`) { 1338 return 1339 } 1340 } 1341 1342 func TestGH706(t *testing.T) { 1343 err := jwt.Validate(jwt.New(), jwt.WithRequiredClaim("foo")) 1344 if !assert.True(t, jwt.IsValidationError(err), `error should be a validation error`) { 1345 return 1346 } 1347 1348 if !assert.ErrorIs(t, err, jwt.ErrRequiredClaim(), `jwt.Validate should fail`) { 1349 return 1350 } 1351 } 1352 1353 func TestBenHigginsByPassRegression(t *testing.T) { 1354 key, err := rsa.GenerateKey(rand.Reader, 2048) 1355 if err != nil { 1356 panic(err) 1357 } 1358 // Test if an access token JSON payload parses when provided directly 1359 // 1360 // The JSON below is slightly modified example payload from: 1361 // https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html 1362 1363 // Case 1: add "aud", and adjust exp to be valid 1364 // Case 2: do not add "aud", adjust exp 1365 1366 exp := strconv.Itoa(int(time.Now().Unix()) + 1000) 1367 const tmpl = `{%s 1368 "sub": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 1369 "device_key": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 1370 "cognito:groups": ["admin"], 1371 "token_use": "access", 1372 "scope": "aws.cognito.signin.user.admin", 1373 "auth_time": 1562190524, 1374 "iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_example", 1375 "exp": %s, 1376 "iat": 1562190524, 1377 "origin_jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 1378 "jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 1379 "client_id": "57cbishk4j24pabc1234567890", 1380 "username": "janedoe@example.com" 1381 }` 1382 1383 testcases := [][]byte{ 1384 []byte(fmt.Sprintf(tmpl, `"aud": ["test"],`, exp)), 1385 []byte(fmt.Sprintf(tmpl, ``, exp)), 1386 } 1387 1388 for _, tc := range testcases { 1389 for _, pedantic := range []bool{true, false} { 1390 _, err = jwt.Parse( 1391 tc, 1392 jwt.WithValidate(true), 1393 jwt.WithPedantic(pedantic), 1394 jwt.WithKey(jwa.RS256, &key.PublicKey), 1395 ) 1396 t.Logf("%s", err) 1397 if !assert.Error(t, err, `jwt.Parse should fail`) { 1398 return 1399 } 1400 } 1401 } 1402 } 1403 1404 func TestVerifyAuto(t *testing.T) { 1405 key, err := jwxtest.GenerateRsaJwk() 1406 if !assert.NoError(t, err, `jwxtest.GenerateRsaJwk should succeed`) { 1407 return 1408 } 1409 1410 key.Set(jwk.KeyIDKey, `my-awesome-key`) 1411 1412 pubkey, err := jwk.PublicKeyOf(key) 1413 if !assert.NoError(t, err, `jwk.PublicKeyOf should succeed`) { 1414 return 1415 } 1416 set := jwk.NewSet() 1417 set.AddKey(pubkey) 1418 backoffCount := 0 1419 srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1420 switch r.URL.Query().Get(`type`) { 1421 case "backoff": 1422 backoffCount++ 1423 if backoffCount == 1 { 1424 w.WriteHeader(http.StatusInternalServerError) 1425 return 1426 } 1427 } 1428 w.WriteHeader(http.StatusOK) 1429 json.NewEncoder(w).Encode(set) 1430 })) 1431 defer srv.Close() 1432 1433 tok, err := jwt.NewBuilder(). 1434 Claim(jwt.IssuerKey, `https://github.com/lestrrat-go/jwx/v2`). 1435 Claim(jwt.SubjectKey, `jku-test`). 1436 Build() 1437 1438 if !assert.NoError(t, err, `jwt.NewBuilder.Build() should succeed`) { 1439 return 1440 } 1441 1442 hdrs := jws.NewHeaders() 1443 hdrs.Set(jws.JWKSetURLKey, srv.URL) 1444 1445 signed, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, key, jws.WithProtectedHeaders(hdrs))) 1446 if !assert.NoError(t, err, `jwt.Sign() should succeed`) { 1447 return 1448 } 1449 1450 wl := jwk.NewMapWhitelist(). 1451 Add(srv.URL) 1452 1453 parsed, err := jwt.Parse(signed, jwt.WithVerifyAuto(nil, jwk.WithFetchWhitelist(wl), jwk.WithHTTPClient(srv.Client()))) 1454 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 1455 return 1456 } 1457 1458 if !assert.True(t, jwt.Equal(tok, parsed), `tokens should be equal`) { 1459 return 1460 } 1461 1462 _, err = jwt.Parse(signed, jwt.WithVerifyAuto(nil)) 1463 if !assert.Error(t, err, `jwt.Parse should fail`) { 1464 return 1465 } 1466 wl = jwk.NewMapWhitelist(). 1467 Add(`https://github.com/lestrrat-go/jwx/v2`) 1468 _, err = jwt.Parse(signed, jwt.WithVerifyAuto(nil, jwk.WithFetchWhitelist(wl))) 1469 if !assert.Error(t, err, `jwt.Parse should fail`) { 1470 return 1471 } 1472 1473 // now with Cache 1474 c := jwk.NewCache(context.TODO()) 1475 parsed, err = jwt.Parse(signed, 1476 jwt.WithVerifyAuto( 1477 jwk.FetchFunc(func(ctx context.Context, u string, options ...jwk.FetchOption) (jwk.Set, error) { 1478 var registeropts []jwk.RegisterOption 1479 // jwk.FetchOption is also an CacheOption, but the container 1480 // doesn't match the signature... so... we need to convert them... 1481 for _, option := range options { 1482 registeropts = append(registeropts, option) 1483 } 1484 c.Register(u, registeropts...) 1485 return c.Get(ctx, u) 1486 }), 1487 jwk.WithHTTPClient(srv.Client()), 1488 jwk.WithFetchWhitelist(jwk.InsecureWhitelist{}), 1489 ), 1490 ) 1491 if !assert.NoError(t, err, `jwt.Parse should succeed`) { 1492 return 1493 } 1494 1495 if !assert.True(t, jwt.Equal(tok, parsed), `tokens should be equal`) { 1496 return 1497 } 1498 } 1499 1500 func TestSerializer(t *testing.T) { 1501 t.Run(`Invalid sign suboption`, func(t *testing.T) { 1502 _, err := jwt.NewSerializer(). 1503 Sign(jwt.WithKey(jwa.HS256, []byte("abracadabra"), jwe.WithCompress(jwa.Deflate))). 1504 Serialize(jwt.New()) 1505 if !assert.Error(t, err, `Serialize() should fail`) { 1506 return 1507 } 1508 }) 1509 t.Run(`Invalid SignatureAglrotihm`, func(t *testing.T) { 1510 _, err := jwt.NewSerializer(). 1511 Encrypt(jwt.WithKey(jwa.A256KW, []byte("abracadabra"))). 1512 Serialize(jwt.New()) 1513 if !assert.Error(t, err, `Serialize() should succeedl`) { 1514 return 1515 } 1516 }) 1517 t.Run(`Invalid encrypt suboption`, func(t *testing.T) { 1518 _, err := jwt.NewSerializer(). 1519 Encrypt(jwt.WithKey(jwa.A256KW, []byte("abracadabra"), jws.WithPretty(true))). 1520 Serialize(jwt.New()) 1521 if !assert.Error(t, err, `Serialize() should fail`) { 1522 return 1523 } 1524 }) 1525 t.Run(`Invalid KeyEncryptionAglrotihm`, func(t *testing.T) { 1526 _, err := jwt.NewSerializer(). 1527 Encrypt(jwt.WithKey(jwa.HS256, []byte("abracadabra"))). 1528 Serialize(jwt.New()) 1529 if !assert.Error(t, err, `Serialize() should succeedl`) { 1530 return 1531 } 1532 }) 1533 } 1534 1535 func TestFractional(t *testing.T) { 1536 t.Run("FormatPrecision", func(t *testing.T) { 1537 var nd types.NumericDate 1538 jwt.Settings(jwt.WithNumericDateParsePrecision(int(types.MaxPrecision))) 1539 s := fmt.Sprintf("%d.100000001", aLongLongTimeAgo) 1540 _ = nd.Accept(s) 1541 jwt.Settings(jwt.WithNumericDateParsePrecision(0)) 1542 testcases := []struct { 1543 Input types.NumericDate 1544 Expected string 1545 Precision int 1546 }{ 1547 { 1548 Input: nd, 1549 Expected: fmt.Sprintf(`%d`, aLongLongTimeAgo), 1550 }, 1551 { 1552 Input: types.NumericDate{Time: time.Unix(0, 1).UTC()}, 1553 Expected: "0", 1554 }, 1555 { 1556 Input: types.NumericDate{Time: time.Unix(0, 1).UTC()}, 1557 Precision: 9, 1558 Expected: "0.000000001", 1559 }, 1560 { 1561 Input: types.NumericDate{Time: time.Unix(0, 100000000).UTC()}, 1562 Precision: 9, 1563 Expected: "0.100000000", 1564 }, 1565 } 1566 1567 for i := 1; i <= int(types.MaxPrecision); i++ { 1568 fractional := (fmt.Sprintf(`%d`, 100000001))[:i] 1569 testcases = append(testcases, struct { 1570 Input types.NumericDate 1571 Expected string 1572 Precision int 1573 }{ 1574 Input: nd, 1575 Precision: i, 1576 Expected: fmt.Sprintf(`%d.%s`, aLongLongTimeAgo, fractional), 1577 }) 1578 } 1579 1580 for _, tc := range testcases { 1581 tc := tc 1582 t.Run(fmt.Sprintf("%s (precision=%d)", tc.Input, tc.Precision), func(t *testing.T) { 1583 jwt.Settings(jwt.WithNumericDateFormatPrecision(tc.Precision)) 1584 require.Equal(t, tc.Expected, tc.Input.String()) 1585 }) 1586 } 1587 jwt.Settings(jwt.WithNumericDateFormatPrecision(0)) 1588 }) 1589 t.Run("ParsePrecision", func(t *testing.T) { 1590 const template = `{"iat":"%s"}` 1591 1592 testcases := []struct { 1593 Input string 1594 Expected time.Time 1595 Precision int 1596 }{ 1597 { 1598 Input: "0", 1599 Expected: time.Unix(0, 0).UTC(), 1600 }, 1601 { 1602 Input: "0.000000001", 1603 Expected: time.Unix(0, 0).UTC(), 1604 }, 1605 { 1606 Input: fmt.Sprintf("%d.111111111", aLongLongTimeAgo), 1607 Expected: time.Unix(aLongLongTimeAgo, 0).UTC(), 1608 }, 1609 { 1610 // Max precision 1611 Input: fmt.Sprintf("%d.100000001", aLongLongTimeAgo), 1612 Precision: int(types.MaxPrecision), 1613 Expected: time.Unix(aLongLongTimeAgo, 100000001).UTC(), 1614 }, 1615 } 1616 1617 for i := 1; i < int(types.MaxPrecision); i++ { 1618 testcases = append(testcases, struct { 1619 Input string 1620 Expected time.Time 1621 Precision int 1622 }{ 1623 Input: fmt.Sprintf("%d.100000001", aLongLongTimeAgo), 1624 Precision: i, 1625 Expected: time.Unix(aLongLongTimeAgo, 100000000).UTC(), 1626 }) 1627 } 1628 1629 for _, tc := range testcases { 1630 tc := tc 1631 t.Run(fmt.Sprintf("%s (precision=%d)", tc.Input, tc.Precision), func(t *testing.T) { 1632 jwt.Settings(jwt.WithNumericDateParsePrecision(tc.Precision)) 1633 tok, err := jwt.Parse( 1634 []byte(fmt.Sprintf(template, tc.Input)), 1635 jwt.WithVerify(false), 1636 jwt.WithValidate(false), 1637 ) 1638 require.NoError(t, err, `jwt.Parse should succeed`) 1639 1640 require.Equal(t, tc.Expected, tok.IssuedAt(), `iat should match`) 1641 }) 1642 } 1643 jwt.Settings(jwt.WithNumericDateParsePrecision(0)) 1644 }) 1645 } 1646 1647 func TestGH836(t *testing.T) { 1648 // tests on TokenOptionSet are found elsewhere. 1649 1650 t1 := jwt.New() 1651 t1.Options().Enable(jwt.FlattenAudience) 1652 1653 require.True(t, t1.Options().IsEnabled(jwt.FlattenAudience), `flag should be enabled`) 1654 1655 t2, err := t1.Clone() 1656 require.NoError(t, err, `t1.Clone should succeed`) 1657 1658 require.True(t, t2.Options().IsEnabled(jwt.FlattenAudience), `cloned token should have same settings`) 1659 1660 t2.Options().Disable(jwt.FlattenAudience) 1661 require.True(t, t1.Options().IsEnabled(jwt.FlattenAudience), `flag should be enabled (t2.Options should have no effect on t1.Options)`) 1662 } 1663 1664 func TestGH850(t *testing.T) { 1665 var testToken = `eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY2MDkxMzczLCJmb28iOiJiYXIifQ.3GWevx1z2_uCBB9Vj-D0rsT_CMsMeP9GP2rEqGDWpesoG8nHEjAXJOEQV1jOVkkCtTnS18JhcQdb7dW4i-zmqg.trailing-rubbish` 1666 1667 _, err := jwt.Parse([]byte(testToken), jwt.WithVerify(false)) 1668 require.True(t, errors.Is(err, jwt.ErrInvalidJWT())) 1669 } 1670 1671 func TestGH888(t *testing.T) { 1672 // Use of "none" is insecure, and we just don't allow it by default. 1673 // In order to allow none, we must tell jwx that we actually want it. 1674 token, err := jwt.NewBuilder(). 1675 Subject("foo"). 1676 Issuer("bar"). 1677 Build() 1678 1679 require.NoError(t, err, `jwt.Builder should succeed`) 1680 1681 // 1) "none" must be triggered by its own option. Can't use jwt.WithKey(jwa.NoSignature, ...) 1682 t.Run("jwt.Sign(token, jwt.WithKey(jwa.NoSignature)) should fail", func(t *testing.T) { 1683 _, err := jwt.Sign(token, jwt.WithKey(jwa.NoSignature, nil)) 1684 require.Error(t, err, `jwt.Sign with jwt.WithKey should fail`) 1685 }) 1686 t.Run("jwt.Sign(token, jwt.WithInsecureNoSignature())", func(t *testing.T) { 1687 signed, err := jwt.Sign(token, jwt.WithInsecureNoSignature()) 1688 require.NoError(t, err, `jwt.Sign should succeed`) 1689 1690 require.Equal(t, `eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJiYXIiLCJzdWIiOiJmb28ifQ.`, string(signed)) 1691 1692 _, err = jwt.Parse(signed) 1693 require.Error(t, err, `jwt.Parse with alg=none should fail`) 1694 }) 1695 } 1696 1697 func TestGH951(t *testing.T) { 1698 signKey, err := jwxtest.GenerateRsaKey() 1699 require.NoError(t, err, `jwxtest.GenerateRsaKey should succeed`) 1700 1701 sharedKey := []byte{ 1702 25, 172, 32, 130, 225, 114, 26, 181, 138, 106, 254, 192, 95, 133, 74, 82, 1703 } 1704 1705 token, err := jwt.NewBuilder(). 1706 Subject(`test-951`). 1707 Issuer(`jwt.Test951`). 1708 Build() 1709 require.NoError(t, err, `jwt.NewBuilder should succeed`) 1710 1711 // this whole workflow actually works even if the bug in #951 is present. 1712 // so we shall compare the results with and without the encryption 1713 // options to see if there is a difference in the length of the 1714 // cipher text, which is the second from last component in the message 1715 serialized, err := jwt.NewSerializer(). 1716 Sign(jwt.WithKey(jwa.RS256, signKey)). 1717 Encrypt( 1718 jwt.WithKey(jwa.A128KW, sharedKey), 1719 jwt.WithEncryptOption(jwe.WithContentEncryption(jwa.A128GCM)), 1720 jwt.WithEncryptOption(jwe.WithCompress(jwa.Deflate)), 1721 ). 1722 Serialize(token) 1723 require.NoError(t, err, `jwt.NewSerializer()....Serizlie() should succeed`) 1724 1725 serialized2, err := jwt.NewSerializer(). 1726 Sign(jwt.WithKey(jwa.RS256, signKey)). 1727 Encrypt( 1728 jwt.WithKey(jwa.A128KW, sharedKey), 1729 ). 1730 Serialize(token) 1731 require.NoError(t, err, `jwt.NewSerializer()....Serizlie() should succeed`) 1732 1733 require.NotEqual(t, 1734 len(bytes.Split(serialized, []byte{'.'})[3]), 1735 len(bytes.Split(serialized2, []byte{'.'})[3]), 1736 ) 1737 1738 decrypted, err := jwe.Decrypt(serialized, jwe.WithKey(jwa.A128KW, sharedKey)) 1739 require.NoError(t, err, `jwe.Decrypt should succeed`) 1740 1741 verified, err := jwt.Parse(decrypted, jwt.WithKey(jwa.RS256, signKey.PublicKey)) 1742 require.NoError(t, err, `jwt.Parse should succeed`) 1743 1744 require.True(t, jwt.Equal(verified, token), `tokens should be equal`) 1745 } 1746 1747 func TestGH1007(t *testing.T) { 1748 key, err := jwxtest.GenerateRsaJwk() 1749 require.NoError(t, err, `jwxtest.GenerateRsaJwk should succeed`) 1750 1751 tok, err := jwt.NewBuilder(). 1752 Claim(`claim1`, `value1`). 1753 Claim(`claim2`, `value2`). 1754 Issuer(`github.com/lestrrat-go/jwx`). 1755 Audience([]string{`users`}). 1756 Build() 1757 require.NoError(t, err, `jwt.NewBuilder should succeed`) 1758 1759 signed, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, key)) 1760 require.NoError(t, err, `jwt.Sign should succeed`) 1761 1762 // This was the intended usage (no WithKey). This worked from the beginning 1763 _, err = jwt.ParseInsecure(signed) 1764 require.NoError(t, err, `jwt.ParseInsecure should succeed`) 1765 1766 // This is the problematic behavior reporded in #1007. 1767 // The fact that we're specifying a wrong key caused Parse() to check for 1768 // verification and yet fail :/ 1769 wrongPubKey, err := jwxtest.GenerateRsaPublicJwk() 1770 require.NoError(t, err, `jwxtest.GenerateRsaPublicJwk should succeed`) 1771 require.NoError(t, err, `jwk.PublicKeyOf should succeed`) 1772 1773 _, err = jwt.ParseInsecure(signed, jwt.WithKey(jwa.RS256, wrongPubKey)) 1774 require.NoError(t, err, `jwt.ParseInsecure with jwt.WithKey() should succeed`) 1775 } 1776 1777 func TestParseJSON(t *testing.T) { 1778 // NOTE: jwt.Settings has global effect! 1779 defer jwt.Settings(jwt.WithCompactOnly(false)) 1780 for _, compactOnly := range []bool{true, false} { 1781 t.Run("compactOnly="+strconv.FormatBool(compactOnly), func(t *testing.T) { 1782 jwt.Settings(jwt.WithCompactOnly(compactOnly)) 1783 1784 privKey, err := jwxtest.GenerateRsaJwk() 1785 require.NoError(t, err, `jwxtest.GenerateRsaJwk should succeed`) 1786 1787 signedJSON, err := jws.Sign([]byte(`{}`), jws.WithKey(jwa.RS256, privKey), jws.WithValidateKey(true), jws.WithJSON()) 1788 require.NoError(t, err, `jws.Sign should succeed`) 1789 1790 // jws.Verify should succeed 1791 _, err = jws.Verify(signedJSON, jws.WithKey(jwa.RS256, privKey)) 1792 require.NoError(t, err, `jws.Parse should succeed`) 1793 1794 if compactOnly { 1795 // jwt.Parse should fail 1796 _, err = jwt.Parse(signedJSON, jwt.WithKey(jwa.RS256, privKey)) 1797 require.Error(t, err, `jws.Parse should fail`) 1798 } else { 1799 // for backward compatibility, this should succeed 1800 _, err = jwt.Parse(signedJSON, jwt.WithKey(jwa.RS256, privKey)) 1801 require.NoError(t, err, `jws.Parse should succeed`) 1802 } 1803 }) 1804 } 1805 }