Skip to content

Instantiate exceptions lazily #7996

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

Merged
merged 2 commits into from
Feb 27, 2020
Merged
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 @@ -16,9 +16,9 @@

package org.springframework.security.oauth2.server.resource.authentication;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
Expand Down Expand Up @@ -54,6 +54,7 @@
* <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>.
*
* @author Josh Cummings
* @author Roman Matiushchenko
* @since 5.3
*/
public final class JwtIssuerReactiveAuthenticationManagerResolver
Expand All @@ -79,8 +80,7 @@ public JwtIssuerReactiveAuthenticationManagerResolver(String... trustedIssuers)
public JwtIssuerReactiveAuthenticationManagerResolver(Collection<String> trustedIssuers) {
Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty");
this.issuerAuthenticationManagerResolver =
new TrustedIssuerJwtAuthenticationManagerResolver
(Collections.unmodifiableCollection(trustedIssuers)::contains);
new TrustedIssuerJwtAuthenticationManagerResolver(new ArrayList<>(trustedIssuers)::contains);
}

/**
Expand Down Expand Up @@ -121,7 +121,7 @@ public Mono<ReactiveAuthenticationManager> resolve(ServerWebExchange exchange) {
return this.issuerConverter.convert(exchange)
.flatMap(issuer ->
this.issuerAuthenticationManagerResolver.resolve(issuer).switchIfEmpty(
Mono.error(new InvalidBearerTokenException("Invalid issuer " + issuer)))
Mono.error(() -> new InvalidBearerTokenException("Invalid issuer " + issuer)))
);
}

Expand All @@ -133,26 +133,26 @@ private static class JwtClaimIssuerConverter

@Override
public Mono<String> convert(@NonNull ServerWebExchange exchange) {
return this.converter.convert(exchange)
.cast(BearerTokenAuthenticationToken.class)
.flatMap(this::issuer);
}

private Mono<String> issuer(BearerTokenAuthenticationToken token) {
try {
String issuer = JWTParser.parse(token.getToken()).getJWTClaimsSet().getIssuer();
return Mono.justOrEmpty(issuer).switchIfEmpty(
Mono.error(new InvalidBearerTokenException("Missing issuer")));
} catch (Exception e) {
return Mono.error(new InvalidBearerTokenException(e.getMessage()));
}
return this.converter.convert(exchange).map(convertedToken -> {
BearerTokenAuthenticationToken token = (BearerTokenAuthenticationToken) convertedToken;
try {
String issuer = JWTParser.parse(token.getToken()).getJWTClaimsSet().getIssuer();
if (issuer == null) {
throw new InvalidBearerTokenException("Missing issuer");
} else {
return issuer;
}
} catch (Exception e) {
throw new InvalidBearerTokenException(e.getMessage(), e);
}
});
}
}

private static class TrustedIssuerJwtAuthenticationManagerResolver
implements ReactiveAuthenticationManagerResolver<String> {

private final Map<String, Mono<? extends ReactiveAuthenticationManager>> authenticationManagers =
private final Map<String, Mono<ReactiveAuthenticationManager>> authenticationManagers =
new ConcurrentHashMap<>();
private final Predicate<String> trustedIssuer;

Expand All @@ -162,15 +162,15 @@ private static class TrustedIssuerJwtAuthenticationManagerResolver

@Override
public Mono<ReactiveAuthenticationManager> resolve(String issuer) {
return Mono.just(issuer)
.filter(this.trustedIssuer)
.flatMap(iss ->
this.authenticationManagers.computeIfAbsent(iss, k ->
Mono.fromCallable(() -> ReactiveJwtDecoders.fromIssuerLocation(iss))
.subscribeOn(Schedulers.boundedElastic())
.map(JwtReactiveAuthenticationManager::new)
.cache())
);
if (!this.trustedIssuer.test(issuer)) {
return Mono.empty();
}
return this.authenticationManagers.computeIfAbsent(issuer, k ->
Mono.<ReactiveAuthenticationManager>fromCallable(() ->
new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k))
)
.subscribeOn(Schedulers.boundedElastic())
.cache());
}
}
}