Search code examples
javaspring-securityspring-boot

Spring Security bypass URL or Filter


I have a Spring Boot application that is only exposing a REST API. I need to secure it and I'm using a token-based approach ― specifically JWT.

So far, this is what I have implemented:

//
// The Spring Security configuration class
@EnableGlobalAuthentication
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(final HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeRequests()
          .antMatchers("/api/login", "/api/logout").permitAll()
          .antMatchers("/api/**").authenticated()
          .anyRequest().authenticated()
        .and()
          .addFilterBefore(new JwtFilter(), BasicAuthenticationFilter.class)
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }
}

//
// The JWT filter class to check for the token in the HTTP request (headers)
public final class JwtFilter extends GenericFilterBean {
  private final Logger logger = LoggerFactory.getLogger(this.getClass());

  @Override
  public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws
      IOException, ServletException {
    final HttpServletRequest req = (HttpServletRequest)request;
    final String header = req.getHeader("Authorization");

    logger.debug("{} {}", req.getMethod(), req.getRequestURI());
    if ((null == header) || !header.startsWith("Bearer ")) {
      logger.debug("Missing or invalid Authorization header");
    }
    try {
      // Check the token here; the implementation is not relevant here
      /*SecurityContextHolder.getContext()
          .setAuthentication(manager.authenticate(new JwtToken(JWTParser.parse(header.substring(7)))));*/
      chain.doFilter(request, response);
    } catch (final AuthenticationException e) {
      SecurityContextHolder.clearContext();
      // Do some other stuff here
    } catch (final ParseException e) { /* ... */ }
  }
}

The issue is that the filter executes correctly for every single URI, but I want to be able to exclude some endpoints from the same set. My API is placed in this context /api/* and I want to exclude, for instance, /api/login and /api/logout.

NOTE: My Spring Boot application.yml file doesn't have settings to enable/modify any security-related features.


Solution

  • Filters will be executed for all the endpoints that are configured through HttpSecurity. If you do not want filters to be applied for certain endpoints, include them in a method that configures WebSecurity. For example,

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
          .ignoring()
            .antMatchers("/api/login", "/api/logout");
    }
    

    Please read this post for more details.