Reputation: 23
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
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
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
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
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