1

On my site I have implemented Google Identity Services using a popup code model.

To prevent CSRF attacks the docs say this:

With Popup mode, you add a custom HTTP header to your requests, and then on your server confirm it matches the expected value and origin.

Here is the popup sample code provided in the docs:

const client = google.accounts.oauth2.initCodeClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  ux_mode: 'popup',
  callback: (response) => {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', code_receiver_uri, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    // Set custom header for CRSF
    xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
    xhr.onload = function() {
      console.log('Auth code response: ' + xhr.responseText);
    };
    xhr.send('code=' + code);
  },
});

It's my understanding that I need to add a random CSRF code string to the above code, and then verify that on my server.

But where exactly do I put that CSRF code?

I thought that maybe it should go in the code variable like this xhr.send('code=' + 'MY_CSRF_STRING') but when I do that my headers look like this (MY_CSRF_STRING is missing so I cannot verify it on the server):

{
   "host":"localhost:5001",
   "connection":"keep-alive",
   "accept":"*/*",
   "access-control-request-method":"POST",
   "access-control-request-headers":"x-requested-with",
   "origin":"http://localhost:8080",
   "user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36",
   "sec-fetch-mode":"cors",
   "sec-fetch-site":"same-site",
   "sec-fetch-dest":"empty",
   "referer":"http://localhost:8080/",
   "accept-encoding":"gzip, deflate, br",
   "accept-language":"en-US,en;q=0.9",
   "severity":"INFO",
   "message":"googleAuthorization req.headers"
}

And if the CSRF code does not go there, what else is supposed to go in the code variable?

TinyTiger
  • 1,801
  • 7
  • 47
  • 92

1 Answers1

2

Think I figured this out.

But I would still love to hear from others to make sure this is correct.

In short, this answer outlines that the csrf protection comes from checking for the existance of the custom X-Requested-With header. No need to create your own unique value.

There is also a typo in the Google code sample which created this confusion.

The line xhr.send('code=' + code); should be xhr.send('code=' + response.code);. Because we are taking the auth code from the response and passing it along to the server.

TinyTiger
  • 1,801
  • 7
  • 47
  • 92