Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security .permitAll() no longer effective after upgrading to Spring Boot 2.0.2

I work with a web app that exposes a REST API to mobile apps. I upgraded my Spring Boot version from 1.5.3.RELEASE to 2.0.2.RELEASE and after fixing a few breaking changes I am facing one that I cannot solve.

I followed this Spring Boot 2.0 Migration Guide and Spring Boot Security 2.0 and also looked into Security changes in Spring Boot 2.0 M4.

The issue is that the app uses JWT authentication and there is an endpoint (/auth/login) accepts user credentials and generates a long-lived JWT in return.

There is a filter that examines the JWT token sent by the client and determines whether the client can access the requested resource.

Custom security config is like this:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfiguration {

@Configuration
@Order(1)
public class AuthenticationConfiguration extends WebSecurityConfigurerAdapter {

    // Some dependencies omitted

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // we don't need CSRF because JWT token is invulnerable
                .csrf().disable()

                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()

                // don't create session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers(HttpMethod.GET, "/version/**").permitAll()
                // Some more antMatchers() lines omitted
                .antMatchers("/auth/**").permitAll()
                .anyRequest().authenticated();

        // Custom JWT based security filter
        httpSecurity
                .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);

        // disable page caching
        httpSecurity.headers().cacheControl();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter(jwtTokenUtil);
    }
}

@Configuration
@Order(2)
public class ClientVersionSupportConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
                .addInterceptor(versionCheckingFilter())
                .addPathPatterns("/**")
                .excludePathPatterns("/error"); // Some more endpoints omitted
    }

    @Bean
    public VersionCheckingInterceptor versionCheckingFilter() {
        return new VersionCheckingInterceptor();
    }
}

}

Note the .antMatchers("/auth/**").permitAll() line. /auth endpoints should be accessible without JWT since the JWT has not yet been generated when the user has not yet logged in.

Before upgrading Spring Boot, it worked fine, now it is not working. Login attemps are rejected by the filter that checks the JWT. Looks like .permitAll() is not making the requests pass through. /version/** does not work either. Hitting it from the browser gives an error page.

I also tried to delete lines from the config until this remained:

httpSecurity
        .authorizeRequests()
                .antMatchers("/auth/**").permitAll()

It did not help. Could you please help with restoring the original behavior?

like image 242
Andras Szoke Avatar asked Jun 11 '18 08:06

Andras Szoke


1 Answers

Do you have a base path for you api, e.g. /api ?

The server.contextPath default Spring property name has changed to server.servlet.context-path.

So if you use a default base path for you api, you won't find the endpoints where you expect them. Unless you update the property ;)

like image 117
vargen_ Avatar answered Oct 30 '22 18:10

vargen_