Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot 2: Basic Http Auth causes unprotected endpoints to respond with 401 "Unauthorized" if Authorization header is attached

After migration to Spring Boot 2 and adding basic authorization requirement for actuator and another application controlling endpoint it became impossible to call any unprotected endpoint with Authorization header.

Configuration snippet:

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("shutdown")).fullyAuthenticated()
            .antMatchers("/payment/status/*").fullyAuthenticated()
            .and().httpBasic();
}

E.g. call to .../health with "Authorization: Basic ..." will cause 401 "Unauthorized" even though it is not protected by spring security.

Question: How can i adjust the configuration so that it is possible to send request with Authorization header to any unprotected endpoint without being denied?

UPD: This fix worked as i wanted

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("shutdown")).fullyAuthenticated()
            .antMatchers("/payment/status/*").fullyAuthenticated()
            .antMatchers("/payment/**").permitAll()
            .and().httpBasic();
}

UPD2: Nevermind, just tested another request and still receive 401 "Unauthorized".

curl localhost:8080/payment/<any_endpoint> -H "Authorization: Basic asdadas"
{"code":401,"message":"Unauthorized"}

This approach unfortunately overrides HttpSecurity matchers, e.g.: /payment/ becomes accessible

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("shutdown")).fullyAuthenticated()
            .antMatchers("/payment/status/*").fullyAuthenticated()
            .and().httpBasic();
}

@Override
public void configure(WebSecurity webSecurity) throws Exception {
    webSecurity.ignoring().antMatchers("/payment/**");
}

UPD 3: I've created a simple project with this issue being reproduced https://github.com/Anoobizzz/SpringSecurity2BasicAuthDemo

  1. /internal & /shutdown are only accessible with user:P455W0RD
  2. /exposed accessible without authorization
  3. /exposed with header "Authorization: Basic 123123" responds with 401 "Unauthorized"
like image 787
Anoobizzz Avatar asked Jul 24 '18 10:07

Anoobizzz


1 Answers

By calling .authorizeRequests() , you enforce authorization of all these requests because you've not called .ignore() on some matcher.

I suggest to use ignore on a ** matcher and then incrementally enforce authorization on specified matchers ontop of the permit-all layer so that everything is accessible except of the ones explicitly specified.

This accomplishes what you want to do but beware, it's not a best practise for a very good reason: You should deny all unauthorized traffic by default and only explicitly permit unauthorized requests for specific route templates.

That said, it would be wiser to just use ignore explicitly on the routes you want to be accessible without authentication, not just ** (for example only for /home - /about - /login - /signup)

like image 160
ntakouris Avatar answered Nov 07 '22 18:11

ntakouris