0
votes

Question

I have the following code running on localhost:3000 and my api running at localhost:8020. If I visit localhost:3000 the request is made to localhost:8020/user/refresh to get a new access-token with the refresh-token in the cookie and it responds with the new access-token. I am now able to make another request with the acquired access-token to localhost:8020/user/delete.

But why am I able to read the response from the first request as an attacker. Should same-origin policy not prohibit from reading the response, because I have different ports? Is it because I am allowing Origin localhost:3000 to make cross-site requests with "Access-Control-Allow-Origin: localhost:3000"?

If Access-Control-Allow-Origin is the problem, do I have to protect my api requests with csrf-tokens or is there another way? Implementing csrf tokens is not the problem but I am wondering, if there is an different, probably smaller solution.

<script>
   function post() {
      var x = new XMLHttpRequest();
      x.open("GET", "http://localhost:8020/user/refresh", true);
      x.withCredentials = true;
      x.setRequestHeader("Content-Type", "application/json");

      x.onreadystatechange = function () {
         if (x.readyState == XMLHttpRequest.DONE) {
            var data = JSON.parse(x.responseText);    
            var x2 = new XMLHttpRequest();
            x2.open("POST", "http://localhost:8020/user/delete", true);
            x2.setRequestHeader("Content-Type", "application/json");
            x2.setRequestHeader("Authorization", `Bearer ${data["data"]["accessToken"]}`);
            x2.onreadystatechange = function () {
               if (x2.readyState == XMLHttpRequest.DONE) {
                  console.log(x2.responseText);
               }
            }
            x2.send(JSON.stringify({user : { "id": "2" }}));
         }
      }
      x.send(null);
   }
</script>

<!DOCTYPE html>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   </head>
<body onload="post()">
</body>
</html>

Solution

But why am I able to read the response from the first request as an attacker. Should same-origin policy not prohibit from reading the response, because I have different ports? Is it because I am allowing Origin localhost:3000 to make cross-site requests with "Access-Control-Allow-Origin: localhost:3000"?

Yes, "Access-Control-Allow-Origin: localhost:3000" allows localhost:3000 to read response.

If Access-Control-Allow-Origin is the problem, do I have to protect my api requests with csrf-tokens or is there another way? Implementing csrf tokens is not the problem but I am wondering, if there is an different, probably smaller solution.

OWASP recommendation is to always use csrf-tokens. So I implemented csrf-tokens.

1
I hope you're doing a real authorization on the server too. CSRF token is not meant to authorize any actions, it's only used to check, that the request came from a source originating your own domain.Teemu
@Teemu I have JWT access and refresh token set up. it sounds like i have to use csrf-tokens to check for origin.byCrookie

1 Answers

0
votes

But why am I able to read the response from the first request as an attacker. Should same-origin policy not prohibit from reading the response, because I have different ports?

By default, yes.

Is it because I am allowing Origin localhost:3000 to make cross-site requests with "Access-Control-Allow-Origin: localhost:3000"?

Yes. Explicitly giving permission to localhost:3000 to read the data lets localhost:3000 read the data.

If Access-Control-Allow-Origin is the problem, do I have to protect my api requests with csrf-tokens or is there another way?

What approaches you use to protect an end point from attackers depends very much on:

  • Who you want to stop doing bad things
  • What you want to allow those people to do
  • What you want to allow other people to do