Search code examples
javaspring-securitypostmancsrf

Why I have to disable csrf token in order to post data using postman?


I'm trying to do some REST calls to my server(localhost), GET methods working properly but, when I try to post JSON objects through postman methods POST, PUT, DELETE not working It says "Request method POST not supported" when I try again disabling csrf tokens on http, everything works well.

Here is my Rest Controller.

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.kish.Service.CustomerService;
import com.kish.entity.Customer;

@RestController
@RequestMapping("/api")
public class CRMRestController {

    public CRMRestController() {

    }

    @Autowired
    private CustomerService customerService;

    @GetMapping("/customers")
    public List<Customer> getCustomers() {


        return customerService.getCustomers();
    }

    @GetMapping("/customers/{customerId}")
    public Customer getCustomer(@PathVariable int customerId) {

        if((customerService.getCustomer(customerId) == null)) {
            throw new CustomerNotFoundException("No customer found in the database" + customerId);
        }

        return customerService.getCustomer(customerId);
    }

    @PostMapping("/customers")
    public Customer addCustomer(@RequestBody Customer customer) {

        customer.setId(0);
        customerService.saveCustomer(customer);

        return customer;

    }

    @PutMapping("/customers")
    public Customer updateCustomer(@RequestBody Customer customer) {

        customerService.saveCustomer(customer);

        return customer;
    }

    @DeleteMapping("/customers/{customerId}")
    public String deleteCustomer(@PathVariable int customerId) {

        if((customerService.getCustomer(customerId)) == null) throw new CustomerNotFoundException("request valid data");

        customerService.deleteCustomer(customerId);

        return "deleted customer id is " + customerId;

    }

}

security config method

 @Override  
        protected void configure(HttpSecurity http) throws Exception {

            http.csrf().disable();
            http.authorizeRequests() // restrict access based on the request coming in.
            .antMatchers("/customer/list").hasRole("EMPLOYEE")
            .antMatchers("/customer/Actions/**").hasAnyRole("ADMIN","MANAGER")
            .and()
            .formLogin()
            .loginPage("/showMyLoginForm")
            .loginProcessingUrl("/authenticateTheUser")  // it checks the 
            .permitAll()
            .and()
            .logout()
            .permitAll()
            .and().exceptionHandling().accessDeniedPage("/access-denied"); // Spring Security uses this page for Access denied pages


        }

So my question is why I have to disable csrf in order to do POST calls but not for GET calls? or did I missing something?


Solution

  • Short answer

    CSRF cares only about actions that can manipulate data; the http verbs used for that are: POST, PUT, PATCH and DELETE. It's not CSRFs job to protect you from requests that intent only to view data: GET, HEAD, OPTIONS, TRACE.

    Long answer

    Spring Security has CSRF enabled by default by implementing the Synchronizer Token Pattern. What does it actually means: when you initiate a session, you will receive a token ( randomly generated ) which needs to be passed every time as an X-XSRF-TOKEN ( or something similar ) header every time when you are making a POST, PUT, PATCH or DELETE request. If the token is not present, or if the token is present but not matched to the one Spring Security has generated you are not allowed to make that request.

    The problem you are encountering right now is because you are not passing the CSRF header with Postman.

    Now, there is the question if you really need CSRF protection? It depends on how you are storing the authentication token in your client(s). I would suggest having a look over CSRF protection and if it is not needed you can just disable it.