0

I was going to implement protective measures against CSRF attack (using Spring Security) on my already built application. However, I am facing the following issues while designing the approach:

Suppose I have two APIs with following endpoints:

  1. /abc
  2. /xyz

Scenario 1: Front End calls /abc along with csrf token. Server checks the csrf token and passes it if found correct. This is working fine.

Scenario 2: Front End calls /xyz along with csrf token. Server checks the csrf token and passes it if found correct. This again is working fine.

Scenario 3: The API /abc calls the API /xyz internally. However, API /xyz is expecting the CSRF token which only comes from front end and hence /xyz is failing due to no csrf token.

Scenario 4: We also have few third party apps (like payment gateway) that consumes our APIs. How will they pass CSRF token to our APIs?

Basically, I want to protect all our APIs from CSRF attack but I am finding it hard to pass the csrf token from BE to BE and from Payment Gateway to BE. Please help me in finalizing the approach that I should follow so that I can easily cover all these 4 scenarios and protect the application from any CSRF attack.

UPDATING QUESTION WITH CODE SAMPLES

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

    http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .requireCsrfProtectionMatcher(new RequestMatcher() {

                @Override
                public boolean matches(HttpServletRequest request) {

                    final HashSet<String> allowedMethods = new HashSet<String>(
                            Arrays.asList("GET", "HEAD", "TRACE", "OPTIONS"));
                    boolean methodCheck = allowedMethods.contains(request.getMethod());
                    if(methodCheck) {
                        return false;
                    }
                    return true;
                }
            });
}

}

APIs

API 1:

@RestController
public class GetVersion {

@RequestMapping(path="/", method=RequestMethod.GET)
public String getVersion() {
    return "This is a Get Call";
}

}

API 2:

@RestController
public class PostCall2 {
    @RequestMapping(value="/{path}/postcall2",method=RequestMethod.POST)
    public String postCall2(@PathVariable("path") String path) {
        return "This is path: "+path;
    }
}

API 3:

@RestController
public class PostCall1 {

@RequestMapping(path="/{path}/postcall1",method=RequestMethod.POST)
@ResponseBody
public String postCall1(@PathVariable("path") String path) {
    System.out.println("Tring to call /postcall2 from /postcall1");

    final String url = "http://localhost:8080/thisisxyz/postcall2";


    RestTemplate restTemplate = new RestTemplate();
    try {
        String result = restTemplate.postForObject(url, "", String.class);
        System.out.println("Result is: "+result);
        System.out.println("Successfully called /postcall2 from /postcall1");
        return "This is path: "+path;
    }
    catch(HTTPException e) {
        e.printStackTrace();
        return "Failed";
    }
    catch(Exception e) {
        e.printStackTrace();
        return "Failed";
    }
}
}

API 1 and API 2 are working fine as they are being called directly. However, API 3 is trying to internally call API 2 and it is failing because it cannot provide CSRF Token to API 2. Please help.

Akhil Prajapati
  • 1,221
  • 3
  • 14
  • 23
  • 1
    yes....I am using REST API – Akhil Prajapati Mar 29 '19 at 10:15
  • See also: https://stackoverflow.com/questions/48985293/spring-security-stateless-rest-service-and-csrf and https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints – dur Mar 29 '19 at 10:24
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190956/discussion-between-akhil-prajapati-and-dur). – Akhil Prajapati Mar 30 '19 at 11:55

0 Answers0