Skip to content

Commit

Permalink
Merge branch '6.1.x'
Browse files Browse the repository at this point in the history
Closes gh-14042
  • Loading branch information
sjohnr committed Oct 19, 2023
2 parents 10c85cc + b4e0873 commit 975ac10
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,24 @@ class ReactiveRemoteJWKSource implements ReactiveJWKSource {
*/
private final AtomicReference<Mono<JWKSet>> cachedJWKSet = new AtomicReference<>(Mono.empty());

/**
* The cached JWK set URL.
*/
private final AtomicReference<String> cachedJwkSetUrl = new AtomicReference<>();

private WebClient webClient = WebClient.create();

private final Mono<String> jwkSetURL;
private final Mono<String> jwkSetUrlProvider;

ReactiveRemoteJWKSource(String jwkSetURL) {
Assert.hasText(jwkSetURL, "jwkSetURL cannot be empty");
this.jwkSetURL = Mono.just(jwkSetURL);
this.jwkSetUrlProvider = Mono.just(jwkSetURL);
}

ReactiveRemoteJWKSource(Mono<String> jwkSetURL) {
Assert.notNull(jwkSetURL, "jwkSetURL cannot be null");
this.jwkSetURL = jwkSetURL.cache();
ReactiveRemoteJWKSource(Mono<String> jwkSetUrlProvider) {
Assert.notNull(jwkSetUrlProvider, "jwkSetUrlProvider cannot be null");
this.jwkSetUrlProvider = Mono.fromCallable(this.cachedJwkSetUrl::get)
.switchIfEmpty(Mono.defer(() -> jwkSetUrlProvider.doOnNext(this.cachedJwkSetUrl::set)));
}

@Override
Expand Down Expand Up @@ -100,13 +106,15 @@ private Mono<List<JWK>> get(JWKSelector jwkSelector, JWKSet jwkSet) {
*/
private Mono<JWKSet> getJWKSet() {
// @formatter:off
return this.jwkSetURL.flatMap((jwkSetURL) -> this.webClient.get()
.uri(jwkSetURL)
.retrieve()
.bodyToMono(String.class))
return this.jwkSetUrlProvider
.flatMap((jwkSetURL) -> this.webClient.get()
.uri(jwkSetURL)
.retrieve()
.bodyToMono(String.class)
)
.map(this::parse)
.doOnNext((jwkSet) -> this.cachedJWKSet
.set(Mono.just(jwkSet))
.set(Mono.just(jwkSet))
)
.cache();
// @formatter:on
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@

import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKMatcher;
Expand All @@ -31,10 +32,16 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import reactor.core.publisher.Mono;

import org.springframework.web.reactive.function.client.WebClientResponseException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willReturn;
import static org.mockito.BDDMockito.willThrow;

/**
* @author Rob Winch
Expand All @@ -52,6 +59,9 @@ public class ReactiveRemoteJWKSourceTests {

private MockWebServer server;

@Mock
private Supplier<String> mockStringSupplier;

// @formatter:off
private String keys = "{\n"
+ " \"keys\": [\n"
Expand Down Expand Up @@ -156,4 +166,18 @@ public void getWhenNoMatchAndKeyIdMatchThenEmpty() {
assertThat(this.source.get(this.selector).block()).isEmpty();
}

@Test
public void getShouldRecoverAndReturnKeysAfterErrorCase() {
given(this.matcher.matches(any())).willReturn(true);
this.source = new ReactiveRemoteJWKSource(Mono.fromSupplier(this.mockStringSupplier));
willThrow(WebClientResponseException.ServiceUnavailable.class).given(this.mockStringSupplier).get();
// first case: id provider has error state
assertThatExceptionOfType(WebClientResponseException.ServiceUnavailable.class)
.isThrownBy(() -> this.source.get(this.selector).block());
// second case: id provider is healthy again
willReturn(this.server.url("/").toString()).given(this.mockStringSupplier).get();
List<JWK> actual = this.source.get(this.selector).block();
assertThat(actual).isNotEmpty();
}

}

0 comments on commit 975ac10

Please sign in to comment.