How to get bearer token from header of a request in java spring boot?

We Are Going To Discuss About How to get bearer token from header of a request in java spring boot?. So lets Start this Java Article.

How to get bearer token from header of a request in java spring boot?

Advertisements
  1. How to get bearer token from header of a request in java spring boot?

    Although the suggested answers work, passing the token each time to FeignClient calls still not the best way to do it.
    I would suggest to create an interceptor for feign requests and there you can extract the token from RequestContextHolder and add it to request header directly.

  2. bearer token from header of a request in java spring boot

    Although the suggested answers work, passing the token each time to FeignClient calls still not the best way to do it.
    I would suggest to create an interceptor for feign requests and there you can extract the token from RequestContextHolder and add it to request header directly.

Solution 1

Advertisements

Although the suggested answers work, passing the token each time to FeignClient calls still not the best way to do it.
I would suggest to create an interceptor for feign requests and there you can extract the token from RequestContextHolder and add it to request header directly.
like this:

    @Component
    public class FeignClientInterceptor implements RequestInterceptor {
    
      private static final String AUTHORIZATION_HEADER = "Authorization";

      public static String getBearerTokenHeader() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("Authorization");
      }
    
      @Override
      public void apply(RequestTemplate requestTemplate) {

          requestTemplate.header(AUTHORIZATION_HEADER, getBearerTokenHeader());
       
      }
    }

this way you have a clean solution for your issue

Original Author Of This Content

Solution 2

Advertisements

You have several options here.

For example, you can use a request scoped bean and, as you suggest, one MVC interceptor.

Basically, you need to define a wrapper for the token value:

public class BearerTokenWrapper {
   private String token;

   // setters and getters
}

Then, provide an implementation of an MVC HandlerInterceptor:

public class BearerTokenInterceptor extends HandlerInterceptorAdapter {

  private BearerTokenWrapper tokenWrapper;

  public BearerTokenInterceptor(BearerTokenWrapper tokenWrapper) {
    this.tokenWrapper = tokenWrapper;
  }

  @Override
  public boolean preHandle(HttpServletRequest request,
          HttpServletResponse response, Object handler) throws Exception {
    final String authorizationHeaderValue = request.getHeader("Authorization");
    if (authorizationHeaderValue != null && authorizationHeaderValue.startsWith("Bearer")) {
      String token = authorizationHeaderValue.substring(7, authorizationHeaderValue.length());
      tokenWrapper.setToken(token);
    }
    
    return true;
  }
}

This interceptor should be registered in your MVC configuration. For instance:

@EnableWebMvc
@Configuration
public class WebConfiguration extends WebConfigurer { /* or WebMvcConfigurerAdapter for Spring 4 */

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(bearerTokenInterceptor());
  }

  @Bean
  public BearerTokenInterceptor bearerTokenInterceptor() {
      return new BearerTokenInterceptor(bearerTokenWrapper());
  }

  @Bean
  @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
  public BearerTokenWrapper bearerTokenWrapper() {
    return new BearerTokenWrapper();
  }

}

With this setup, you can use the bean in your Service autowiring the corresponding bean:

@Autowired
private BearerTokenWrapper tokenWrapper;

//...


public TransDeliveryPlanning save(InputRequest<TransDeliveryPlanningDto> request) {
       Future<List<PartnerDto>> initPartners = execs.submit(getDataFromAccount(transDeliveryPlanningDtSoDtoPartnerIdsSets));

}

public Callable<List<PartnerDto>> getDataFromAccount(Set<Long> ids) {

    String tokenString = tokenWrapper.getToken();
    List<PartnerDto> partnerDtoResponse = accountFeignClient.getData("Bearer " + tokenString, ids);
    
    return () -> partnerDtoResponse;
}

Similar solutions has been provided here in stack overflow. See, for instance, this related question.

In addition to this Spring based approach, you can try something similar to the solution exposed in this other stackoverflow question.

Honestly I have never tested it, but it seems that you can provide the request header value right in the Feign client definition, in your case something like:

@FeignClient(name="AccountFeignClient")
public interface AccountFeignClient {    
    @RequestMapping(method = RequestMethod.GET, value = "/data")
    List<PartnerDto> getData(@RequestHeader("Authorization") String token, Set<Long> ids);
}

Of course, you can also a common Controller that other Controllers can extend. This Controller will provide the logic necessary to obtain the bearer token from the Authorization header and the HTTP request provided, but in my opinion any of the aforementioned solutions are better.

Original Author Of This Content

Solution 3

Advertisements

I had a similar case. I was intercepting the requests from one microservice, getting the token and setting it my new ApiClient and calling endpoint from another microservice using this ApiClient. But I really don’t know if there is possibility to pre-configure feign client. One thing that you can do is to create DefaultApiFilter, intercept the request, save the token in your database (or set it to some static variable, some singleton class or something similar) and then call in it your service method when trying to use the FeignClient:

package com.north.config;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Component
public class DefaultApiFilter implements Filter {


@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) servletRequest;

    String auth = req.getHeader("Authorization");

    //TODO if you want you can persist your token here and use it on other place

    //TODO This may be used for verification if it comes from the right endpoint and if you should save the token
    final String requestURI = ((RequestFacade) servletRequest).getRequestURI();

    filterChain.doFilter(servletRequest, servletResponse);
    }
}

This doFilter method will always be executed before any endpoint is called, and later the endpoint will be called.

And later use it when calling the accountFeignClient.getData("Bearer " + tokenString, ids); you can get it from your database (or from any other place that you kept it) and set it here.

Original Author Of This Content

Solution 4

Advertisements

i got the answer but i think there i will still wait for better option, since my answer here is i have to add @RequestHeader in every controller to get the value of my token and get the token with String token = headers.getFirst(HttpHeaders.AUTHORIZATION);, and here is my complete controller :

@Operation(summary = "Save new")
@PostMapping("/store")
public ResponseEntity<ResponseRequest<TransDeliveryPlanning>> saveNewTransDeliveryPlanning(@RequestHeader HttpHeaders headers, 
        @Valid @RequestBody InputRequest<TransDeliveryPlanningDto> request) {

    String token = headers.getFirst(HttpHeaders.AUTHORIZATION);

    TransDeliveryPlanning newTransDeliveryPlanning = transDeliveryPlanningService.save(token, request);

    ResponseRequest<TransDeliveryPlanning> response = new ResponseRequest<TransDeliveryPlanning>();

    if (newTransDeliveryPlanning != null) {
        response.setMessage(PESAN_SIMPAN_BERHASIL);
        response.setData(newTransDeliveryPlanning);
    } else {
        response.setMessage(PESAN_SIMPAN_GAGAL);
    }

    return ResponseEntity.ok(response);
}

and i read somewhere there is something called Interceptor so we don’t have to type @RequestHeader in every controller i think, but i dunno if that the solution or how to use it properly. if someone can do this with something better, i will accept yours as answer

Original Author Of This Content

Conclusion

So This is all About This Tutorial. Hope This Tutorial Helped You. Thank You.

Also Read,

Siddharth

I am an Information Technology Engineer. I have Completed my MCA And I have 4 Year Plus Experience, I am a web developer with knowledge of multiple back-end platforms Like PHP, Node.js, Python and frontend JavaScript frameworks Like Angular, React, and Vue.

Leave a Comment