title: How to provide an OAuth2 token to a Feign client using Spring Security for the client_credentials workflow
body: <h2>Overview</h2>
  <p>I am trying to write a program that accesses a public REST API. In order for me to be able to consume it, I need to provide an OAuth2 token.</p>
  <p>My App uses Spring Boot 2.4.2 and Spring Cloud version 2020.0.1. The app itself does call the REST API once every 24h, download the data, and stores it in a database. A different microservice consumes this data at some other point and needs the data to have been refreshed daily.</p>
  <p>My approach to this is to use OpenFeign to declare the REST Client that consumes the REST API and provide it an OAuth2 token. This is a problem that is quite common, so I assume that machine to machine <code>client_credentials</code> workflow is well documented.</p>
  <p>And indeed, I did find a simple example to do this with OpenFeign - here: <a href="https://github.com/netshoes/sample-feign-oauth2-interceptor/blob/master/src/main/java/com/sample/feign/oauth2/interceptor/OrderFeignClientConfiguration.java" rel="noreferrer">https://github.com/netshoes/sample-feign-oauth2-interceptor/blob/master/src/main/java/com/sample/feign/oauth2/interceptor/OrderFeignClientConfiguration.java</a></p>
  <p><strong>TL;DR:</strong> Trying to write a machine-to-machine microservice requiring an OAuth2 token (client_credentials grant type).</p>
  <h2>Problem</h2>
  <p>This was my first try, but unfortunately with the new Spring Security release, I can't seem to get the <code>OAuth2FeignRequestInterceptor</code> instantiated, I might have a package problem. I then went on to study the documentation for Spring Security and the new OAuth2 rewrite, which can be found here: <a href="https://docs.spring.io/spring-security/site/docs/5.1.2.RELEASE/reference/htmlsingle/#oauth2client" rel="noreferrer">https://docs.spring.io/spring-security/site/docs/5.1.2.RELEASE/reference/htmlsingle/#oauth2client</a>.</p>
  <h2>Approaches</h2>
  <p>My approach is to use a <code>RequestInterceptor</code> which injects the current OAuth2 token into the request of the OpenFeign client, by adding an Authorization Bearer header. My assumption is that I can retrieve this, more or less automagically, using the Spring Security OAuth2 layer.</p>
  <p>Using the documentation I tried providing a bean of <code>OAuth2RegisteredClient</code> to my interceptor, as well as a bean of type <code>OAuth2AccessToken</code> - which both didn't work. My last try looked like this and is to be seen, as a sort of hail mary, kind of approach:</p>
  <pre class="lang-java prettyprint-override"><code>    @Bean
      public OAuth2AccessToken apiAccessToken(
              @RegisteredOAuth2AuthorizedClient(&quot;MY_AWESOME_PROVIDER&quot;) OAuth2AuthorizedClient authorizedClient) {
          return authorizedClient.getAccessToken();
      }
  </code></pre>
  <p>This doesn't work because <code>RegisteredOAuth2AuthorizedClient</code> requires a user session, lest it is <code>null</code>. I also saw someone else on Stackoverflow trying the same approach, but they actually did it in a <code>Controller</code> (=&gt; <a href="https://stackoverflow.com/questions/57907747/resolving-oauth2authorizedclient-as-a-spring-bean">Resolving OAuth2AuthorizedClient as a Spring bean</a>)</p>
  <p>I also tried some approaches that I have found here on SO:</p>
  <ul>
  <li><a href="https://stackoverflow.com/questions/63283022/feign-and-spring-security-5-client-credentials">Feign and Spring Security 5 - Client Credentials</a> (Provided answer uses Spring Boot 2.2.4 - thus not relevant anymore)</li>
  <li><a href="https://stackoverflow.com/questions/66091706/alternative-for-oauth2feignrequestinterceptor-as-it-is-deprecated-now">Alternative For OAuth2FeignRequestInterceptor as it is deprecated NOW</a> another gentleman looking for an alternative for <code>OAuth2FeignRequestInterceptor</code></li>
  <li><a href="https://stackoverflow.com/questions/62448111/oauth2feignrequestinterceptor-class-deprecated-in-spring-boot-2-3">OAuth2FeignRequestInterceptor class deprecated in Spring Boot 2.3</a> - solution here again required an active user-session</li>
  <li><a href="https://github.com/jgrandja/spring-security-oauth-5-2-migrate" rel="noreferrer">https://github.com/jgrandja/spring-security-oauth-5-2-migrate</a> this Github repo pops up every now and then, I studied it, but I deem it irrelevant to my question - maybe I missed something? From what I understood, this sample application has multiple providers using multiple scopes - but still a user that triggers a login and thus the automagic generation of an OAuth2 token through Spring Security. (also featured in this question: <a href="https://stackoverflow.com/questions/60874507/migrating-from-spring-boot-oauth2-to-spring-security-5">Migrating from Spring Boot Oauth2 to Spring Security 5</a>) [1]</li>
  <li><a href="https://github.com/spring-cloud/spring-cloud-openfeign/issues/417" rel="noreferrer">https://github.com/spring-cloud/spring-cloud-openfeign/issues/417</a> -&gt; as of right now there is no replacement for <code>OAuth2FeignRequestInterceptor</code></li>
  </ul>
  <p>My assumption is that I can somehow use Spring Security 5 to solve this, but I simply can't wrap my head around how to actually do it. It seems to me that most of the tutorials and code samples I have found actually require a user-session, or are outdated with Spring Security 5.</p>
  <p>It really seems that I am missing something and I hope that somebody can point me in the right direction, towards a tutorial or written documentation on how to achieve this.</p>
  <h3>In depth example</h3>
  <p>I tried supplying an <code>OAuth2AuthorizedClientManager</code> as seen in this example (<a href="https://github.com/jgrandja/spring-security-oauth-5-2-migrate" rel="noreferrer">https://github.com/jgrandja/spring-security-oauth-5-2-migrate</a>).
  For this, I registered an <code>OAuth2AuthorizedClientManager</code> following the example code:</p>
  <pre class="lang-java prettyprint-override"><code>    @Bean
      public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository,
                                                                   OAuth2AuthorizedClientRepository authorizedClientRepository) {
          OAuth2AuthorizedClientProvider authorizedClientProvider =
                  OAuth2AuthorizedClientProviderBuilder.builder()
                          .authorizationCode()
                          .refreshToken()
                          .clientCredentials()
                          .password()
                          .build();
          DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
                  clientRegistrationRepository, authorizedClientRepository);
          authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  
          return authorizedClientManager;
      }
  </code></pre>
  <p>and provided it for my <code>RequestInterceptor</code> as can be seen here:</p>
  <pre class="lang-java prettyprint-override"><code>    @Bean
      public RequestInterceptor requestInterceptor(OAuth2AuthorizedClientManager clientManager) {
          return new OAuthRequestInterceptor(clientManager);
      }
  </code></pre>
  <p>Finally I wrote the interceptor, which looks like this:</p>
  <pre class="lang-java prettyprint-override"><code>    private String getAccessToken() {
          OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest.withClientRegistrationId(appClientId)
                  // .principal(appClientId) // if this is not set, I receive &quot;principal cannot be null&quot; (or empty)
                  .build();
          return Optional.ofNullable(authorizedClientManager)
                  .map(clientManager -&gt; clientManager.authorize(request))
                  .map(OAuth2AuthorizedClient::getAccessToken)
                  .map(AbstractOAuth2Token::getTokenValue)
                  .orElseThrow(OAuth2AccessTokenRetrievalException::failureToRetrieve);
      }
  
      @Override
      public void apply(RequestTemplate template) {
          log.debug(&quot;FeignClientInterceptor -&gt; apply CALLED&quot;);
          String token = getAccessToken();
          if (token != null) {
              String bearerString = String.format(&quot;%s %s&quot;, BEARER, token);
              template.header(HttpHeaders.AUTHORIZATION, bearerString);
              log.debug(&quot;set the template header to this bearer string: {}&quot;, bearerString);
          } else {
              log.error(&quot;No bearer string.&quot;);
          }
      }
  </code></pre>
  <p>When I run the code, I can see &quot;FeignClientInterceptor -&gt; apply called&quot; output in the console, followed by an Exception:</p>
  <blockquote>
  <p><code>Caused by: java.lang.IllegalArgumentException: servletRequest cannot be null</code></p>
  </blockquote>
  <p>My assumption is that I receive this, because I don't have an active user session. It seems to me thus, that I absolutely need one to fix this problem - which I don't have in machine-to-machine communcations.</p>
  <p>This is a common use-case so I am sure I must have made a mistake at some point.</p>
  <h2>Used packages</h2>
  <p>Maybe I made a mistake with my packages?</p>
  <pre class="lang-gradle prettyprint-override"><code>    implementation 'org.springframework.boot:spring-boot-starter-amqp'
      implementation 'org.springframework.boot:spring-boot-starter-jooq'
      implementation 'org.springframework.boot:spring-boot-starter-security'
      implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
      implementation 'org.springframework.boot:spring-boot-starter-web'
      implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
  </code></pre>