title: Spring Configuring WebClient Oauth2 Authentication with Custom Request
body: <p>I'm having some trouble understanding how to customize an authentication request made using Oauth2 when applying a <code>ServerOAuth2AuthorizedClientExchangeFilterFunction</code> filter on a <code>WebClient.Builder</code> that is used as a base for all <code>WebClient</code> instances.</p>
  <p>The system itself is working, and the request is generated according to Oauth2 specifications. However, my authentication service has some extra fields that need to be present in order for the authentication to work. That's the problem, so far I couldn't find any reasonable way of adding the field that I need or customizing the request itself.</p>
  <p>The only wat I could find so far would be to implement a <code>ReactiveOAuth2AuthorizedClientManager</code>. But I'm quite resistant about doing that, since there is no generic implementation of that interface that I can extend, and all available implementations are <code>final</code> and can't be extended. Since my use case would be only to add a field to the request body, I hope there is a better way of achieving that.</p>
  <p>Any help would be highly appreciated. Thanks for your time.</p>
  <h3>What I want to achieve</h3>
  <ul>
  <li>Add a field to the authentication Oauth2 request, managed by spring security</li>
  </ul>
  <h3>What's getting in the way</h3>
  <ul>
  <li>Couldn't find a way to customize adding custom fields to the authentication request. There is too much voodoo magic happening behind the curtain.</li>
  </ul>
  <h2>Configuration</h2>
  <pre><code>@Configuration
  public class WebClientConfig {
  
      @Bean(&quot;azure&quot;)
      public ReactiveClientRegistrationRepository getRegistration(
              @Value(&quot;${spring.security.oauth2.client.provider.azure.token-uri}&quot;)
              String tokenUri,
              @Value(&quot;${spring.security.oauth2.client.registration.azure.client-id}&quot;)
              String clientId,
              @Value(&quot;${spring.security.oauth2.client.registration.azure.client-secret}&quot;)
              String clientSecret,
              @Value(&quot;${spring.security.oauth2.client.registration.azure.authorization-grant-type}&quot;)
              String authorizationGrantType
      )
      {
          ClientRegistration registration = getClientRegistration(
                  &quot;azure&quot;,
                  tokenUri,
                  clientId,
                  clientSecret,
                  getAuthorizationGrantType(authorizationGrantType)
          );
          return new InMemoryReactiveClientRegistrationRepository(registration);
      }
  
      protected AuthorizationGrantType getAuthorizationGrantType(@Value(&quot;${spring.security.oauth2.client.registration.azure.authorization-grant-type}&quot;) String authorizationGrantType) {
          return new AuthorizationGrantType(authorizationGrantType);
      }
  
      protected ClientRegistration getClientRegistration(
              String registrationId,
              String tokenUri,
              String clientId,
              String clientSecret,
              AuthorizationGrantType authorizationGrantType
      ) {
          return ClientRegistration
                      .withRegistrationId(registrationId)
                      .tokenUri(tokenUri)
                      .clientId(clientId)
                      .clientSecret(clientSecret)
                      .authorizationGrantType(authorizationGrantType)
                      .build();
      }
  
      @Bean
      public ServerOAuth2AuthorizedClientExchangeFilterFunction  oauth2AuthenticationFilter(
              @Qualifier(&quot;azure&quot;) ReactiveClientRegistrationRepository clientRegistrations
      ) {
          ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                  clientRegistrations,
                          new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
          oauth.setDefaultClientRegistrationId(&quot;azure&quot;);
          oauth.setDefaultOAuth2AuthorizedClient(true);
          return oauth;
      }
  
      @Bean(&quot;base&quot;)
      public WebClient.Builder webClientBaseBuilder()
      {
          return WebClient.builder();
      }
  
      @Bean
      @Primary
      public WebClient.Builder webClientBuilderWithFilters(
              @Qualifier(&quot;base&quot;) WebClient.Builder baseBuilder,
              ServerOAuth2AuthorizedClientExchangeFilterFunction  oauth2AuthenticationFilter
      ) {
          return baseBuilder
                  .filter(oauth2AuthenticationFilter);
      }
  
      @Bean
      public WebClient webClient(
              @Value(&quot;${api.appId}&quot;) String appId,
              @Value(&quot;${api.url}&quot;) String url,
              WebClient.Builder builder
      ) {
          return builder
                  .baseUrl(url)
                  .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                  .defaultHeader(&quot;Application-Id&quot;, appId)
                  .build();
      }
  
  }
  </code></pre>