rs7
rs7

Reputation: 1630

Verify Google ID Token with Node js

I have an iOS app that's sending a google id to a backend server for validation.

I'm following the Google guidelines: https://developers.google.com/identity/sign-in/web/backend-auth

I'm quite new to Node js and I can't figure out why the callback function never gets executed (i.e., the promise doesn't resolve nor reject):

const verifyToken = new Promise(function(resolve, reject){
    console.log("promise function")
    client.verifyIdToken({
        idToken: token,
        audience: process.env.CLIENT_ID, 
        function (e, login){
            console.log(e)
           if (login) {
               var payload = login.getPayload();
               var googleId = payload['sub'];
               resolve(googleId);
            } else {
            reject("invalid token");
           }
        }
    });
});
verifyToken.then((token) => {
    console.log("RESOLVED");
    jwt.sign({id: googleId}, 'secret key', { algorithm: 'RS256' }, (err, token) => {
        console.log("sending data back");
        res.send(token);
    });
});
verifyToken.catch((message) => {
    console.log("REJECTED");
    res.send(message);
});

Upvotes: 1

Views: 2477

Answers (2)

Samuel
Samuel

Reputation: 368

The best way to verify Google ID token is to use google-auth-library from npm below is a sample snippet for validating the tokenId sent from client to the server, hope it helps.

const {GOOGLE_CLIENT_ID, JWT_SECRET } = process.env;

app.post('/api/v1/auth/google', async ({ body: { tokenId } }, res) => {

  const client = new OAuth2Client(GOOGLE_CLIENT_ID);

  const ticket = await client.verifyIdToken({
    idToken: tokenId,
    audience: GOOGLE_CLIENT_ID,
  });

  const response = ticket.getPayload();

  if (response.iss !== 'accounts.google.com' && response.aud !== GOOGLE_CLIENT_ID)
    return res.status(400).json({ status: 'error', error: 'Bad Request' });

  const user = {
    email: response.email,
    image: response.picture,
    social_id: response.sub,
    first_name: response.given_name,
    last_name: response.family_name,
  };

  let result = await User.findOne({
    where: { [Op.or]: [{ email: user.email }, { social_id: user.social_id }] },
  });

  if (!result) result = await User.create(user);

  const token = await jwt.sign({ id: result.dataValues.id }, JWT_SECRET, { expiresIn: '1hr' });
  const data = { token, ...result.dataValues};

  res.status(200).json({ status: 'success', data });

});

Upvotes: 7

Rahul Yadav
Rahul Yadav

Reputation: 181

When a new Promise is created it will execute automatically. The resolve and reject functions you passed in the executor will change the state of promise to resolved or rejected respectively when called. Have a look at this link

The .then and .catch implementations will execute for the resolved and rejected promise. So your code looks fine as far as execution of promise is concerned.

Depends if the control is coming to the block you've written. As i can see res.send in your implementation it must be inside some (req,res) middleware.

So check if the execution is coming to the that middleware.

Upvotes: 3

Related Questions