Search code examples
node.jsexpressgoogle-oauth

Google "One Tap", tokeninfo endpoint 404


In the HTML in the site I have got from the docs here

<script src="https://accounts.google.com/gsi/client"></script>

      <div
        id="g_id_onload"
        data-client_id={googleClientID}
        data-login_uri='https://mytestdomain.appspot.com/google'
        data-return_uri={uri}
      ></div>

When the site loads it shows me the prompt to continue with my google account, I click continue and it shows me as logged in, the webhook does get called and I can get the g_csrf_token from the cookie

const fetch = require("node-fetch");
...
app.post("/google", function(req, res) {
  const token = req.cookies.g_csrf_token;
  console.log('-------------- token');
  console.log(token);
  const url = `https://oauth2.googleapis.com/tokeninfo?id_token=${token}`
  const getData = async (url) => {
    try {
      const response = await fetch(url);
      console.log('-------------- response');
      console.log(response);
      const json = await response.json();
      console.log('-------------- json');
      console.log(json);
      res.status(200).send({ data });
    } catch (error) {
      console.log('--------------  error');
      console.log(error);
      res.status(400).send({ error });
    }
  };
  if (token) getData(url);
  res.status(200).send({ req });
});

But when I try to call the token info endpoint as detailed in the docs here, I get the error

  -------------- token
  d7d07535919b8e26
  -------------- response
  Response {
    size: 0,
    timeout: 0,
    [Symbol(Body internals)]: {
      body: PassThrough {
        _readableState: [ReadableState],
        readable: true,
        _events: [Object: null prototype],
        _eventsCount: 5,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        _transformState: [Object],
        [Symbol(kCapture)]: false
      },
      disturbed: false,
      error: null
    },
    [Symbol(Response internals)]: {
      url: 'https://oauth2.googleapis.com/tokeninfo?id_token=d7d07535919b8e26',
      status: 404,
      statusText: 'Not Found',
      headers: Headers { [Symbol(map)]: [Object: null prototype] },
      counter: 0
    }
  }

The docs say I can use GET or POST, I've tried both with the same error response

If I try to call the endpoint in the browser by entering https://oauth2.googleapis.com/tokeninfo?id_token=d7d07535919b8e26 into the address bar I get the response

{
  "error": "invalid_token",
  "error_description": "Invalid Value"
}

So is it not the token in the cookie from the callback that I should be using?


Solution

  • The g_csrf_token is used for double-submission to prevent CSRF attack. It's not the returned ID token.

    As mentioned in the offical doc (https://developers.google.com/identity/one-tap/web/guides/verify-google-id-token), the ID token is returned in the 'credential' filed.