How to implement OAuth2 “Token Exchange” with Spring Cloud Security

旧巷老猫 提交于 2019-12-03 02:14:36

I'm curious why you'd need to "exchange" the token for making calls from Microservice A to Microservice B and why relaying is not sufficient? What are your trying to achieve by exchanging tokens for inter-service requests?

We have a set up very similar to what is described in this Nordic APIs entry. The short version is that external callers use an opaque token, but once the request goes through our gateway, every microservice gets a JWT representation of the same token. We had to implement a custom endpoint to to perform the opaque to JWT exchange. When services need to interact with one another, we do not exchange the token when A needs to call B, we simply relay the token. Either the RestTemplate or Feign client will automatically forward the token from A to B. Thus, context is not lost.

Now, if we wanted to control access, the JWT could specify a collection of audience values or we could enforce access via scopes. We are actually doing a combination of the two depending on the use case.

Exchanging tokens is not a cheap operation, in fact it's quite expensive at scale and should really consider why you need to do a token exchange for intra-service communication. If you every API request is going result in service A calling service B and you have to make a token exchange, you're going to have ensure that your authorization service can handle that type of workload. Lastly, the IETF token exchange is still draft status, and has changed quite a bit in its evolution, so I would not expect much in the way of implementation advice until the spec gets closer to finalization.

I think this is something you might try.

In my project we also use OAuth2, Eureka, Ribbon for microservices to communicate each other. In order to use Ribbon with OAuth2, the approach we took was bit different.

First we leave the restTemplate untouched.

  @LoadBalanced
  @Bean
  public RestTemplate restTemplate() {

However, we created FeignClientIntercepter implementing RequestIntercepter which sets authorization tokens for OAuth when making a request via restTemplate.

  @Component
  public class FeignClientInterceptor implements RequestInterceptor {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_TOKEN_TYPE = "Jwt";

    @Override
    public void apply(RequestTemplate template) {
      SecurityContext securityContext = SecurityContextHolder.getContext();
      Authentication authentication = securityContext.getAuthentication();

      if (authentication != null && authentication
          .getDetails() instanceof OAuth2AuthenticationDetails) {
        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication
          .getDetails();
        template.header(AUTHORIZATION_HEADER,
            String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));
      }
    }
  }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!