1

I'm currently working on a Google Sign-in Auth app with a React frontend and an Express backend and I'm currently stuck in the part of the process where I'm validating tokens on the backend. The docs for this process show this code to validate the token:

const {OAuth2Client} = require('google-auth-library');

...

const client = new OAuth2Client(CLIENT_ID);
async function verify() {
  const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,  // Specify the CLIENT_ID of the app that accesses the backend
      // Or, if multiple clients access the backend:
      //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
  });
  const payload = ticket.getPayload();
  const userid = payload['sub'];
  // If request specified a G Suite domain:
  //const domain = payload['hd'];
}
verify().catch(console.error);

I've implemented this code in my own project here:

//verify token
async function verify(token, client) {

  const ticket = await client.verifyIdToken({
    idToken: token,
    audience: keys.google.clientID,
  });

  const payload = ticket.getPayload();
  const userid = payload['sub'];
  const domain = payload['hd'];
  const email = payload['email']
  console.log('User ID: ' + userid);
  console.log('Domian: ' + domain);
  console.log('Email: ' + email);

  var message = '';
  var cookie = {};
  await User.find({email: email}, (error, user) => {
    if(error) {
      message = error;
    } else if (user.length === 0) {
      message = 'this user is not in the database';
    } else {
      message = 'this user is in the database';
      const session = new Session({
        email: email,
        session_token: token
      });
      cookie = {
        email: email,
        session_token: token
      };
      session.save((error, session) => {
        if (error) {
          console.log(error);
        } else {
          console.log('session saved');
        }
      });
      console.log(message);
    }
  });
  return Promise.resolve(cookie);
}

//recieve token id from frontend, verify it, and send session back in response
router.post('/google', (req, res) => {
  const body = req.body.tokenID;
  const client = new OAuth2Client(keys.google.clientID);

  let cookie = verify(body, client).catch(console.error);

  console.log('Cookie:' + cookie);
  return res.send(cookie);
});

Currently when this runs everything inside the async function executes, but the return statement only returns the empty promise object. I think I'm making a mistake using async and await incorrectly, but I don't know how to correctly get the function to wait for all the work verifying the token and then update the DB before returning.

Not sure if this will help, but when I call the route my console gives me this output:

(I took out my personal info from the output fields, but assume these lines actually have gmail account info)

...
Cookie:[object Promise]
User ID: <GOOGLE ID>
Domian: <DOMAIN>
Email: <USER EMAIL>
this user is in the database
session saved

Thanks for reading!

2 Answers 2

1

Since "verify" function is an async function, you should add "await" before calling it. For catching errors you can simply place it in a try/catch:

router.post('/google', async (req, res) => {
  const body = req.body.tokenID;
  const client = new OAuth2Client(keys.google.clientID);

  try {
    let cookie = await verify(body, client);
    console.log('Cookie:' + cookie);
    return res.send(cookie);
  } catch(error) {
    // handling error
    console.log(error);
    return res.send("error")
}
});

`

Sign up to request clarification or add additional context in comments.

3 Comments

you can't add await outside of the the async function
So make the whole callback function async. I updated my code.
I made the whole callback async and it worked! thank you!
0

You're mixing async/await with callback based calls. I don't know the internals of the library you're using, but the pattern should look more like this:

var cookie = {};
try{
    const user = await User.find({email: email});
    if (user.length === 0) {
        console.log('this user is not in the database');
    }
    else {
        console.log('this user is in the database');
        const session = new Session({
          email: email,
          session_token: token
        });

        try{
            await session.save();
            console.log('session saved');
        } catch(err){
            console.log(err);
        }
        return {
          email: email,
          session_token: token
        };
} catch(error){
    console.log(error);
}

1 Comment

I implemented this pattern, but I'm still returning an empty promise object

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.