R. Overbeck
R. Overbeck

Reputation: 23

Spring Boot REST API - enable / disable CSRF protection by client type (browser / non-browser)?

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?

Upvotes: 2

Views: 7243

Answers (4)

Anish Poladi
Anish Poladi

Reputation: 11

Since relying on request headers may not accurately identify the source of requests, creating separate service urls, one for browser and one for non browser clients and disabling CSRF protection for non browser service can also be considered as a solution.

CSRF protection for specific URLs can be disabled while creating SecurityFilterChain.

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    httpSecurity.csrf((csrf) -> csrf.ignoringRequestMatchers("/trade/item/nxtitems", "/trade/item/**")).build();
}

Upvotes: 0

Ayoub Anbara
Ayoub Anbara

Reputation: 473

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 {}

Upvotes: 0

Marcus Hert da Coregio
Marcus Hert da Coregio

Reputation: 6258

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.

Upvotes: 4

ferrouskid
ferrouskid

Reputation: 661

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.

Upvotes: 0

Related Questions