1

I have a Spring Boot REST API. Due to a security policy I need to have CSRF protection enabled for endpoints accessed by the browser. However, this API will also be accessed by non-browsers. Is there a way I can create two sets of endpoints, one accessible by browsers only with CSRF enabled and the other accessible by non-browsers only with CSRF disabled?

R. Overbeck
  • 13
  • 1
  • 3

3 Answers3

2

When you configure your CSRF protection using the DSL, like this http.csrf()... you can tell which requests you want the CSRF protection to be applied by passing a RequestMatcher, like so:

http.csrf(csrf -> csrf.requireCsrfProtectionMatcher(new MyBrowserRequestMatcher()));

And your implementation of RequestMatcher could verify if the HttpServletRequest contains the header X-Requested-With: XMLHttpRequest or check the User-Agent.

Just keep in mind that the headers can be changed and you have no guarantee that the request actually come from a browser or non-browser app.

0

I think you could have separate URL bases for the browser requests and API requests.

For example, you could have all the endpoints that are to be queried by non-browsers under /api/... and in your SpringBootSecurityConfiguration class and configure(HttpSecurity http) method you could conditionally disable CSRF with http.csrf().disable(); if the pattern matches (great tutorial can be found here)

Edit: here is another answer that might be useful.

ferrouskid
  • 466
  • 2
  • 7
  • 1
    Thanks for the input. However, wouldn't that non-browser endpoint set still be accessible by browsers? Is there a way I can restrict a given endpoint to one client type or another? – R. Overbeck Mar 18 '22 at 16:18
  • You could set up roles and authorities, and make the API users have different level of security to users that signed up through the browser. Maybe that's a possible approach for you? In the end, a browser is just making the requests on behalf of the user, so in theory there really isn't a difference by type as far as I know, but you could enforce that separation manually. Is your main concern security and ensuring that the browser (end users) don't stumble onto an unsage endpoint? – ferrouskid Mar 18 '22 at 21:00
0

As @ferrouskid said, I created two URL one for browsers and other for non-browsers:

In spring security config:

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.csrf().ignoringAntMatchers("/withoutCsrf/**")
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .cors().disable();
//complete your configuration }

In controller:

@Controller
@RequestMapping({"books","withoutCsrf/books"})
public class BookController {}
Ayoub Anbara
  • 407
  • 5
  • 10