|
57 | 57 | import com.nimbusds.jwt.proc.JWTProcessor; |
58 | 58 | import reactor.core.publisher.Flux; |
59 | 59 | import reactor.core.publisher.Mono; |
| 60 | +import reactor.core.scheduler.Schedulers; |
60 | 61 | import reactor.util.function.Tuple2; |
61 | 62 | import reactor.util.function.Tuples; |
62 | 63 |
|
@@ -96,7 +97,7 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { |
96 | 97 |
|
97 | 98 | private final Converter<JWT, Mono<JWTClaimsSet>> jwtProcessor; |
98 | 99 |
|
99 | | - private OAuth2TokenValidator<Jwt> jwtValidator = JwtValidators.createDefault(); |
| 100 | + private Converter<Jwt, Mono<Jwt>> jwtValidator; |
100 | 101 |
|
101 | 102 | private Converter<Map<String, Object>, Map<String, Object>> claimSetConverter = MappedJwtClaimSetConverter |
102 | 103 | .withDefaults(Collections.emptyMap()); |
@@ -126,13 +127,35 @@ public NimbusReactiveJwtDecoder(RSAPublicKey publicKey) { |
126 | 127 | */ |
127 | 128 | public NimbusReactiveJwtDecoder(Converter<JWT, Mono<JWTClaimsSet>> jwtProcessor) { |
128 | 129 | this.jwtProcessor = jwtProcessor; |
| 130 | + setJwtValidator(JwtValidators.createDefault()); |
129 | 131 | } |
130 | 132 |
|
131 | 133 | /** |
132 | 134 | * Use the provided {@link OAuth2TokenValidator} to validate incoming {@link Jwt}s. |
133 | 135 | * @param jwtValidator the {@link OAuth2TokenValidator} to use |
134 | 136 | */ |
135 | 137 | public void setJwtValidator(OAuth2TokenValidator<Jwt> jwtValidator) { |
| 138 | + Assert.notNull(jwtValidator, "jwtValidator cannot be null"); |
| 139 | + this.jwtValidator = jwt -> Mono.fromSupplier(() -> jwtValidator.validate(jwt)) |
| 140 | + .subscribeOn(Schedulers.boundedElastic()) |
| 141 | + .handle((result, sink) -> { |
| 142 | + if (result.hasErrors()) { |
| 143 | + Collection<OAuth2Error> errors = result.getErrors(); |
| 144 | + String validationErrorString = getJwtValidationExceptionMessage(errors); |
| 145 | + sink.error(new JwtValidationException(validationErrorString, errors)); |
| 146 | + } |
| 147 | + else { |
| 148 | + sink.next(jwt); |
| 149 | + } |
| 150 | + }); |
| 151 | + } |
| 152 | + |
| 153 | + /** |
| 154 | + * Use the provided {@link Converter} to validate incoming {@link Jwt}s. |
| 155 | + * This overrides the {@link OAuth2TokenValidator}, but allows for reactive validation. |
| 156 | + * @param jwtValidator the {@link Converter} to use |
| 157 | + */ |
| 158 | + public void setJwtValidator(Converter<Jwt, Mono<Jwt>> jwtValidator) { |
136 | 159 | Assert.notNull(jwtValidator, "jwtValidator cannot be null"); |
137 | 160 | this.jwtValidator = jwtValidator; |
138 | 161 | } |
@@ -166,7 +189,7 @@ private Mono<Jwt> decode(JWT parsedToken) { |
166 | 189 | // @formatter:off |
167 | 190 | return this.jwtProcessor.convert(parsedToken) |
168 | 191 | .map((set) -> createJwt(parsedToken, set)) |
169 | | - .map(this::validateJwt) |
| 192 | + .flatMap(jwtValidator::convert) |
170 | 193 | .onErrorMap((ex) -> !(ex instanceof IllegalStateException) && !(ex instanceof JwtException), |
171 | 194 | (ex) -> new JwtException("An error occurred while attempting to decode the Jwt: ", ex)); |
172 | 195 | // @formatter:on |
|
0 commit comments