'Spring Cloud Gateway with Custom Auth Server client credentials flow with WebClient

I followed this blog How can I use client_credentials to access another oauth2 resource from a resource server? to create a WebClient which will request for token and forward it downstream to another resource server. This seems to be working fine because the code shows that it is using the WebClient.

Now, I have a Spring Cloud Gateway which would like to do that and request a token and forward it downstream to a resource server.

I have the following configuration below.

@EnableWebFluxSecurity
public class WebClientConfig {

  @Bean
  public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
      ReactiveClientRegistrationRepository clientRegistrationRepository,
      ReactiveOAuth2AuthorizedClientService authorizedClientService) {

    ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
        ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
            .clientCredentials()
            .build();

    AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
        new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
            clientRegistrationRepository, authorizedClientService);

    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    return authorizedClientManager;
  }

  @Bean
  public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
    String registrationId = "custom";

    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
        authorizedClientManager);

    oauth.setDefaultClientRegistrationId(registrationId);
    return WebClient.builder()
        .baseUrl("http://localhost:8888")
        .filter(oauth).build();
  }

  @Bean
  public SecurityWebFilterChain configure(ServerHttpSecurity http) {
    return http
        .oauth2Client()
        .and()
        .build();
  }
}

My application.yml is below

server:
  port: 8081
spring:
  security:
    oauth2:
      client:
        provider:
          custom:
            token-uri: http://localhost:8080/oauth/token
        registration:
          custom:
            client-id: campaign-station-client
            client-secret: password
            scope: "*"
            authorization-grant-type: client_credentials
  cloud:
    gateway:
      routes:
        - id: resource_server_id
          uri: http://localhost:8888/
          predicates:
            - Path=/resourceserver/**
          filters:
            - RewritePath=/resourceserver/(?<segment>.*), /$\{segment}

When i call my resource server endpoint via the gateway, the gateway does not use the WebClient to retrieve the access token (eg client_credentials flow). How can i make use of this WebClient for every call to the gateway in order to forward the token downstream to the resource server?



Solution 1:[1]

You need to write a custom filter and you can pass the token from there .Look at the code for TokenGatewayFilter . That will give you a better idea. I have implemented the same .

Solution 2:[2]

That was worked for me

@Autowired
private TokenRelayGatewayFilterFactory filterFactory;

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
   return builder.routes()
        .route("resource", r -> r.path("/resource")
                .filters(f -> f.filter(filterFactory.apply()))
                .uri("http://localhost:9000"))
        .build();
}

ref: https://cloud.spring.io/spring-cloud-static/Greenwich.RELEASE/multi/multi__more_detail.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user16496586
Solution 2 Grissom lau