@@ -416,7 +416,11 @@ def set_basic_auth_header(user, password)
416
416
let ( :token_aud ) { [ "https://openproject.local" , "master-realm" , "account" ] }
417
417
let ( :token_issuer ) { "https://keycloak.local/realms/master" }
418
418
let ( :expected_message ) { "You did not provide the correct credentials." }
419
- let ( :keys_request_stub ) { nil }
419
+ let ( :keys_request_stub ) do
420
+ stub_request ( :get , "https://keycloak.local/realms/master/protocol/openid-connect/certs" )
421
+ . to_return ( status : 200 , body : JWT ::JWK ::Set . new ( jwk_response ) . export . to_json , headers : { } )
422
+ end
423
+ let ( :jwk_response ) { jwk }
420
424
421
425
before do
422
426
create ( :oidc_provider , slug : "keycloak" )
@@ -426,10 +430,17 @@ def set_basic_auth_header(user, password)
426
430
header "Authorization" , "Bearer #{ token } "
427
431
end
428
432
433
+ it "succeeds" do
434
+ get resource
435
+
436
+ expect ( last_response ) . to have_http_status :ok
437
+ expect ( last_response . header [ "WWW-Authenticate" ] ) . to be_blank
438
+ end
439
+
429
440
context "when token is issued by provider not configured in OP" do
430
441
let ( :token_issuer ) { "https://eve.example.com" }
431
442
432
- it do
443
+ it "fails with HTTP 401 Unauthorized" do
433
444
get resource
434
445
expect ( last_response ) . to have_http_status :unauthorized
435
446
expect ( last_response . header [ "WWW-Authenticate" ] )
@@ -438,103 +449,66 @@ def set_basic_auth_header(user, password)
438
449
end
439
450
end
440
451
441
- context "when token is issued by provider configured in OP" do
442
- context "when token signature algorithm is not supported" do
443
- let ( :token ) { JWT . encode ( payload , "secret" , "HS256" , { kid : "97AmyvoS8BFFRfm585GPgA16G1H2V22EdxxuAYUuoKk" } ) }
444
-
445
- it do
446
- get resource
447
- expect ( last_response ) . to have_http_status :unauthorized
448
- error = "Token signature algorithm HS256 is not supported"
449
- expect ( last_response . header [ "WWW-Authenticate" ] )
450
- . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="#{ error } "} )
451
- expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
452
- end
453
- end
452
+ context "when token signature algorithm is not supported" do
453
+ let ( :token ) { JWT . encode ( payload , "secret" , "HS256" , { kid : "97AmyvoS8BFFRfm585GPgA16G1H2V22EdxxuAYUuoKk" } ) }
454
454
455
- context "when kid is present" do
456
- let ( :keys_request_stub ) do
457
- stub_request ( :get , "https://keycloak.local/realms/master/protocol/openid-connect/certs" )
458
- . with (
459
- headers : {
460
- "Accept" => "*/*" ,
461
- "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" ,
462
- "User-Agent" => /JSON::JWK::Set::Fetcher \d +\. \d +\. \d +/
463
- }
464
- )
465
- . to_return ( status : 200 , body : JWT ::JWK ::Set . new ( jwk ) . export . to_json , headers : { } )
466
- end
467
-
468
- context "when access token has not expired yet" do
469
- context "when aud does not contain client_id" do
470
- let ( :token_aud ) { [ "Lisa" , "Bart" ] }
471
-
472
- it do
473
- get resource
455
+ it "fails with HTTP 401 Unauthorized" do
456
+ get resource
457
+ expect ( last_response ) . to have_http_status :unauthorized
458
+ error = "Token signature algorithm HS256 is not supported"
459
+ expect ( last_response . header [ "WWW-Authenticate" ] )
460
+ . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="#{ error } "} )
461
+ expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
462
+ end
463
+ end
474
464
475
- expect ( last_response ) . to have_http_status :unauthorized
476
- error = 'Invalid audience. Expected https://openproject.local, received ["Lisa", "Bart"]'
477
- expect ( last_response . header [ "WWW-Authenticate" ] )
478
- . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="#{ error } "} )
479
- expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
480
- end
481
- end
465
+ context "when aud does not contain client_id" do
466
+ let ( :token_aud ) { [ "Lisa" , "Bart" ] }
482
467
483
- context "when aud contains client_id" do
484
- it do
485
- get resource
468
+ it "fails with HTTP 401 Unauthorized" do
469
+ get resource
486
470
487
- expect ( last_response ) . to have_http_status :ok
488
- end
489
- end
490
- end
471
+ expect ( last_response ) . to have_http_status :unauthorized
472
+ error = 'Invalid audience. Expected https://openproject.local, received ["Lisa", "Bart"]'
473
+ expect ( last_response . header [ "WWW-Authenticate" ] )
474
+ . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="#{ error } "} )
475
+ expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
476
+ end
477
+ end
491
478
492
- context "when access token has expired already" do
493
- let ( :token_exp ) { 5 . minutes . ago }
479
+ context "when access token has expired already" do
480
+ let ( :token_exp ) { 5 . minutes . ago }
494
481
495
- it do
496
- get resource
482
+ it "fails with HTTP 401 Unauthorized" do
483
+ get resource
497
484
498
- expect ( last_response ) . to have_http_status :unauthorized
499
- expect ( last_response . header [ "WWW-Authenticate" ] )
500
- . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="Signature has expired"} )
501
- expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
502
- end
485
+ expect ( last_response ) . to have_http_status :unauthorized
486
+ expect ( last_response . header [ "WWW-Authenticate" ] )
487
+ . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="Signature has expired"} )
488
+ expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
489
+ end
503
490
504
- it "caches keys request to keycloak" do
505
- get resource
506
- expect ( last_response ) . to have_http_status :unauthorized
491
+ it "caches keys request to keycloak" do
492
+ get resource
493
+ expect ( last_response ) . to have_http_status :unauthorized
507
494
508
- get resource
509
- expect ( last_response ) . to have_http_status :unauthorized
495
+ get resource
496
+ expect ( last_response ) . to have_http_status :unauthorized
510
497
511
- expect ( keys_request_stub ) . to have_been_made . once
512
- end
513
- end
498
+ expect ( keys_request_stub ) . to have_been_made . once
514
499
end
500
+ end
515
501
516
- context "when kid is absent in keycloak keys response" do
517
- let ( :keys_request_stub ) do
518
- wrong_key = JWT ::JWK . new ( OpenSSL ::PKey ::RSA . new ( 2048 ) , kid : "your-kid" , use : "sig" , alg : "RS256" )
519
- stub_request ( :get , "https://keycloak.local/realms/master/protocol/openid-connect/certs" )
520
- . with (
521
- headers : {
522
- "Accept" => "*/*" ,
523
- "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3" ,
524
- "User-Agent" => /JSON::JWK::Set::Fetcher \d +\. \d +\. \d +/
525
- }
526
- )
527
- . to_return ( status : 200 , body : JWT ::JWK ::Set . new ( wrong_key ) . export . to_json , headers : { } )
528
- end
502
+ context "when kid is absent in keycloak keys response" do
503
+ let ( :jwk_response ) { JWT ::JWK . new ( OpenSSL ::PKey ::RSA . new ( 2048 ) , kid : "your-kid" , use : "sig" , alg : "RS256" ) }
529
504
530
- it do
531
- get resource
532
- expect ( last_response ) . to have_http_status :unauthorized
533
- expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
534
- error = "The signature key ID is unknown"
535
- expect ( last_response . header [ "WWW-Authenticate" ] )
536
- . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="#{ error } "} )
537
- end
505
+ it "fails with HTTP 401 Unauthorized" do
506
+ get resource
507
+ expect ( last_response ) . to have_http_status :unauthorized
508
+ expect ( JSON . parse ( last_response . body ) ) . to eq ( error_response_body )
509
+ error = "The signature key ID is unknown"
510
+ expect ( last_response . header [ "WWW-Authenticate" ] )
511
+ . to eq ( %{Bearer realm="OpenProject API", error="invalid_token", error_description="#{ error } "} )
538
512
end
539
513
end
540
514
end
0 commit comments