简体   繁体   中英

How to fix Spring Security Authorization header not being passed?

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

工作测试

On PROD I get the following:

产品结果

Please help.

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

Possible Issue:

  • Set Authorization in exposed headers,allowed headers list
  • Set OPTIONS method in setAllowedMethods

When using Spring Security with Spring web flux , I had to use the following config to make it work: -

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@EnableWebFluxSecurity
public class WebSecurityConfig {

  @Bean
  public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

    http.cors().and()
        .csrf().disable()
        .authorizeExchange()
        .pathMatchers("/**").permitAll()
        .anyExchange()
        .authenticated()
        .and()
        ... //more mappings 

    return http.build();
  }

  @Bean
  CorsConfigurationSource corsConfiguration() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.applyPermitDefaultValues();
    UrlBasedCorsConfigurationSource source =
        new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);
    return source;
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM