Skip to content

Commit dbd1819

Browse files
BoukeNijhuisjgrandja
authored andcommitted
add media type jwk-set+json to accept header
Fixes gh-7290
1 parent ad0d3e9 commit dbd1819

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.security.interfaces.RSAPublicKey;
2323
import java.text.ParseException;
2424
import java.time.Instant;
25+
import java.util.Arrays;
2526
import java.util.Collections;
2627
import java.util.HashMap;
2728
import java.util.HashSet;
@@ -310,6 +311,7 @@ private static URL toURL(String url) {
310311
}
311312

312313
private static class RestOperationsResourceRetriever implements ResourceRetriever {
314+
private static final MediaType APPLICATION_JWK_SET_JSON = new MediaType("application", "jwk-set+json");
313315
private final RestOperations restOperations;
314316

315317
RestOperationsResourceRetriever(RestOperations restOperations) {
@@ -320,7 +322,7 @@ private static class RestOperationsResourceRetriever implements ResourceRetrieve
320322
@Override
321323
public Resource retrieveResource(URL url) throws IOException {
322324
HttpHeaders headers = new HttpHeaders();
323-
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
325+
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON, APPLICATION_JWK_SET_JSON));
324326

325327
ResponseEntity<String> response;
326328
try {

oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoderTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.Base64;
3131
import java.util.Collections;
3232
import java.util.Date;
33+
import java.util.List;
3334
import java.util.Map;
3435
import javax.crypto.SecretKey;
3536

@@ -54,8 +55,10 @@
5455
import org.junit.BeforeClass;
5556
import org.junit.Test;
5657

58+
import org.mockito.ArgumentCaptor;
5759
import org.springframework.core.convert.converter.Converter;
5860
import org.springframework.http.HttpStatus;
61+
import org.springframework.http.MediaType;
5962
import org.springframework.http.RequestEntity;
6063
import org.springframework.http.ResponseEntity;
6164
import org.springframework.security.oauth2.core.OAuth2Error;
@@ -72,6 +75,7 @@
7275
import static org.mockito.ArgumentMatchers.any;
7376
import static org.mockito.ArgumentMatchers.eq;
7477
import static org.mockito.Mockito.mock;
78+
import static org.mockito.Mockito.verify;
7579
import static org.mockito.Mockito.when;
7680
import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSetUri;
7781
import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withPublicKey;
@@ -97,6 +101,8 @@ public class NimbusJwtDecoderTests {
97101
private static final String RS256_SIGNED_JWT = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYzMzl9.CT-H2OWEqmSs1NWmnta5ealLFvM8OlbQTjGhfRcKLNxrTrzsOkqBJl-AN3k16BQU7mS32o744TiiZ29NcDlxPsr1MqTlN86-dobPiuNIDLp3A1bOVdXMcVFuMYkrNv0yW0tGS9OjEqsCCuZDkZ1by6AhsHLbGwRY-6AQdcRouZygGpOQu1hNun5j8q5DpSTY4AXKARIFlF-O3OpVbPJ0ebr3Ki-i3U9p_55H0e4-wx2bqcApWlqgofl1I8NKWacbhZgn81iibup2W7E0CzCzh71u1Mcy3xk1sYePx-dwcxJnHmxJReBBWjJZEAeCrkbnn_OCuo2fA-EQyNJtlN5F2w";
98102
private static final String VERIFY_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4yKxb6SNePdDmQi9xFCrP6QvHosErQzryknQTTTffs0t3cy3Er3lIceuhZ7yQNSCDfPFqG8GoyoKhuChRiA5D+J2ab7bqTa1QJKfnCyERoscftgN2fXPHjHoiKbpGV2tMVw8mXl//tePOAiKbMJaBUnlAvJgkk1rVm08dSwpLC1sr2M19euf9jwnRGkMRZuhp9iCPgECRke5T8Ixpv0uQjSmGHnWUKTFlbj8sM83suROR1Ue64JSGScANc5vk3huJ/J97qTC+K2oKj6L8d9O8dpc4obijEOJwpydNvTYDgbiivYeSB00KS9jlBkQ5B2QqLvLVEygDl3dp59nGx6YQIDAQAB";
99103

104+
private static final MediaType APPLICATION_JWK_SET_JSON = new MediaType("application", "jwk-set+json");
105+
100106
private static KeyFactory kf;
101107

102108
NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(withoutSigning());
@@ -400,6 +406,23 @@ public void jwsKeySelectorWhenMultipleAlgorithmThenReturnsCompositeSelector() {
400406
.containsExactlyInAnyOrder(JWSAlgorithm.RS256, JWSAlgorithm.RS512);
401407
}
402408

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+
403426
private RSAPublicKey key() throws InvalidKeySpecException {
404427
byte[] decoded = Base64.getDecoder().decode(VERIFY_KEY.getBytes());
405428
EncodedKeySpec spec = new X509EncodedKeySpec(decoded);

0 commit comments

Comments
 (0)