Feign and Spring Security 5 – Client Credentials

For this to work with Spring Security 5 and Feign you need to have

  • a working Spring Security config
  • a Feign interceptor
  • a Feign configuration using that interceptor
  1. Working Spring Security Config

Here we will register a generic internal-api client for your oauth2 client credentials. This is where you specify the client-id,client-secret, scopes and grant type.
All basic Spring Security 5 stuff. This also involves setting up a provider (here I am using a custom OpenID Connect provider called “yourprovider”

spring:
  security:
    oauth2:
      client:
        registration:
          internal-api:
            provider: yourprovider
            client-id: x
            client-secret: y
            scope:
              - ROLE_ADMIN
            authorization-grant-type: client_credentials
        provider:
          yourprovider:
            issuer-uri: yourprovider.issuer-uri
      resourceserver:
        jwt:
          issuer-uri: yourprovider.issuer-uri

Next you need your feign config. This will use a OAuth2FeignRequestInterceptor

public class ServiceToServiceFeignConfiguration extends AbstractFeignConfiguration {

    @Bean
    public OAuth2FeignRequestInterceptor requestInterceptor() {
        return new OAuth2FeignRequestInterceptor(
                OAuth2AuthorizeRequest.withClientRegistrationId("internal-api")
                        .principal(new AnonymousAuthenticationToken("feignClient", "feignClient", createAuthorityList("ROLE_ANONYMOUS")))
                        .build());
    }
}

And a RequestInterceptor that looks like this :

The OAuth2AuthorizedClientManager is a bean that you can configure in your Configuration

public OAuth2AuthorizedClientManager authorizedClientManager(final ClientRegistrationRepository clientRegistrationRepository, final OAuth2AuthorizedClientService authorizedClientService) {
    return new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
}

The OAuth2AuthorizeRequest is provided by the Feign Configuration above.
The oAuth2AuthorizedClientManager can authorize the oAuth2AuthorizeRequest, get you the access token, and provide it as an Authorization header to the underlying service

public class OAuth2FeignRequestInterceptor implements RequestInterceptor {

    @Inject
    private OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager;

    private OAuth2AuthorizeRequest oAuth2AuthorizeRequest;

    OAuth2FeignRequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest) {
        this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest;
    }

    @Override
    public void apply(RequestTemplate template) {
        template.header(AUTHORIZATION,getAuthorizationToken());
    }

    private String getAuthorizationToken() {
        final OAuth2AccessToken accessToken = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest).getAccessToken();
        return String.format("%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue());
    }

}

Leave a Comment