Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix Spring Security Authorization header not being passed?

Tags:

In one of my REST services, I make use of Spring Security to validate the token that is being passed in the header. However, spring is unable to find the "Authorization" header, even though it is there. This was not a problem when testing in test, and even locally but when we deployed to PROD we get this issue.

As an alternative/workaround I removed Spring security and instead tried to do the validation of my token in the actual endpoint before continueing with the rest of the request like such:

@PostMapping(value="/create",consumes="application/json; charset=utf-8")
    @CrossOrigin
    public ResponseEntity createAccount(@RequestBody MerchantAccount merchantAccount,@RequestHeader(name="Authorization") String token) {
        log.info("Checking User Token");
        if(!jwtUtil.isAuthorizedToken(token))
            return ResponseEntity.status(401).build();
//some creating Account Logic
}

If I did the above once again it would work in TEST and on LOCAL but not in PROD. Error that I would get back would be "Missing Authorization header". But yet again it is present. (Tested from postman to).

After some research, I saw that I could add ",required=false" so spring would not check for it, but then still there was no token to extract.

The only difference between PROD and TEST and my local is the following:

Java version java version on test:java version "1.6.0_32"

java version on PROD: java version "1.8.0_121"

java version on local:java version "1.8.0_221"

On Test we use HTTP and PROD it's HTTPS. Spring Security Version in POM file is 5.2

EDIT In my web config I do have a section that allows for the "Authorization" header to be present as seen below.

 @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));//YOLO Allow all origins, we can change this once we go to prod
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH","OPTIONS"));//Allowed Methods
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type","Access-Control-Request-Headers","Access-Control-Request-Method",
               "Accept","Access-Control-Allow-Headers"));//Allowed Headers
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

Update On TEST & LOCAL when I iterate through headers in the request filter (as seen below)

@Component
@Service
public class JwtRequestFilter extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        logger.info("Done Getting Headers");
        Collections.list(request.getHeaderNames()).forEach(item -> logger.info("header name is " + item));
        logger.info("Done Getting Headers");
        boolean isAccessToken = true;
        final String requestTokenHeader = request.getHeader("authorization");//This is null as the Authorization header is not found in request
}

I get the following output. TEST & LOCAL

Working Test

On PROD I get the following:

prod result

Please help.

like image 488
Terblanche Daniel Avatar asked Nov 17 '19 14:11

Terblanche Daniel


1 Answers

After wandering galaxies....

I've fixed it using this:

@Configuration
@EnableWebSecurity
public class Config extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and() /*.other stuff */;
    }
}

Basically you need to enable cors() with the http object.. and then there are multiple ways to handle the cros origin for each controller/method or globally.

My issue was like this:

Whenever I make request from postman it worked & the "Authorization" key in header was always present, debugged it using request filter just like you.

However, each time request made form front end app (react) the browser prevented the"Authorization" key every single time...

To configure it globally:

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry
                  .addMapping("/greeting-javaconfig")
                  .allowedOrigins("http://localhost:8080");
        }
    };
}

Or, controller level,

@CrossOrigin(origins = "http://localhost:8080")
@GetMapping("/greeting")
public String greeting() {
    return "works!";
}

Ref:

SO answer, Spring Official Guide

like image 133
some user Avatar answered Oct 05 '22 23:10

some user