Spring Security, Stateless REST service and CSRF

14,518

Solution 1

To answer your first question, in the context that you describe, you do not need CSRF protection. The background of CSRF protection is to ensure that the user is not tricked into doing some unwanted action.

For example, in pure theory, you could have logged into a bank's website (and thus established a session) and then went to some shady website. This site could have a form making a POST request to the bank's APIs. Because you have a session there, if the endpoint is not CSRF protected, then the request may go through.

As such, CSRF mostly acts as a protection against browser + session based attacks. If you expose a pure REST API with e.g. OAuth protection, then I don't see any reason for CSRF.

As you use spring boot, you could also disable CSRF using the application.properties / application.yaml configuration file.

security.enable-csrf=false

You can check out the Common Application Properties documentation page for more out-of-the-box configuration options.

Solution 2

If you want to disable csrf in more proper way you can call it like this(if using java configuration)

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().fullyAuthenticated()
            .and().httpBasic();
       .and()
            .csrf()
            .disable()
Share:
14,518
robjwilkins
Author by

robjwilkins

Software Developer. Financial Services. Scotland.

Updated on June 07, 2022

Comments

  • robjwilkins
    robjwilkins almost 2 years

    I have a REST service, built using Java, Spring-boot and using Spring Security with Basic Access Authentication. There are no Views, no JSP etc, no 'login', just stateless services which can be called from a React app hosted separately.

    I've read a variety of documentation about CSRF protection, but can't decide whether I should be using spring-security CSRF config, or just disabling it? If I disable the csrf protection I can call the service with curl using my basic auth like this:

    curl -H "authorization:Basic c35sdfsdfjpzYzB0dDFzaHA=" -H "content-type:application/json" -d '{"username":"user","password":"password","roles":"USER"}' localhost:8081/api/v1/user
    

    If I enable the csrf protection and provide a x-csrf-token header, then the spring CsrfFilter attempts to cross check this against a value from (I think) a session cookie in the HttpServletRequest. However since its a stateless REST service I don't have a session, and haven't 'logged in'.

    I have a config class which looks like this:

    @EnableWebSecurity
    @Configuration
    public class ServiceSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .anyRequest().fullyAuthenticated()
                    .and().httpBasic();
            if (!serviceProperties.isCsrfEnabled()) {
                http.csrf().disable();
            }
        }
    

    The more I think about it, the more it seems that I will just need to disable CSRF protection. Is there another way to configure spring security so it will work?

    thanks

  • robjwilkins
    robjwilkins about 6 years
    The services will be called from a React app hosted separately, but the intention is for the service calls it makes to be stateless. I'll update the question. thanks for the answer
  • Osmund Francis
    Osmund Francis almost 3 years
  • Khanna111
    Khanna111 almost 3 years
    If you are using a browser, then you need CSRF protection in cases when you store the credentials in local or session storage in the browser. Note you are not using cookies but still. So I'm not sure this is a correct answer. See: stackoverflow.com/questions/21357182/…
  • Serban Petrescu
    Serban Petrescu almost 3 years
    This answer is actually in line with the one that you linked. As described there, stateless auth does not need CSRF. It is indeed vulnerable to XSS (which is a different vulnerability). The only way in which basic auth would be vulnerable to CSRF is if the browser would remember the username and password for you. As this question is about a rest API, called from a separately hoated SPA. The basic auth header is added via JS code to the fetch call and not entered in the browser's basic auth prompt (because the SPA is hosted separately e.g. on a CDN and not in the Spring app as a static asset).