Skip to content

Allow for custom rest template #8588

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,32 @@
* @author Rafiullah Hamedy
* @since 5.2
*/
class JwtDecoderProviderConfigurationUtils {
public class JwtDecoderProviderConfiguration {
private static final String OIDC_METADATA_PATH = "/.well-known/openid-configuration";
private static final String OAUTH_METADATA_PATH = "/.well-known/oauth-authorization-server";
private static final RestTemplate rest = new RestTemplate();
private static final ParameterizedTypeReference<Map<String, Object>> typeReference =
private final RestTemplate rest = new RestTemplate();
private final ParameterizedTypeReference<Map<String, Object>> typeReference =
new ParameterizedTypeReference<Map<String, Object>>() {};

static Map<String, Object> getConfigurationForOidcIssuerLocation(String oidcIssuerLocation) {
return getConfiguration(oidcIssuerLocation, oidc(URI.create(oidcIssuerLocation)));
Map<String, Object> getConfigurationForOidcIssuerLocation(String oidcIssuerLocation) {
return getConfiguration(rest, oidcIssuerLocation, oidc(URI.create(oidcIssuerLocation)));
}
Map<String, Object> getConfigurationForOidcIssuerLocationWithRestTemplate(RestTemplate rest, String oidcIssuerLocation) {
return getConfiguration(rest, oidcIssuerLocation, oidc(URI.create(oidcIssuerLocation)));
}

Map<String, Object> getConfigurationForIssuerLocation(String issuer) {
URI uri = URI.create(issuer);
return getConfiguration(rest, issuer, oidc(uri), oidcRfc8414(uri), oauth(uri));
}

static Map<String, Object> getConfigurationForIssuerLocation(String issuer) {
Map<String, Object> getConfigurationForIssuerLocationWithRestTemplate(String issuer, RestTemplate rest)
{
URI uri = URI.create(issuer);
return getConfiguration(issuer, oidc(uri), oidcRfc8414(uri), oauth(uri));
return getConfiguration(rest, issuer, oidc(uri), oidcRfc8414(uri), oauth(uri));
}

static void validateIssuer(Map<String, Object> configuration, String issuer) {
void validateIssuer(Map<String, Object> configuration, String issuer) {
String metadataIssuer = "(unavailable)";
if (configuration.containsKey("issuer")) {
metadataIssuer = configuration.get("issuer").toString();
Expand All @@ -63,7 +72,7 @@ static void validateIssuer(Map<String, Object> configuration, String issuer) {
}
}

private static Map<String, Object> getConfiguration(String issuer, URI... uris) {
private Map<String, Object> getConfiguration(RestTemplate rest, String issuer, URI... uris) {
String errorMessage = "Unable to resolve the Configuration with the provided Issuer of " +
"\"" + issuer + "\"";
for (URI uri : uris) {
Expand All @@ -90,19 +99,19 @@ private static Map<String, Object> getConfiguration(String issuer, URI... uris)
throw new IllegalArgumentException(errorMessage);
}

private static URI oidc(URI issuer) {
private URI oidc(URI issuer) {
return UriComponentsBuilder.fromUri(issuer)
.replacePath(issuer.getPath() + OIDC_METADATA_PATH)
.build(Collections.emptyMap());
}

private static URI oidcRfc8414(URI issuer) {
private URI oidcRfc8414(URI issuer) {
return UriComponentsBuilder.fromUri(issuer)
.replacePath(OIDC_METADATA_PATH + issuer.getPath())
.build(Collections.emptyMap());
}

private static URI oauth(URI issuer) {
private URI oauth(URI issuer) {
return UriComponentsBuilder.fromUri(issuer)
.replacePath(OAUTH_METADATA_PATH + issuer.getPath())
.build(Collections.emptyMap());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
*/
public final class JwtDecoders {

private final static JwtDecoderProviderConfiguration JWT_DECODER_PROVIDER_CONFIGURATION = new JwtDecoderProviderConfiguration();

/**
* Creates a {@link JwtDecoder} using the provided
* <a href="https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a> by making an
Expand All @@ -47,7 +49,7 @@ public final class JwtDecoders {
*/
public static JwtDecoder fromOidcIssuerLocation(String oidcIssuerLocation) {
Assert.hasText(oidcIssuerLocation, "oidcIssuerLocation cannot be empty");
Map<String, Object> configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForOidcIssuerLocation(oidcIssuerLocation);
Map<String, Object> configuration = new JwtDecoderProviderConfiguration().getConfigurationForOidcIssuerLocation(oidcIssuerLocation);
return withProviderConfiguration(configuration, oidcIssuerLocation);
}

Expand Down Expand Up @@ -85,7 +87,7 @@ public static JwtDecoder fromOidcIssuerLocation(String oidcIssuerLocation) {
*/
public static JwtDecoder fromIssuerLocation(String issuer) {
Assert.hasText(issuer, "issuer cannot be empty");
Map<String, Object> configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForIssuerLocation(issuer);
Map<String, Object> configuration = JWT_DECODER_PROVIDER_CONFIGURATION.getConfigurationForIssuerLocation(issuer);
return withProviderConfiguration(configuration, issuer);
}

Expand All @@ -100,7 +102,7 @@ public static JwtDecoder fromIssuerLocation(String issuer) {
* @return {@link JwtDecoder}
*/
private static JwtDecoder withProviderConfiguration(Map<String, Object> configuration, String issuer) {
JwtDecoderProviderConfigurationUtils.validateIssuer(configuration, issuer);
JWT_DECODER_PROVIDER_CONFIGURATION.validateIssuer(configuration, issuer);
OAuth2TokenValidator<Jwt> jwtValidator = JwtValidators.createDefaultWithIssuer(issuer);
NimbusJwtDecoder jwtDecoder = withJwkSetUri(configuration.get("jwks_uri").toString()).build();
jwtDecoder.setJwtValidator(jwtValidator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

import static org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder.withJwkSetUri;

Expand All @@ -33,6 +34,7 @@
*/
public final class ReactiveJwtDecoders {

private static final JwtDecoderProviderConfiguration JWT_DECODER_PROVIDER_CONFIGURATION = new JwtDecoderProviderConfiguration();
/**
* Creates a {@link ReactiveJwtDecoder} using the provided
* <a href="https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a> by making an
Expand All @@ -46,7 +48,7 @@ public final class ReactiveJwtDecoders {
*/
public static ReactiveJwtDecoder fromOidcIssuerLocation(String oidcIssuerLocation) {
Assert.hasText(oidcIssuerLocation, "oidcIssuerLocation cannot be empty");
Map<String, Object> configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForOidcIssuerLocation(oidcIssuerLocation);
Map<String, Object> configuration = JWT_DECODER_PROVIDER_CONFIGURATION.getConfigurationForOidcIssuerLocation(oidcIssuerLocation);
return withProviderConfiguration(configuration, oidcIssuerLocation);
}

Expand Down Expand Up @@ -84,7 +86,13 @@ public static ReactiveJwtDecoder fromOidcIssuerLocation(String oidcIssuerLocatio
*/
public static ReactiveJwtDecoder fromIssuerLocation(String issuer) {
Assert.hasText(issuer, "issuer cannot be empty");
Map<String, Object> configuration = JwtDecoderProviderConfigurationUtils.getConfigurationForIssuerLocation(issuer);
Map<String, Object> configuration = JWT_DECODER_PROVIDER_CONFIGURATION.getConfigurationForIssuerLocation(issuer);
return withProviderConfiguration(configuration, issuer);
}

public static ReactiveJwtDecoder fromIssuerLocation(String issuer, RestTemplate rest) {
Assert.hasText(issuer, "issuer cannot be empty");
Map<String, Object> configuration = JWT_DECODER_PROVIDER_CONFIGURATION.getConfigurationForIssuerLocation(issuer);
return withProviderConfiguration(configuration, issuer);
}

Expand All @@ -99,7 +107,7 @@ public static ReactiveJwtDecoder fromIssuerLocation(String issuer) {
* @return {@link ReactiveJwtDecoder}
*/
private static ReactiveJwtDecoder withProviderConfiguration(Map<String, Object> configuration, String issuer) {
JwtDecoderProviderConfigurationUtils.validateIssuer(configuration, issuer);
JWT_DECODER_PROVIDER_CONFIGURATION.validateIssuer(configuration, issuer);
OAuth2TokenValidator<Jwt> jwtValidator = JwtValidators.createDefaultWithIssuer(issuer);
NimbusReactiveJwtDecoder jwtDecoder = withJwkSetUri(configuration.get("jwks_uri").toString()).build();
jwtDecoder.setJwtValidator(jwtValidator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.function.Predicate;

import com.nimbusds.jwt.JWTParser;
import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

Expand Down Expand Up @@ -62,6 +63,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver

private final ReactiveAuthenticationManagerResolver<String> issuerAuthenticationManagerResolver;
private final Converter<ServerWebExchange, Mono<String>> issuerConverter = new JwtClaimIssuerConverter();
private RestTemplate rest = new RestTemplate();

/**
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
Expand All @@ -72,6 +74,10 @@ public JwtIssuerReactiveAuthenticationManagerResolver(String... trustedIssuers)
this(Arrays.asList(trustedIssuers));
}

public void setRest(RestTemplate rest) {
this.rest = rest;
}

/**
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
*
Expand Down Expand Up @@ -167,7 +173,7 @@ public Mono<ReactiveAuthenticationManager> resolve(String issuer) {
}
return this.authenticationManagers.computeIfAbsent(issuer, k ->
Mono.<ReactiveAuthenticationManager>fromCallable(() ->
new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k))
new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k, rest))
)
.subscribeOn(Schedulers.boundedElastic())
.cache());
Expand Down