1

I'm configuring a spring application to use existing authentication in Webclient:

Flow:

Client login app -> service1 -> service2

Webclient service1:

@Bean
public WebClient webClient(ClientRegistrationRepository clientRegistrations,
                           OAuth2AuthorizedClientRepository authorizedClients) {
    
    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
    
    oauth2Client.setDefaultOAuth2AuthorizedClient(true);
    
    return WebClient.builder()
            .apply(oauth2Client.oauth2Configuration()) 
            .baseUrl("some_url")
            .exchangeStrategies(ExchangeStrategies.builder()
                    .codecs(configurer ->
                            configurer.defaultCodecs()
                                    .maxInMemorySize(2 * 1024)
                    )
                    .build())
            .filter(this.logRequest())
            .build();
}

service1 Call to service2:

        Flux<DataBuffer> dataBuffer = webClient
            .get()
            .uri("some_uri")
            .accept(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL)
            .retrieve()
            .bodyToFlux(DataBuffer.class);

    DataBufferUtils.write(dataBuffer, Paths.get(joiner.toString()) , StandardOpenOption.CREATE).share().block();

The above fails to add a bearer token to the request, which subsequently fails auth on service2.

I can add the following to my Webclient: oauth2Client.setDefaultClientRegistrationId("keycloak"); This will add a token to each request, but the token is not the existing token available at: SecurityContextHolder.getContext().getAuthentication();

It appears to be a newly requested token using the spring.security.oauth2.client.registration config in the application.properties

I've been able to get the existing token added to my request, by modifying the call to set the header as follows:

Flux<DataBuffer> dataBuffer = webClient
            .get()
            .uri(Constant.AQUAMIS_DOCUMENTS_URL + entityId)
            .headers(h -> h.setBearerAuth(keycloakPrincipal.getKeycloakSecurityContext().getTokenString()))
            .accept(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL)
            .retrieve()
            .bodyToFlux(DataBuffer.class);

I'm unable to get the Webclient to use the existing token, without extracting it from Springs security context and explicitly setting it myself on the Webclient.

Am I missing something, from the documentation I've read my intial configuration should be reusing the token contained within the spring security context?

JTK
  • 1,469
  • 2
  • 22
  • 39
  • did you read this https://docs.spring.io/spring-security/reference/5.7.0-RC1/reactive/oauth2/client/authorized-clients.html#oauth2Client-webclient-webflux – Toerktumlare Aug 02 '22 at 18:21
  • I have read the documentation,I'm using OAuth2AuthorizedClientManager, rather than ReactiveOAuth2AuthorizedClientManager, this is the only difference I can see, should it not work with my configuration also? – JTK Aug 09 '22 at 10:33

1 Answers1

0

Aren't you missing .filter(new ServletBearerExchangeFilterFunction())?

ch4mp
  • 6,622
  • 6
  • 29
  • 49
  • Here is an description of why this approach does not work: https://github.com/spring-projects/spring-security/issues/7771 I am using ServletOAuth2AuthorizedClientExchangeFilterFunction as apposed to ServerOAuth2AuthorizedClientExchangeFilterFunction as described in the above issue, but have been unsuccessful so far. – JTK Aug 09 '22 at 13:39
  • Are you in a reactive or srvlet app? did you have a look at https://stackoverflow.com/a/66586903/619830? – ch4mp Aug 10 '22 at 22:32