mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-02-25 06:34:59 +00:00
Add postProcessor to Introspector Builder
Closes gh-18623 Signed-off-by: itsmevichu <vishnutheep@gmail.com>
This commit is contained in:
parent
da0cd0bc68
commit
d528be38bb
@ -28,6 +28,7 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@ -325,6 +326,8 @@ public class SpringOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
||||
|
||||
private String clientSecret;
|
||||
|
||||
private final List<Consumer<SpringOpaqueTokenIntrospector>> postProcessors = new ArrayList<>();
|
||||
|
||||
private Builder(String introspectionUri) {
|
||||
this.introspectionUri = introspectionUri;
|
||||
}
|
||||
@ -355,6 +358,20 @@ public class SpringOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Consumer} to customize the {@link SpringOpaqueTokenIntrospector}
|
||||
* after it is built. This allows for additional configuration that cannot be
|
||||
* expressed through the builder methods.
|
||||
* @param customizer the {@link Consumer} to customize the introspector
|
||||
* @return the {@link SpringOpaqueTokenIntrospector.Builder}
|
||||
* @since 7.x.x
|
||||
*/
|
||||
public Builder postProcessor(Consumer<SpringOpaqueTokenIntrospector> customizer) {
|
||||
Assert.notNull(customizer, "customizer cannot be null");
|
||||
this.postProcessors.add(customizer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code SpringOpaqueTokenIntrospector}
|
||||
* @return the {@link SpringOpaqueTokenIntrospector}
|
||||
@ -363,7 +380,10 @@ public class SpringOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
|
||||
public SpringOpaqueTokenIntrospector build() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(this.clientId, this.clientSecret));
|
||||
return new SpringOpaqueTokenIntrospector(this.introspectionUri, restTemplate);
|
||||
SpringOpaqueTokenIntrospector introspector = new SpringOpaqueTokenIntrospector(this.introspectionUri,
|
||||
restTemplate);
|
||||
this.postProcessors.forEach((postProcessor) -> postProcessor.accept(introspector));
|
||||
return introspector;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@ -278,6 +279,8 @@ public class SpringReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
|
||||
|
||||
private String clientSecret;
|
||||
|
||||
private final List<Consumer<SpringReactiveOpaqueTokenIntrospector>> postProcessors = new ArrayList<>();
|
||||
|
||||
private Builder(String introspectionUri) {
|
||||
this.introspectionUri = introspectionUri;
|
||||
}
|
||||
@ -308,6 +311,21 @@ public class SpringReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Consumer} to customize the
|
||||
* {@link SpringReactiveOpaqueTokenIntrospector} after it is built. This allows
|
||||
* for additional configuration that cannot be expressed through the builder
|
||||
* methods.
|
||||
* @param customizer the {@link Consumer} to customize the introspector
|
||||
* @return the {@link SpringReactiveOpaqueTokenIntrospector.Builder}
|
||||
* @since 7.x.x
|
||||
*/
|
||||
public Builder postProcessor(Consumer<SpringReactiveOpaqueTokenIntrospector> customizer) {
|
||||
Assert.notNull(customizer, "customizer cannot be null");
|
||||
this.postProcessors.add(customizer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code SpringReactiveOpaqueTokenIntrospector}
|
||||
* @return the {@link SpringReactiveOpaqueTokenIntrospector}
|
||||
@ -317,7 +335,10 @@ public class SpringReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
|
||||
WebClient webClient = WebClient.builder()
|
||||
.defaultHeaders((h) -> h.setBasicAuth(this.clientId, this.clientSecret))
|
||||
.build();
|
||||
return new SpringReactiveOpaqueTokenIntrospector(this.introspectionUri, webClient);
|
||||
SpringReactiveOpaqueTokenIntrospector introspector = new SpringReactiveOpaqueTokenIntrospector(
|
||||
this.introspectionUri, webClient);
|
||||
this.postProcessors.forEach((postProcessor) -> postProcessor.accept(introspector));
|
||||
return introspector;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -383,6 +383,25 @@ public class SpringOpaqueTokenIntrospectorTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void builderWhenPostProcessorSetThenApplied() throws Exception {
|
||||
try (MockWebServer server = new MockWebServer()) {
|
||||
server.setDispatcher(requiresAuth(CLIENT_ID, CLIENT_SECRET, ACTIVE_RESPONSE));
|
||||
String introspectUri = server.url("/introspect").toString();
|
||||
Converter<OAuth2TokenIntrospectionClaimAccessor, OAuth2AuthenticatedPrincipal> authenticationConverter = mock(
|
||||
Converter.class);
|
||||
OAuth2AuthenticatedPrincipal principal = mock(OAuth2AuthenticatedPrincipal.class);
|
||||
given(authenticationConverter.convert(any())).willReturn(principal);
|
||||
OpaqueTokenIntrospector introspector = SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectUri)
|
||||
.clientId(CLIENT_ID)
|
||||
.clientSecret(CLIENT_SECRET)
|
||||
.postProcessor((i) -> i.setAuthenticationConverter(authenticationConverter))
|
||||
.build();
|
||||
OAuth2AuthenticatedPrincipal result = introspector.introspect("token");
|
||||
assertThat(result).isSameAs(principal);
|
||||
}
|
||||
}
|
||||
|
||||
private static ResponseEntity<Map<String, Object>> response(String content) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
@ -308,6 +308,26 @@ public class SpringReactiveOpaqueTokenIntrospectorTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void builderWhenPostProcessorSetThenApplied() throws Exception {
|
||||
try (MockWebServer server = new MockWebServer()) {
|
||||
server.setDispatcher(requiresAuth(CLIENT_ID, CLIENT_SECRET, ACTIVE_RESPONSE));
|
||||
String introspectUri = server.url("/introspect").toString();
|
||||
Converter<OAuth2TokenIntrospectionClaimAccessor, Mono<? extends OAuth2AuthenticatedPrincipal>> authenticationConverter = mock(
|
||||
Converter.class);
|
||||
OAuth2AuthenticatedPrincipal principal = mock(OAuth2AuthenticatedPrincipal.class);
|
||||
given(authenticationConverter.convert(any())).willReturn((Mono) Mono.just(principal));
|
||||
ReactiveOpaqueTokenIntrospector introspector = SpringReactiveOpaqueTokenIntrospector
|
||||
.withIntrospectionUri(introspectUri)
|
||||
.clientId(CLIENT_ID)
|
||||
.clientSecret(CLIENT_SECRET)
|
||||
.postProcessor((i) -> i.setAuthenticationConverter(authenticationConverter))
|
||||
.build();
|
||||
OAuth2AuthenticatedPrincipal result = introspector.introspect("token").block();
|
||||
assertThat(result).isSameAs(principal);
|
||||
}
|
||||
}
|
||||
|
||||
private WebClient mockResponse(String response) {
|
||||
return mockResponse(toMap(response));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user