github.com/openshift-online/ocm-sdk-go@v0.1.473/authentication/transport_wrapper_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright (c) 2019 Red Hat, Inc. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 // This file contains tests for the methods that request tokens. 21 22 package authentication 23 24 import ( 25 "context" 26 "encoding/base64" 27 "errors" 28 "fmt" 29 "net/http" 30 "os" 31 "strings" 32 "time" 33 34 "github.com/golang-jwt/jwt/v4" 35 "github.com/google/uuid" 36 37 . "github.com/onsi/ginkgo/v2/dsl/core" // nolint 38 . "github.com/onsi/gomega" // nolint 39 . "github.com/onsi/gomega/ghttp" // nolint 40 . "github.com/openshift-online/ocm-sdk-go/testing" // nolint 41 ) 42 43 var _ = Describe("Tokens", func() { 44 // Context used by the tests: 45 var ctx context.Context 46 47 // Server used during the tests: 48 var server *Server 49 50 // Name of the temporary file containing the CA for the server: 51 var ca string 52 53 BeforeEach(func() { 54 // Create the context: 55 ctx = context.Background() 56 57 // Create the servers: 58 server, ca = MakeTCPTLSServer() 59 }) 60 61 AfterEach(func() { 62 // Stop the servers: 63 server.Close() 64 65 // Remove the temporary CA files: 66 err := os.Remove(ca) 67 Expect(err).ToNot(HaveOccurred()) 68 }) 69 70 It("Can be created tokens that don't have the `typ` claim", func() { 71 // Generate the tokens: 72 accessToken := MakeTokenObject(jwt.MapClaims{ 73 "typ": nil, 74 "exp": time.Now().Add(5 * time.Minute).Unix(), 75 }).Raw 76 refreshToken := MakeTokenObject(jwt.MapClaims{ 77 "typ": nil, 78 "exp": time.Now().Add(10 * time.Hour).Unix(), 79 }).Raw 80 81 // Create the wrapper: 82 wrapper, err := NewTransportWrapper(). 83 Logger(logger). 84 TokenURL(server.URL()). 85 TrustedCA(ca). 86 Tokens(accessToken, refreshToken). 87 Build(ctx) 88 Expect(err).ToNot(HaveOccurred()) 89 defer func() { 90 err = wrapper.Close() 91 Expect(err).ToNot(HaveOccurred()) 92 }() 93 94 // Get the tokens: 95 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 96 Expect(err).ToNot(HaveOccurred()) 97 Expect(returnedAccess).To(Equal(accessToken)) 98 Expect(returnedRefresh).To(Equal(refreshToken)) 99 }) 100 101 Describe("Refresh grant", func() { 102 It("Returns the access token generated by the server", func() { 103 // Generate the tokens: 104 accessToken := MakeTokenString("Bearer", 5*time.Minute) 105 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 106 107 // Configure the server: 108 server.AppendHandlers( 109 CombineHandlers( 110 VerifyRefreshGrant(refreshToken), 111 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 112 ), 113 ) 114 115 // Create the wrapper: 116 wrapper, err := NewTransportWrapper(). 117 Logger(logger). 118 TokenURL(server.URL()). 119 TrustedCA(ca). 120 Tokens(refreshToken). 121 Build(ctx) 122 Expect(err).ToNot(HaveOccurred()) 123 defer func() { 124 err = wrapper.Close() 125 Expect(err).ToNot(HaveOccurred()) 126 }() 127 128 // Get the tokens: 129 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 130 Expect(err).ToNot(HaveOccurred()) 131 Expect(returnedAccess).To(Equal(accessToken)) 132 Expect(returnedRefresh).To(Equal(refreshToken)) 133 }) 134 135 It("Accepts tokens without the `typ` claim", func() { 136 // Generate the tokens: 137 accessToken := MakeTokenObject(jwt.MapClaims{ 138 "typ": nil, 139 "exp": time.Now().Add(5 * time.Minute).Unix(), 140 }).Raw 141 refreshToken := MakeTokenObject(jwt.MapClaims{ 142 "typ": nil, 143 "exp": time.Now().Add(10 * time.Hour).Unix(), 144 }).Raw 145 146 // Configure the server: 147 server.AppendHandlers( 148 CombineHandlers( 149 VerifyRefreshGrant(refreshToken), 150 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 151 ), 152 ) 153 154 // Create the wrapper: 155 wrapper, err := NewTransportWrapper(). 156 Logger(logger). 157 TokenURL(server.URL()). 158 TrustedCA(ca). 159 Tokens(accessToken, refreshToken). 160 Build(ctx) 161 Expect(err).ToNot(HaveOccurred()) 162 defer func() { 163 err = wrapper.Close() 164 Expect(err).ToNot(HaveOccurred()) 165 }() 166 167 // Get the tokens: 168 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(returnedAccess).To(Equal(accessToken)) 171 Expect(returnedRefresh).To(Equal(refreshToken)) 172 }) 173 174 It("Sends the token request the first time only", func() { 175 // Generate the tokens: 176 accessToken := MakeTokenString("Bearer", 5*time.Minute) 177 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 178 179 // Configure the server: 180 server.AppendHandlers( 181 CombineHandlers( 182 VerifyRefreshGrant(refreshToken), 183 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 184 ), 185 ) 186 187 // Create the wrapper: 188 wrapper, err := NewTransportWrapper(). 189 Logger(logger). 190 TokenURL(server.URL()). 191 TrustedCA(ca). 192 Tokens(refreshToken). 193 Build(ctx) 194 Expect(err).ToNot(HaveOccurred()) 195 defer func() { 196 err = wrapper.Close() 197 Expect(err).ToNot(HaveOccurred()) 198 }() 199 200 // Get the tokens the first time: 201 firstAccess, firstRefresh, err := wrapper.Tokens(ctx) 202 Expect(err).ToNot(HaveOccurred()) 203 204 // Get the tones the second time: 205 secondAccess, secondRefresh, err := wrapper.Tokens(ctx) 206 Expect(err).ToNot(HaveOccurred()) 207 Expect(firstAccess).To(Equal(secondAccess)) 208 Expect(firstRefresh).To(Equal(secondRefresh)) 209 }) 210 211 It("Refreshes the access token request if it is expired", func() { 212 // Generate the tokens: 213 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 214 validAccess := MakeTokenString("Bearer", 5*time.Minute) 215 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 216 217 // Configure the server: 218 server.AppendHandlers( 219 CombineHandlers( 220 VerifyRefreshGrant(refreshToken), 221 RespondWithAccessAndRefreshTokens(validAccess, refreshToken), 222 ), 223 ) 224 225 // Create the wrapper: 226 wrapper, err := NewTransportWrapper(). 227 Logger(logger). 228 TokenURL(server.URL()). 229 TrustedCA(ca). 230 Tokens(expiredAccess, refreshToken). 231 Build(ctx) 232 Expect(err).ToNot(HaveOccurred()) 233 defer func() { 234 err = wrapper.Close() 235 Expect(err).ToNot(HaveOccurred()) 236 }() 237 238 // Get the tokens: 239 returnedAccess, _, err := wrapper.Tokens(ctx) 240 Expect(err).ToNot(HaveOccurred()) 241 Expect(returnedAccess).To(Equal(validAccess)) 242 }) 243 244 It("Uses opaque refresh token to refresh expired access token", func() { 245 // Generate the tokens: 246 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 247 validAccess := MakeTokenString("Bearer", 5*time.Minute) 248 refreshToken := "my_refresh_token" 249 250 // Configure the server: 251 server.AppendHandlers( 252 CombineHandlers( 253 VerifyRefreshGrant(refreshToken), 254 RespondWithAccessAndRefreshTokens(validAccess, refreshToken), 255 ), 256 ) 257 258 // Create the wrapper: 259 wrapper, err := NewTransportWrapper(). 260 Logger(logger). 261 TokenURL(server.URL()). 262 TrustedCA(ca). 263 Tokens(expiredAccess, refreshToken). 264 Build(ctx) 265 Expect(err).ToNot(HaveOccurred()) 266 defer func() { 267 err = wrapper.Close() 268 Expect(err).ToNot(HaveOccurred()) 269 }() 270 271 // Get the tokens: 272 returnedAccess, _, err := wrapper.Tokens(ctx) 273 Expect(err).ToNot(HaveOccurred()) 274 Expect(returnedAccess).To(Equal(validAccess)) 275 }) 276 277 It("Refreshes the access token if it expires in less than one minute", func() { 278 // Generate the tokens: 279 firstAccess := MakeTokenString("Bearer", 50*time.Second) 280 secondAccess := MakeTokenString("Bearer", 5*time.Minute) 281 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 282 283 // Configure the server: 284 server.AppendHandlers( 285 CombineHandlers( 286 VerifyRefreshGrant(refreshToken), 287 RespondWithAccessAndRefreshTokens(secondAccess, refreshToken), 288 ), 289 ) 290 291 // Create the wrapper: 292 wrapper, err := NewTransportWrapper(). 293 Logger(logger). 294 TokenURL(server.URL()). 295 TrustedCA(ca). 296 Tokens(firstAccess, refreshToken). 297 Build(ctx) 298 Expect(err).ToNot(HaveOccurred()) 299 defer func() { 300 err = wrapper.Close() 301 Expect(err).ToNot(HaveOccurred()) 302 }() 303 304 // Get the tokens: 305 returnedAccess, _, err := wrapper.Tokens(ctx) 306 Expect(err).ToNot(HaveOccurred()) 307 Expect(returnedAccess).To(Equal(secondAccess)) 308 }) 309 310 It("Refreshes the access token if it expires in less than specified expiry period", func() { 311 // Ask for a token valid for at least 10 minutes 312 expiresIn := 10 * time.Minute 313 314 // Generate the tokens: 315 firstAccess := MakeTokenString("Bearer", 9*time.Minute) 316 secondAccess := MakeTokenString("Bearer", 20*time.Minute) 317 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 318 319 // Configure the server: 320 server.AppendHandlers( 321 CombineHandlers( 322 VerifyRefreshGrant(refreshToken), 323 RespondWithAccessAndRefreshTokens(secondAccess, refreshToken), 324 ), 325 ) 326 327 // Create the wrapper: 328 wrapper, err := NewTransportWrapper(). 329 Logger(logger). 330 TokenURL(server.URL()). 331 TrustedCA(ca). 332 Tokens(firstAccess, refreshToken). 333 Build(ctx) 334 Expect(err).ToNot(HaveOccurred()) 335 defer func() { 336 err = wrapper.Close() 337 Expect(err).ToNot(HaveOccurred()) 338 }() 339 340 // Get the tokens: 341 returnedAccess, _, err := wrapper.Tokens(ctx, expiresIn) 342 Expect(err).ToNot(HaveOccurred()) 343 Expect(returnedAccess).To(Equal(secondAccess)) 344 }) 345 346 It("Fails if the access token is expired and there is no refresh token", func() { 347 // Generate the tokens: 348 accessToken := MakeTokenString("Bearer", -5*time.Second) 349 350 // Create the wrapper: 351 wrapper, err := NewTransportWrapper(). 352 Logger(logger). 353 TokenURL(server.URL()). 354 TrustedCA(ca). 355 Tokens(accessToken). 356 Build(ctx) 357 Expect(err).ToNot(HaveOccurred()) 358 defer func() { 359 err = wrapper.Close() 360 Expect(err).ToNot(HaveOccurred()) 361 }() 362 363 // Get the tokens: 364 _, _, err = wrapper.Tokens(ctx) 365 Expect(err).To(HaveOccurred()) 366 }) 367 368 It("Succeeds if access token expires soon and there is no refresh token", func() { 369 // Generate the tokens: 370 accessToken := MakeTokenString("Bearer", 10*time.Second) 371 372 // Create the wrapper: 373 wrapper, err := NewTransportWrapper(). 374 Logger(logger). 375 TokenURL(server.URL()). 376 TrustedCA(ca). 377 Tokens(accessToken). 378 Build(ctx) 379 Expect(err).ToNot(HaveOccurred()) 380 defer func() { 381 err = wrapper.Close() 382 Expect(err).ToNot(HaveOccurred()) 383 }() 384 385 // Get the tokens: 386 _, _, err = wrapper.Tokens(ctx) 387 Expect(err).ToNot(HaveOccurred()) 388 }) 389 390 It("Fails if the refresh token is expired", func() { 391 // Generate the tokens: 392 refreshToken := MakeTokenString("Refresh", -5*time.Second) 393 394 // Create the wrapper: 395 wrapper, err := NewTransportWrapper(). 396 Logger(logger). 397 TokenURL(server.URL()). 398 TrustedCA(ca). 399 Tokens(refreshToken). 400 Build(ctx) 401 Expect(err).ToNot(HaveOccurred()) 402 defer func() { 403 err = wrapper.Close() 404 Expect(err).ToNot(HaveOccurred()) 405 }() 406 407 // Get the tokens: 408 _, _, err = wrapper.Tokens(ctx) 409 Expect(err).To(HaveOccurred()) 410 }) 411 412 When("The server doesn't return JSON content type", func() { 413 It("Adds complete content to error message if it is short", func() { 414 // Generate the refresh token: 415 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 416 417 // Configure the server: 418 for i := 0; i < 100; i++ { // there are going to be several retries 419 server.AppendHandlers( 420 RespondWith( 421 http.StatusServiceUnavailable, 422 `Service unavailable`, 423 http.Header{ 424 "Content-Type": []string{ 425 "text/plain", 426 }, 427 }, 428 ), 429 ) 430 } 431 432 // Create the wrapper: 433 wrapper, err := NewTransportWrapper(). 434 Logger(logger). 435 TokenURL(server.URL()). 436 TrustedCA(ca). 437 Tokens(refreshToken). 438 Build(ctx) 439 Expect(err).ToNot(HaveOccurred()) 440 defer func() { 441 err = wrapper.Close() 442 Expect(err).ToNot(HaveOccurred()) 443 }() 444 445 // Try to get the access token: 446 ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 447 defer cancel() 448 _, _, err = wrapper.Tokens(ctx) 449 Expect(err).To(HaveOccurred()) 450 message := err.Error() 451 Expect(message).To(ContainSubstring("text/plain")) 452 Expect(message).To(ContainSubstring("Service unavailable")) 453 }) 454 455 It("Adds summary of content if it is too long", func() { 456 // Generate the refresh token: 457 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 458 459 // Calculate a long message: 460 content := fmt.Sprintf("Ver%s long", strings.Repeat("y", 1000)) 461 462 // Configure the server: 463 server.AppendHandlers( 464 RespondWith( 465 http.StatusBadRequest, 466 content, 467 http.Header{ 468 "Content-Type": []string{ 469 "text/plain", 470 }, 471 }, 472 ), 473 ) 474 475 // Create the wrapper: 476 wrapper, err := NewTransportWrapper(). 477 Logger(logger). 478 TokenURL(server.URL()). 479 TrustedCA(ca). 480 Tokens(refreshToken). 481 Build(ctx) 482 Expect(err).ToNot(HaveOccurred()) 483 defer func() { 484 err = wrapper.Close() 485 Expect(err).ToNot(HaveOccurred()) 486 }() 487 488 // Try to get the access token: 489 _, _, err = wrapper.Tokens(ctx) 490 Expect(err).To(HaveOccurred()) 491 message := err.Error() 492 Expect(message).To(ContainSubstring("text/plain")) 493 Expect(message).To(ContainSubstring("Veryyyyyy")) 494 Expect(message).To(ContainSubstring("...")) 495 }) 496 }) 497 498 It("Honors cookies", func() { 499 // Generate the tokens: 500 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 501 validAccess := MakeTokenString("Bearer", 5*time.Minute) 502 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 503 504 // Configure the server: 505 server.AppendHandlers( 506 CombineHandlers( 507 RespondWithCookie("mycookie", "myvalue"), 508 RespondWithAccessAndRefreshTokens(expiredAccess, refreshToken), 509 ), 510 CombineHandlers( 511 VerifyCookie("mycookie", "myvalue"), 512 RespondWithAccessAndRefreshTokens(validAccess, refreshToken), 513 ), 514 ) 515 516 // Create the wrapper: 517 wrapper, err := NewTransportWrapper(). 518 Logger(logger). 519 TokenURL(server.URL()). 520 TrustedCA(ca). 521 Tokens(expiredAccess, refreshToken). 522 Build(ctx) 523 Expect(err).ToNot(HaveOccurred()) 524 defer func() { 525 err = wrapper.Close() 526 Expect(err).ToNot(HaveOccurred()) 527 }() 528 529 // Request the tokens the first time. This will return an expired access 530 // token and a valid refresh token. 531 _, _, err = wrapper.Tokens(ctx) 532 Expect(err).ToNot(HaveOccurred()) 533 534 // Request the tokens a second time, therefore forcing a refresh grant which 535 // should honor the cookies returned in the first attempt: 536 _, _, err = wrapper.Tokens(ctx) 537 Expect(err).ToNot(HaveOccurred()) 538 }) 539 }) 540 541 Describe("Password grant", func() { 542 It("Returns the access and refresh tokens generated by the server", func() { 543 // Generate the tokens: 544 accessToken := MakeTokenString("Bearer", 5*time.Minute) 545 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 546 547 // Configure the server: 548 server.AppendHandlers( 549 CombineHandlers( 550 VerifyPasswordGrant("myuser", "mypassword"), 551 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 552 ), 553 ) 554 555 // Create the wrapper: 556 wrapper, err := NewTransportWrapper(). 557 Logger(logger). 558 TokenURL(server.URL()). 559 TrustedCA(ca). 560 User("myuser", "mypassword"). 561 Build(ctx) 562 Expect(err).ToNot(HaveOccurred()) 563 defer func() { 564 err = wrapper.Close() 565 Expect(err).ToNot(HaveOccurred()) 566 }() 567 568 // Get the tokens: 569 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 570 Expect(err).ToNot(HaveOccurred()) 571 Expect(returnedAccess).To(Equal(accessToken)) 572 Expect(returnedRefresh).To(Equal(refreshToken)) 573 }) 574 575 It("Accepts tokens without the `typ` claim", func() { 576 // Generate the tokens: 577 accessToken := MakeTokenObject(jwt.MapClaims{ 578 "typ": nil, 579 "exp": time.Now().Add(5 * time.Minute).Unix(), 580 }).Raw 581 refreshToken := MakeTokenObject(jwt.MapClaims{ 582 "typ": nil, 583 "exp": time.Now().Add(10 * time.Hour).Unix(), 584 }).Raw 585 586 // Configure the server: 587 server.AppendHandlers( 588 CombineHandlers( 589 VerifyPasswordGrant("myuser", "mypassword"), 590 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 591 ), 592 ) 593 594 // Create the wrapper: 595 wrapper, err := NewTransportWrapper(). 596 Logger(logger). 597 TokenURL(server.URL()). 598 TrustedCA(ca). 599 User("myuser", "mypassword"). 600 Build(ctx) 601 Expect(err).ToNot(HaveOccurred()) 602 defer func() { 603 err = wrapper.Close() 604 Expect(err).ToNot(HaveOccurred()) 605 }() 606 607 // Get the tokens: 608 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 609 Expect(err).ToNot(HaveOccurred()) 610 Expect(returnedAccess).To(Equal(accessToken)) 611 Expect(returnedRefresh).To(Equal(refreshToken)) 612 }) 613 614 It("Refreshes access token", func() { 615 // Generate the tokens: 616 expiredAccess := MakeTokenString("Bearer", -5*time.Second) 617 validAccess := MakeTokenString("Bearer", 5*time.Minute) 618 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 619 620 // Configure the server: 621 server.AppendHandlers( 622 CombineHandlers( 623 VerifyPasswordGrant("myuser", "mypassword"), 624 RespondWithAccessAndRefreshTokens(expiredAccess, refreshToken), 625 ), 626 CombineHandlers( 627 VerifyRefreshGrant(refreshToken), 628 RespondWithAccessAndRefreshTokens(validAccess, refreshToken), 629 ), 630 ) 631 632 // Create the wrapper: 633 wrapper, err := NewTransportWrapper(). 634 Logger(logger). 635 TokenURL(server.URL()). 636 TrustedCA(ca). 637 User("myuser", "mypassword"). 638 Build(ctx) 639 Expect(err).ToNot(HaveOccurred()) 640 defer func() { 641 err = wrapper.Close() 642 Expect(err).ToNot(HaveOccurred()) 643 }() 644 645 // Get the tokens the first time: 646 firstAccess, _, err := wrapper.Tokens(ctx) 647 Expect(err).ToNot(HaveOccurred()) 648 Expect(firstAccess).To(Equal(expiredAccess)) 649 650 // Get the tokens the second time: 651 secondAccess, _, err := wrapper.Tokens(ctx) 652 Expect(err).ToNot(HaveOccurred()) 653 Expect(secondAccess).To(Equal(validAccess)) 654 }) 655 656 It("Requests a new refresh token when it expires", func() { 657 // Generate the tokens: 658 expiredAccess := MakeTokenString("Bearer", -5*time.Second) 659 expiredRefresh := MakeTokenString("Refresh", -15*time.Second) 660 validAccess := MakeTokenString("Bearer", 5*time.Minute) 661 validRefresh := MakeTokenString("Refresh", 10*time.Hour) 662 663 // Configure the server: 664 server.AppendHandlers( 665 CombineHandlers( 666 VerifyPasswordGrant("myuser", "mypassword"), 667 RespondWithAccessAndRefreshTokens(expiredAccess, expiredRefresh), 668 ), 669 CombineHandlers( 670 VerifyPasswordGrant("myuser", "mypassword"), 671 RespondWithAccessAndRefreshTokens(validAccess, validRefresh), 672 ), 673 ) 674 675 // Create the wrapper: 676 wrapper, err := NewTransportWrapper(). 677 Logger(logger). 678 TokenURL(server.URL()). 679 TrustedCA(ca). 680 User("myuser", "mypassword"). 681 Build(ctx) 682 Expect(err).ToNot(HaveOccurred()) 683 defer func() { 684 err = wrapper.Close() 685 Expect(err).ToNot(HaveOccurred()) 686 }() 687 688 // Get the tokens the first time: 689 _, firstRefresh, err := wrapper.Tokens(ctx) 690 Expect(err).ToNot(HaveOccurred()) 691 Expect(firstRefresh).To(Equal(expiredRefresh)) 692 693 // Get the tokens the second time: 694 _, secondRefresh, err := wrapper.Tokens(ctx) 695 Expect(err).ToNot(HaveOccurred()) 696 Expect(secondRefresh).To(Equal(validRefresh)) 697 }) 698 699 It("Requests a new refresh token when expires in less than ten seconds", func() { 700 // Generate the tokens: 701 expiredAccess := MakeTokenString("Bearer", -5*time.Second) 702 expiredRefresh := MakeTokenString("Refresh", 5*time.Second) 703 validAccess := MakeTokenString("Bearer", 5*time.Minute) 704 validRefresh := MakeTokenString("Refresh", 10*time.Hour) 705 706 // Configure the server: 707 server.AppendHandlers( 708 CombineHandlers( 709 VerifyPasswordGrant("myuser", "mypassword"), 710 RespondWithAccessAndRefreshTokens(expiredAccess, expiredRefresh), 711 ), 712 CombineHandlers( 713 VerifyPasswordGrant("myuser", "mypassword"), 714 RespondWithAccessAndRefreshTokens(validAccess, validRefresh), 715 ), 716 ) 717 718 // Create the wrapper: 719 wrapper, err := NewTransportWrapper(). 720 Logger(logger). 721 TokenURL(server.URL()). 722 TrustedCA(ca). 723 User("myuser", "mypassword"). 724 Build(ctx) 725 Expect(err).ToNot(HaveOccurred()) 726 defer func() { 727 err = wrapper.Close() 728 Expect(err).ToNot(HaveOccurred()) 729 }() 730 731 // Get the tokens the first time: 732 _, firstRefresh, err := wrapper.Tokens(ctx) 733 Expect(err).ToNot(HaveOccurred()) 734 Expect(firstRefresh).To(Equal(expiredRefresh)) 735 736 // Get the tokens the second time: 737 _, secondRefresh, err := wrapper.Tokens(ctx) 738 Expect(err).ToNot(HaveOccurred()) 739 Expect(secondRefresh).To(Equal(validRefresh)) 740 }) 741 742 It("Fails with wrong user name", func() { 743 // Configure the server: 744 server.AppendHandlers( 745 CombineHandlers( 746 VerifyPasswordGrant("baduser", "mypassword"), 747 RespondWithTokenError("bad_user", "Bad user"), 748 ), 749 ) 750 751 // Create the wrapper: 752 wrapper, err := NewTransportWrapper(). 753 Logger(logger). 754 TokenURL(server.URL()). 755 TrustedCA(ca). 756 User("baduser", "mypassword"). 757 Build(ctx) 758 Expect(err).ToNot(HaveOccurred()) 759 defer func() { 760 err = wrapper.Close() 761 Expect(err).ToNot(HaveOccurred()) 762 }() 763 764 // Get the tokens: 765 _, _, err = wrapper.Tokens(ctx) 766 Expect(err).To(HaveOccurred()) 767 }) 768 769 It("Fails with wrong password", func() { 770 // Configure the server: 771 server.AppendHandlers( 772 CombineHandlers( 773 VerifyPasswordGrant("myuser", "badpassword"), 774 RespondWithTokenError("bad_password", "Bad password"), 775 ), 776 ) 777 778 // Create the wrapper: 779 wrapper, err := NewTransportWrapper(). 780 Logger(logger). 781 TokenURL(server.URL()). 782 TrustedCA(ca). 783 User("myuser", "badpassword"). 784 Build(ctx) 785 Expect(err).ToNot(HaveOccurred()) 786 defer func() { 787 err = wrapper.Close() 788 Expect(err).ToNot(HaveOccurred()) 789 }() 790 791 // Get the tokens: 792 _, _, err = wrapper.Tokens(ctx) 793 Expect(err).To(HaveOccurred()) 794 }) 795 796 It("Honors cookies", func() { 797 // Generate the tokens: 798 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 799 validAccess := MakeTokenString("Bearer", 5*time.Minute) 800 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 801 802 // Configure the server: 803 server.AppendHandlers( 804 CombineHandlers( 805 RespondWithCookie("mycookie", "myvalue"), 806 RespondWithAccessAndRefreshTokens(expiredAccess, refreshToken), 807 ), 808 CombineHandlers( 809 VerifyCookie("mycookie", "myvalue"), 810 RespondWithAccessAndRefreshTokens(validAccess, refreshToken), 811 ), 812 ) 813 814 // Create the wrapper: 815 wrapper, err := NewTransportWrapper(). 816 Logger(logger). 817 TokenURL(server.URL()). 818 TrustedCA(ca). 819 User("myuser", "mypassword"). 820 Build(ctx) 821 Expect(err).ToNot(HaveOccurred()) 822 defer func() { 823 err = wrapper.Close() 824 Expect(err).ToNot(HaveOccurred()) 825 }() 826 827 // Request the tokens the first time. This will return an expired access 828 // token and a valid refresh token. 829 _, _, err = wrapper.Tokens(ctx) 830 Expect(err).ToNot(HaveOccurred()) 831 832 // Request the tokens a second time, therefore forcing a refresh grant which 833 // should honor the cookies returned in the first attempt: 834 _, _, err = wrapper.Tokens(ctx) 835 Expect(err).ToNot(HaveOccurred()) 836 }) 837 838 It("Works if no refresh token is returned", func() { 839 // Generate the tokens: 840 accessToken := MakeTokenString("Bearer", 5*time.Minute) 841 842 // Configure the server: 843 server.AppendHandlers( 844 CombineHandlers( 845 VerifyPasswordGrant("myuser", "mypassword"), 846 RespondWithAccessToken(accessToken), 847 ), 848 ) 849 850 // Create the wrapper: 851 wrapper, err := NewTransportWrapper(). 852 Logger(logger). 853 TokenURL(server.URL()). 854 TrustedCA(ca). 855 User("myuser", "mypassword"). 856 Build(ctx) 857 Expect(err).ToNot(HaveOccurred()) 858 defer func() { 859 err = wrapper.Close() 860 Expect(err).ToNot(HaveOccurred()) 861 }() 862 863 // Get the tokens: 864 returnedAccess, _, err := wrapper.Tokens(ctx) 865 Expect(err).ToNot(HaveOccurred()) 866 Expect(returnedAccess).To(Equal(accessToken)) 867 }) 868 869 It("Accepts lower case token type", func() { 870 // Generate the tokens: 871 accessToken := MakeTokenString("bearer", 5*time.Minute) 872 873 // Configure the server: 874 server.AppendHandlers( 875 CombineHandlers( 876 VerifyPasswordGrant("myuser", "mypassword"), 877 RespondWithAccessToken(accessToken), 878 ), 879 ) 880 881 // Create the wrapper: 882 wrapper, err := NewTransportWrapper(). 883 Logger(logger). 884 TokenURL(server.URL()). 885 TrustedCA(ca). 886 User("myuser", "mypassword"). 887 Build(ctx) 888 Expect(err).ToNot(HaveOccurred()) 889 defer func() { 890 err = wrapper.Close() 891 Expect(err).ToNot(HaveOccurred()) 892 }() 893 894 // Get the tokens: 895 returnedAccess, _, err := wrapper.Tokens(ctx) 896 Expect(err).ToNot(HaveOccurred()) 897 Expect(returnedAccess).To(Equal(accessToken)) 898 }) 899 900 It("Accepts opaque refresh token", func() { 901 // Generate the tokens: 902 accessToken := MakeTokenString("bearer", 5*time.Minute) 903 refreshToken := "my_refresh_token" 904 905 // Configure the server: 906 server.AppendHandlers( 907 CombineHandlers( 908 VerifyPasswordGrant("myuser", "mypassword"), 909 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 910 ), 911 ) 912 913 // Create the wrapper: 914 wrapper, err := NewTransportWrapper(). 915 Logger(logger). 916 TokenURL(server.URL()). 917 TrustedCA(ca). 918 User("myuser", "mypassword"). 919 Build(ctx) 920 Expect(err).ToNot(HaveOccurred()) 921 defer func() { 922 err = wrapper.Close() 923 Expect(err).ToNot(HaveOccurred()) 924 }() 925 926 // Get the tokens: 927 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 928 Expect(err).ToNot(HaveOccurred()) 929 Expect(returnedAccess).To(Equal(accessToken)) 930 Expect(returnedRefresh).To(Equal(refreshToken)) 931 }) 932 }) 933 934 When("Only the access token is provided", func() { 935 It("Returns the access token if it hasn't expired", func() { 936 // Generate the token: 937 accessToken := MakeTokenString("Bearer", 5*time.Minute) 938 939 // Create the wrapper: 940 wrapper, err := NewTransportWrapper(). 941 Logger(logger). 942 TokenURL(server.URL()). 943 TrustedCA(ca). 944 Tokens(accessToken). 945 Build(ctx) 946 Expect(err).ToNot(HaveOccurred()) 947 defer func() { 948 err = wrapper.Close() 949 Expect(err).ToNot(HaveOccurred()) 950 }() 951 952 // Get the tokens: 953 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 954 Expect(err).ToNot(HaveOccurred()) 955 Expect(returnedAccess).To(Equal(accessToken)) 956 Expect(returnedRefresh).To(BeEmpty()) 957 }) 958 959 It("Returns an error if the access token has expired", func() { 960 // Generate the token: 961 accessToken := MakeTokenString("Bearer", -5*time.Minute) 962 963 // Create the wrapper: 964 wrapper, err := NewTransportWrapper(). 965 Logger(logger). 966 TokenURL(server.URL()). 967 TrustedCA(ca). 968 Tokens(accessToken). 969 Build(ctx) 970 Expect(err).ToNot(HaveOccurred()) 971 defer func() { 972 err = wrapper.Close() 973 Expect(err).ToNot(HaveOccurred()) 974 }() 975 976 // Get the tokens: 977 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 978 Expect(err).To(HaveOccurred()) 979 Expect(returnedAccess).To(BeEmpty()) 980 Expect(returnedRefresh).To(BeEmpty()) 981 }) 982 }) 983 984 Describe("Client credentials grant", func() { 985 It("Returns the access token generated by the server", func() { 986 // Generate the tokens: 987 accessToken := MakeTokenString("Bearer", 5*time.Minute) 988 989 // Configure the server: 990 server.AppendHandlers( 991 CombineHandlers( 992 VerifyClientCredentialsGrant("myclient", "mysecret"), 993 RespondWithAccessToken(accessToken), 994 ), 995 ) 996 997 // Create the wrapper: 998 wrapper, err := NewTransportWrapper(). 999 Logger(logger). 1000 TokenURL(server.URL()). 1001 TrustedCA(ca). 1002 Client("myclient", "mysecret"). 1003 Build(ctx) 1004 Expect(err).ToNot(HaveOccurred()) 1005 defer func() { 1006 err = wrapper.Close() 1007 Expect(err).ToNot(HaveOccurred()) 1008 }() 1009 1010 // Get the token: 1011 returnedAccess, _, err := wrapper.Tokens(ctx) 1012 Expect(err).ToNot(HaveOccurred()) 1013 Expect(returnedAccess).To(Equal(accessToken)) 1014 }) 1015 1016 It("Accepts token without the `typ` claim", func() { 1017 // Generate the tokens: 1018 accessToken := MakeTokenObject(jwt.MapClaims{ 1019 "typ": nil, 1020 "exp": time.Now().Add(5 * time.Minute).Unix(), 1021 }).Raw 1022 1023 // Configure the server: 1024 server.AppendHandlers( 1025 CombineHandlers( 1026 VerifyClientCredentialsGrant("myclient", "mysecret"), 1027 RespondWithAccessToken(accessToken), 1028 ), 1029 ) 1030 1031 // Create the wrapper: 1032 wrapper, err := NewTransportWrapper(). 1033 Logger(logger). 1034 TokenURL(server.URL()). 1035 TrustedCA(ca). 1036 Client("myclient", "mysecret"). 1037 Build(ctx) 1038 Expect(err).ToNot(HaveOccurred()) 1039 defer func() { 1040 err = wrapper.Close() 1041 Expect(err).ToNot(HaveOccurred()) 1042 }() 1043 1044 // Get the tokens: 1045 returnedAccess, _, err := wrapper.Tokens(ctx) 1046 Expect(err).ToNot(HaveOccurred()) 1047 Expect(returnedAccess).To(Equal(accessToken)) 1048 }) 1049 1050 It("Refreshes access token", func() { 1051 // Generate the tokens: 1052 expiredAccess := MakeTokenString("Bearer", -5*time.Second) 1053 validAccess := MakeTokenString("Bearer", 5*time.Minute) 1054 1055 // Configure the server: 1056 server.AppendHandlers( 1057 CombineHandlers( 1058 VerifyClientCredentialsGrant("myclient", "mysecret"), 1059 RespondWithAccessToken(validAccess), 1060 ), 1061 ) 1062 1063 // Create the wrapper: 1064 wrapper, err := NewTransportWrapper(). 1065 Logger(logger). 1066 TokenURL(server.URL()). 1067 TrustedCA(ca). 1068 Client("myclient", "mysecret"). 1069 Tokens(expiredAccess). 1070 Build(ctx) 1071 Expect(err).ToNot(HaveOccurred()) 1072 defer func() { 1073 err = wrapper.Close() 1074 Expect(err).ToNot(HaveOccurred()) 1075 }() 1076 1077 // Get the token: 1078 returnedAccess, _, err := wrapper.Tokens(ctx) 1079 Expect(err).ToNot(HaveOccurred()) 1080 Expect(returnedAccess).To(Equal(validAccess)) 1081 }) 1082 1083 It("Fails with wrong client identifier", func() { 1084 // Configure the server: 1085 server.AppendHandlers( 1086 CombineHandlers( 1087 VerifyClientCredentialsGrant("badclient", "mysecret"), 1088 RespondWithTokenError("invalid_grant", "Bad client"), 1089 ), 1090 ) 1091 1092 // Create the wrapper: 1093 wrapper, err := NewTransportWrapper(). 1094 Logger(logger). 1095 TokenURL(server.URL()). 1096 TrustedCA(ca). 1097 Client("badclient", "mysecret"). 1098 Build(ctx) 1099 Expect(err).ToNot(HaveOccurred()) 1100 defer func() { 1101 err = wrapper.Close() 1102 Expect(err).ToNot(HaveOccurred()) 1103 }() 1104 1105 // Get the tokens: 1106 _, _, err = wrapper.Tokens(ctx) 1107 Expect(err).To(HaveOccurred()) 1108 }) 1109 1110 It("Fails with wrong client secret", func() { 1111 // Configure the server: 1112 server.AppendHandlers( 1113 CombineHandlers( 1114 VerifyClientCredentialsGrant("myclient", "badsecret"), 1115 RespondWithTokenError("invalid_grant", "Bad secret"), 1116 ), 1117 ) 1118 1119 // Create the wrapper: 1120 wrapper, err := NewTransportWrapper(). 1121 Logger(logger). 1122 TokenURL(server.URL()). 1123 TrustedCA(ca). 1124 Client("myclient", "badsecret"). 1125 Build(ctx) 1126 Expect(err).ToNot(HaveOccurred()) 1127 defer func() { 1128 err = wrapper.Close() 1129 Expect(err).ToNot(HaveOccurred()) 1130 }() 1131 1132 // Get the tokens: 1133 _, _, err = wrapper.Tokens(ctx) 1134 Expect(err).To(HaveOccurred()) 1135 }) 1136 1137 It("Honours cookies", func() { 1138 // Generate the tokens: 1139 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 1140 validAccess := MakeTokenString("Bearer", 5*time.Minute) 1141 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1142 1143 // Configure the server: 1144 server.AppendHandlers( 1145 CombineHandlers( 1146 RespondWithCookie("mycookie", "myvalue"), 1147 RespondWithAccessAndRefreshTokens(expiredAccess, refreshToken), 1148 ), 1149 CombineHandlers( 1150 VerifyCookie("mycookie", "myvalue"), 1151 RespondWithAccessAndRefreshTokens(validAccess, refreshToken), 1152 ), 1153 ) 1154 1155 // Create the wrapper: 1156 wrapper, err := NewTransportWrapper(). 1157 Logger(logger). 1158 TokenURL(server.URL()). 1159 TrustedCA(ca). 1160 Client("myclient", "mysecret"). 1161 Build(ctx) 1162 Expect(err).ToNot(HaveOccurred()) 1163 defer func() { 1164 err = wrapper.Close() 1165 Expect(err).ToNot(HaveOccurred()) 1166 }() 1167 1168 // Request the tokens the first time. This will return an expired access 1169 // token and a valid refresh token. 1170 _, _, err = wrapper.Tokens(ctx) 1171 Expect(err).ToNot(HaveOccurred()) 1172 1173 // Request the tokens a second time, therefore forcing a refresh grant which 1174 // should honor the cookies returned in the first attempt: 1175 _, _, err = wrapper.Tokens(ctx) 1176 Expect(err).ToNot(HaveOccurred()) 1177 }) 1178 1179 It("Doesn't fail if the server returns a refresh token", func() { 1180 // Generate the tokens: 1181 accessToken := MakeTokenString("Bearer", 5*time.Minute) 1182 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1183 1184 // Configure the server: 1185 server.AppendHandlers( 1186 CombineHandlers( 1187 VerifyClientCredentialsGrant("myclient", "mysecret"), 1188 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 1189 ), 1190 ) 1191 1192 // Create the wrapper: 1193 wrapper, err := NewTransportWrapper(). 1194 Logger(logger). 1195 TokenURL(server.URL()). 1196 TrustedCA(ca). 1197 Client("myclient", "mysecret"). 1198 Build(ctx) 1199 Expect(err).ToNot(HaveOccurred()) 1200 defer func() { 1201 err = wrapper.Close() 1202 Expect(err).ToNot(HaveOccurred()) 1203 }() 1204 1205 // Get the token: 1206 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 1207 Expect(err).ToNot(HaveOccurred()) 1208 Expect(returnedAccess).To(Equal(accessToken)) 1209 Expect(returnedRefresh).To(Equal(refreshToken)) 1210 }) 1211 1212 It("Uses client credentials grant even if it has refresh token", func() { 1213 // Generate the tokens: 1214 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 1215 validAccess := MakeTokenString("Bearer", 5*time.Minute) 1216 validRefresh := MakeTokenString("Refresh", 10*time.Hour) 1217 1218 // Configure the server so that it returns a expired access token and a 1219 // valid refresh token for the first request, and then a valid access token 1220 // for the second request. In both cases the client should be using the 1221 // client credentials grant. 1222 server.AppendHandlers( 1223 CombineHandlers( 1224 VerifyClientCredentialsGrant("myclient", "mysecret"), 1225 RespondWithAccessAndRefreshTokens(expiredAccess, validRefresh), 1226 ), 1227 CombineHandlers( 1228 VerifyClientCredentialsGrant("myclient", "mysecret"), 1229 RespondWithAccessAndRefreshTokens(validAccess, validRefresh), 1230 ), 1231 ) 1232 1233 // Create the wrapper: 1234 wrapper, err := NewTransportWrapper(). 1235 Logger(logger). 1236 TokenURL(server.URL()). 1237 TrustedCA(ca). 1238 Client("myclient", "mysecret"). 1239 Tokens(expiredAccess, validRefresh). 1240 Build(ctx) 1241 Expect(err).ToNot(HaveOccurred()) 1242 defer func() { 1243 err = wrapper.Close() 1244 Expect(err).ToNot(HaveOccurred()) 1245 }() 1246 1247 // Force the initial token request. This will return an expired access token 1248 // and a valid refresh token, that way when we get the tokens again the 1249 // wrapper should send another request, but using the client credentials 1250 // grant and ignoring the refresh token. 1251 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 1252 Expect(err).ToNot(HaveOccurred()) 1253 Expect(returnedAccess).To(Equal(expiredAccess)) 1254 Expect(returnedRefresh).To(Equal(validRefresh)) 1255 1256 // Force another request: 1257 returnedAccess, returnedRefresh, err = wrapper.Tokens(ctx) 1258 Expect(err).ToNot(HaveOccurred()) 1259 Expect(returnedAccess).To(Equal(validAccess)) 1260 Expect(returnedRefresh).To(Equal(validRefresh)) 1261 }) 1262 1263 It("Uses client credentials grant with basic authentication and opaque refresh token", func() { 1264 // Generate the tokens: 1265 expiredAccess := MakeTokenString("Bearer", -5*time.Minute) 1266 validAccess := MakeTokenString("Bearer", 5*time.Minute) 1267 opaqueRefresh := "a.bb.ccc.dddd.eeeee" 1268 1269 // Configure the server so that it returns a expired access token for the 1270 // first request, and then a valid access token for the second request. In 1271 // both cases the client should be using the client credentials grant with 1272 // basic authentication. 1273 server.AppendHandlers( 1274 CombineHandlers( 1275 VerifyClientCredentialsGrant("myclient", "mysecret"), 1276 RespondWithAccessToken(expiredAccess), 1277 ), 1278 CombineHandlers( 1279 VerifyClientCredentialsGrant("myclient", "mysecret"), 1280 RespondWithAccessToken(validAccess), 1281 ), 1282 ) 1283 1284 // Create the wrapper: 1285 wrapper, err := NewTransportWrapper(). 1286 Logger(logger). 1287 TokenURL(server.URL()). 1288 TrustedCA(ca). 1289 Client("myclient", "mysecret"). 1290 Tokens(expiredAccess, opaqueRefresh). 1291 Build(ctx) 1292 Expect(err).ToNot(HaveOccurred()) 1293 defer func() { 1294 err = wrapper.Close() 1295 Expect(err).ToNot(HaveOccurred()) 1296 }() 1297 1298 // Force the initial token request. This will return an expired access token 1299 // and a valid refresh token, that way when we get the tokens again the 1300 // wrapper should send another request, but using the client credentials 1301 // grant and ignoring the refresh token. 1302 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 1303 Expect(err).ToNot(HaveOccurred()) 1304 Expect(returnedAccess).To(Equal(expiredAccess)) 1305 Expect(returnedRefresh).To(Equal(opaqueRefresh)) 1306 1307 // Force another request: 1308 returnedAccess, returnedRefresh, err = wrapper.Tokens(ctx) 1309 Expect(err).ToNot(HaveOccurred()) 1310 Expect(returnedAccess).To(Equal(validAccess)) 1311 Expect(returnedRefresh).To(Equal(opaqueRefresh)) 1312 }) 1313 }) 1314 1315 Describe("Retry for getting access token", func() { 1316 It("Return access token after a few retries", func() { 1317 // Generate tokens: 1318 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1319 accessToken := MakeTokenString("Bearer", 5*time.Minute) 1320 1321 server.AppendHandlers( 1322 RespondWithContent( 1323 http.StatusInternalServerError, 1324 "text/plain", 1325 "Internal Server Error", 1326 ), 1327 RespondWithContent( 1328 http.StatusBadGateway, 1329 "text/plain", 1330 "Bad Gateway", 1331 ), 1332 CombineHandlers( 1333 VerifyRefreshGrant(refreshToken), 1334 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 1335 ), 1336 ) 1337 1338 // Create the wrapper: 1339 wrapper, err := NewTransportWrapper(). 1340 Logger(logger). 1341 TokenURL(server.URL()). 1342 TrustedCA(ca). 1343 Tokens(refreshToken). 1344 Build(ctx) 1345 Expect(err).ToNot(HaveOccurred()) 1346 defer func() { 1347 err = wrapper.Close() 1348 Expect(err).ToNot(HaveOccurred()) 1349 }() 1350 1351 // Get the tokens: 1352 returnedAccess, returnedRefresh, err := wrapper.Tokens(ctx) 1353 Expect(err).ToNot(HaveOccurred()) 1354 Expect(returnedAccess).ToNot(BeEmpty()) 1355 Expect(returnedRefresh).ToNot(BeEmpty()) 1356 }) 1357 1358 It("Test no retry when status is not http 5xx", func() { 1359 // Generate tokens: 1360 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1361 accessToken := MakeTokenString("Bearer", 5*time.Minute) 1362 1363 server.AppendHandlers( 1364 RespondWithContent( 1365 http.StatusInternalServerError, 1366 "text/plain", 1367 "Internal Server Error", 1368 ), 1369 RespondWithJSON( 1370 http.StatusForbidden, 1371 "{}", 1372 ), 1373 CombineHandlers( 1374 VerifyRefreshGrant(refreshToken), 1375 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 1376 ), 1377 ) 1378 1379 // Create the wrapper: 1380 wrapper, err := NewTransportWrapper(). 1381 Logger(logger). 1382 TokenURL(server.URL()). 1383 TrustedCA(ca). 1384 Tokens(refreshToken). 1385 Build(ctx) 1386 Expect(err).ToNot(HaveOccurred()) 1387 defer func() { 1388 err = wrapper.Close() 1389 Expect(err).ToNot(HaveOccurred()) 1390 }() 1391 1392 // Get the tokens: 1393 _, _, err = wrapper.Tokens(ctx) 1394 Expect(err).To(HaveOccurred()) 1395 }) 1396 1397 It("Honours context timeout", func() { 1398 // Generate tokens: 1399 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1400 accessToken := MakeTokenString("Bearer", 5*time.Minute) 1401 1402 // Configure the server with a handler that introduces an 1403 // artificial delay: 1404 server.AppendHandlers( 1405 CombineHandlers( 1406 http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 1407 time.Sleep(10 * time.Millisecond) 1408 }), 1409 VerifyRefreshGrant(refreshToken), 1410 RespondWithAccessAndRefreshTokens(accessToken, refreshToken), 1411 ), 1412 ) 1413 1414 // Create the wrapper: 1415 wrapper, err := NewTransportWrapper(). 1416 Logger(logger). 1417 TokenURL(server.URL()). 1418 TrustedCA(ca). 1419 Tokens(refreshToken). 1420 Build(ctx) 1421 Expect(err).ToNot(HaveOccurred()) 1422 defer func() { 1423 err = wrapper.Close() 1424 Expect(err).ToNot(HaveOccurred()) 1425 }() 1426 1427 // Request the token with a timeout smaller than the artificial 1428 // delay introduced by the server: 1429 ctx, cancel := context.WithTimeout(ctx, 5*time.Millisecond) 1430 defer cancel() 1431 _, _, err = wrapper.Tokens(ctx) 1432 1433 // The request should fail with a context deadline exceeded error: 1434 Expect(err).To(HaveOccurred()) 1435 Expect(errors.Is(err, context.DeadlineExceeded)).To(BeTrue()) 1436 }) 1437 }) 1438 1439 When("Parsing a pull-secret access token", func() { 1440 It("Will not consider a JWT as a pull-secret access token", func() { 1441 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1442 accessToken := MakeTokenString("Bearer", 5*time.Minute) 1443 err := parsePullSecretAccessToken(refreshToken) 1444 Expect(err).To(HaveOccurred()) 1445 err = parsePullSecretAccessToken(accessToken) 1446 Expect(err).To(HaveOccurred()) 1447 }) 1448 It("Will validate a correctly-formatted token", func() { 1449 pullSecretAccessToken := makeTestPullSecretToken() 1450 err := parsePullSecretAccessToken(pullSecretAccessToken) 1451 Expect(err).NotTo(HaveOccurred()) 1452 }) 1453 }) 1454 1455 It("Will prefer the pull-secret access token if one is supplied", func() { 1456 // Generate the tokens: 1457 refreshToken := MakeTokenString("Refresh", 10*time.Hour) 1458 accessToken := MakeTokenString("Bearer", 5*time.Minute) 1459 pullSecretAccessToken := makeTestPullSecretToken() 1460 1461 // Create the wrapper: 1462 wrapper, err := NewTransportWrapper(). 1463 Logger(logger). 1464 TokenURL(server.URL()). 1465 TrustedCA(ca). 1466 Tokens(accessToken, refreshToken, pullSecretAccessToken). 1467 Build(ctx) 1468 Expect(err).ToNot(HaveOccurred()) 1469 defer func() { 1470 err = wrapper.Close() 1471 Expect(err).ToNot(HaveOccurred()) 1472 }() 1473 1474 // Get the tokens: 1475 returnedAccess, _, err := wrapper.Tokens(ctx) 1476 Expect(err).ToNot(HaveOccurred()) 1477 Expect(returnedAccess).To(Equal(pullSecretAccessToken), "Pull Secret Access Token not returned") 1478 }) 1479 1480 }) 1481 1482 func makeTestPullSecretToken() string { 1483 id := uuid.New() 1484 dummyTokenText := base64.StdEncoding.EncodeToString([]byte("abcdefghijklmnopqrstuvwxyz")) 1485 return fmt.Sprintf("%s:%s", id, dummyTokenText) 1486 } 1487 1488 func VerifyPasswordGrant(user, password string) http.HandlerFunc { 1489 return CombineHandlers( 1490 VerifyRequest(http.MethodPost, "/"), 1491 VerifyContentType("application/x-www-form-urlencoded"), 1492 VerifyFormKV("grant_type", "password"), 1493 VerifyFormKV("username", user), 1494 VerifyFormKV("password", password), 1495 ) 1496 } 1497 1498 func VerifyClientCredentialsGrant(id, secret string) http.HandlerFunc { 1499 return CombineHandlers( 1500 VerifyRequest(http.MethodPost, "/"), 1501 VerifyContentType("application/x-www-form-urlencoded"), 1502 VerifyBasicAuth(id, secret), 1503 VerifyFormKV("grant_type", "client_credentials"), 1504 VerifyFormKV("client_id", id), 1505 ) 1506 } 1507 1508 func VerifyRefreshGrant(refreshToken string) http.HandlerFunc { 1509 return CombineHandlers( 1510 VerifyRequest(http.MethodPost, "/"), 1511 VerifyContentType("application/x-www-form-urlencoded"), 1512 VerifyFormKV("grant_type", "refresh_token"), 1513 VerifyFormKV("refresh_token", refreshToken), 1514 ) 1515 }