2

I have a spring boot REST Service which offers some methods. They are protected by CSRF and Username / Password Basic Auth (https).

But when I try to do a POST Request it fails with Status Code 403 and Message "Could not verify the provided CSRF token because your session was not found"

That's my client code:

    ApiMessage msg = new ApiMessage("Client1", "Key1", "Value1");

    // Set up Basic Authentication
    HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder()
            .nonPreemptive()
            .credentials(ApiUser, ApiUserPassword)
            .build();
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.register(feature);
    Client client = ClientBuilder.newClient(clientConfig);

    // Set up client and target (ApiHost = URI for the request Ressource)
    WebTarget target = client.target(ApiHost);
    WebTarget checkTarget = target.path("check");
    Invocation.Builder invocationBuilder = checkTarget.request(MediaType.APPLICATION_JSON);

    // Do a first request to get the CSRF Header
    Response response = invocationBuilder.post(Entity.entity(msg, MediaType.APPLICATION_JSON));

    if (response.getStatus() == 200) {

        System.out.println("Without CSRF - everything worked. ");

    } else if (response.getStatus() == 403) {

        System.out.println("CSRF Protection: " + response.getStatus() + response.readEntity(String.class));

        // Get CSRF Token out of the response
        Map<String, NewCookie> cookies = response.getCookies();
        String csrf = cookies.get("XSRF-TOKEN").getValue();

        // Add the Token to the header and POST again
        invocationBuilder.header("X-XSRF-TOKEN", csrf);
        response = invocationBuilder.post(Entity.entity(msg, MediaType.APPLICATION_JSON));

        if (response.getStatus() != 200) {
            System.out.println("Error: " + response.getStatus() + response.readEntity(String.class));
        } else {
            System.out.println("With CSRF - everything worked. ");
        }
    } else {
        System.out.println(response.getStatus() + " " + response.readEntity(String.class));
    }

The first request ends with Status 403 and message "Could not verify the provided CSRF token because your session was not found". After that I extract the CSRF Token successful out of the response header. But the second request with CSRF header fails with the same error.

Doing the same in Postman works fine.

Any ideas where is my mistake and what I am doing wrong?

Daniel Pomrehn
  • 791
  • 3
  • 8
  • 23

1 Answers1

0

There's probably a session cookie you also need to send back, like JSESSIONID. Get that cookie. From the NewCookie you create a Cookie and add it to the request

NewCookie session = cookies.get("JSESSIONID");
Cookie cookie = session.toCookie();
invocationBuilder.cookie(cookie);

If it's not JSESSIONID, check all the cookies. It might be something else.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • there is only one Cookie back, when calling Map cookies = response.getCookies(); When looking in Postman I can see two cookies: XSRF-TOKEN and JSESSIONID. But in my Java Client I get only XSRF-TOKEN – Daniel Pomrehn Jul 11 '17 at 12:22
  • Hmm, that's odd. I'll test it out a bit later. – Paul Samsotha Jul 11 '17 at 12:27
  • First I do a POST Request with Basic Authentication to the resource I like to access. I get back two Cookies: XSRF-TOKEN and JSESSIONID. Then I set the header X-XSRF-TOKEN with the value of cookie XSRF-TOKEN and resend the POST Request to the same Resource – Daniel Pomrehn Jul 11 '17 at 13:27
  • And the request you get back on the first request in Postman is a 403? That's what your code above implies. – Paul Samsotha Jul 11 '17 at 13:36
  • Yes, the first answer in Postman is a 403. The second request (with CSRF header) ends with a 200. – Daniel Pomrehn Jul 11 '17 at 13:50
  • Yeah I don't know. I did a [simple test](https://gist.github.com/psamsotha/1eae09394fff8fcac11869635194eb12). The sessionid shows up fine, so it's not a problem with the client accessing the cookie. It seems to be a problem with the cookie not even being sent. It's not something I can really test. Just something you need to figure out. – Paul Samsotha Jul 11 '17 at 13:58