30
30
import java .util .Base64 ;
31
31
import java .util .Collections ;
32
32
import java .util .Date ;
33
+ import java .util .List ;
33
34
import java .util .Map ;
34
35
import javax .crypto .SecretKey ;
35
36
54
55
import org .junit .BeforeClass ;
55
56
import org .junit .Test ;
56
57
58
+ import org .mockito .ArgumentCaptor ;
57
59
import org .springframework .core .convert .converter .Converter ;
58
60
import org .springframework .http .HttpStatus ;
61
+ import org .springframework .http .MediaType ;
59
62
import org .springframework .http .RequestEntity ;
60
63
import org .springframework .http .ResponseEntity ;
61
64
import org .springframework .security .oauth2 .core .OAuth2Error ;
72
75
import static org .mockito .ArgumentMatchers .any ;
73
76
import static org .mockito .ArgumentMatchers .eq ;
74
77
import static org .mockito .Mockito .mock ;
78
+ import static org .mockito .Mockito .verify ;
75
79
import static org .mockito .Mockito .when ;
76
80
import static org .springframework .security .oauth2 .jwt .NimbusJwtDecoder .withJwkSetUri ;
77
81
import static org .springframework .security .oauth2 .jwt .NimbusJwtDecoder .withPublicKey ;
@@ -97,6 +101,8 @@ public class NimbusJwtDecoderTests {
97
101
private static final String RS256_SIGNED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYzMzl9.CT-H2OWEqmSs1NWmnta5ealLFvM8OlbQTjGhfRcKLNxrTrzsOkqBJl-AN3k16BQU7mS32o744TiiZ29NcDlxPsr1MqTlN86-dobPiuNIDLp3A1bOVdXMcVFuMYkrNv0yW0tGS9OjEqsCCuZDkZ1by6AhsHLbGwRY-6AQdcRouZygGpOQu1hNun5j8q5DpSTY4AXKARIFlF-O3OpVbPJ0ebr3Ki-i3U9p_55H0e4-wx2bqcApWlqgofl1I8NKWacbhZgn81iibup2W7E0CzCzh71u1Mcy3xk1sYePx-dwcxJnHmxJReBBWjJZEAeCrkbnn_OCuo2fA-EQyNJtlN5F2w" ;
98
102
private static final String VERIFY_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4yKxb6SNePdDmQi9xFCrP6QvHosErQzryknQTTTffs0t3cy3Er3lIceuhZ7yQNSCDfPFqG8GoyoKhuChRiA5D+J2ab7bqTa1QJKfnCyERoscftgN2fXPHjHoiKbpGV2tMVw8mXl//tePOAiKbMJaBUnlAvJgkk1rVm08dSwpLC1sr2M19euf9jwnRGkMRZuhp9iCPgECRke5T8Ixpv0uQjSmGHnWUKTFlbj8sM83suROR1Ue64JSGScANc5vk3huJ/J97qTC+K2oKj6L8d9O8dpc4obijEOJwpydNvTYDgbiivYeSB00KS9jlBkQ5B2QqLvLVEygDl3dp59nGx6YQIDAQAB" ;
99
103
104
+ private static final MediaType APPLICATION_JWK_SET_JSON = new MediaType ("application" , "jwk-set+json" );
105
+
100
106
private static KeyFactory kf ;
101
107
102
108
NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder (withoutSigning ());
@@ -400,6 +406,23 @@ public void jwsKeySelectorWhenMultipleAlgorithmThenReturnsCompositeSelector() {
400
406
.containsExactlyInAnyOrder (JWSAlgorithm .RS256 , JWSAlgorithm .RS512 );
401
407
}
402
408
409
+ // gh-7290
410
+ @ Test
411
+ public void decodeWhenJwkSetRequestedThenAcceptHeaderJsonAndJwkSetJson () {
412
+ RestOperations restOperations = mock (RestOperations .class );
413
+ when (restOperations .exchange (any (RequestEntity .class ), eq (String .class )))
414
+ .thenReturn (new ResponseEntity <>(JWK_SET , HttpStatus .OK ));
415
+ JWTProcessor <SecurityContext > processor = withJwkSetUri ("https://issuer/.well-known/jwks.json" )
416
+ .restOperations (restOperations )
417
+ .processor ();
418
+ NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder (processor );
419
+ jwtDecoder .decode (SIGNED_JWT );
420
+ ArgumentCaptor <RequestEntity > requestEntityCaptor = ArgumentCaptor .forClass (RequestEntity .class );
421
+ verify (restOperations ).exchange (requestEntityCaptor .capture (), eq (String .class ));
422
+ List <MediaType > acceptHeader = requestEntityCaptor .getValue ().getHeaders ().getAccept ();
423
+ assertThat (acceptHeader ).contains (MediaType .APPLICATION_JSON , APPLICATION_JWK_SET_JSON );
424
+ }
425
+
403
426
private RSAPublicKey key () throws InvalidKeySpecException {
404
427
byte [] decoded = Base64 .getDecoder ().decode (VERIFY_KEY .getBytes ());
405
428
EncodedKeySpec spec = new X509EncodedKeySpec (decoded );
0 commit comments