Firebase Google Sign-In token expiration issue

Viewed 775

I want to let my users send emails in my app through their Gmail account. So, in my front-end, I'm collecting the token generated with

const provider = new firebase.auth.GoogleAuthProvider()
provider.addScope('https://www.googleapis.com/auth/gmail.send')
provider.setCustomParameters({
    access_type: 'offline',
    prompt: 'consent',
})
firebase.auth()
  .signInWithPopup(provider)
  .then((result) => {
    var credential = result.credential;
    var token = credential.accessToken;
  })

In my backend, I'm using this token to send emails on their behalf thanks to the Google API. Eveything works well but the token only last one hour...

Do you have any recommandations about the right way to handle this ? Do I need to extend the duration of the token ? Do I have to create a new token every time I want to send an email ? Or do I have to not use firebase to collect the token ?

1 Answers

By default, Firebase auth returns a short-lived authentication token and a refresh token that you can use to extend that session indefinitely. In order to extend that session you'll need to implement session cookies.

Here's a brief summary of how it works:

  1. User signs in using .signInWithPopup()

  2. User POSTs that ID token to a backend API endpoint that calls .verifyIdToken() to validate the token and then .createSessionCookie() with whatever expiration you desire.

  3. Backend reponds with a set-cookie HTTP parameter containing the generated session cookie.

Here's an example of what that backend API endpoint would look like:

  login(req: any, res: Response) {
    // Cookie has a 30 day expiration
    const AUTH_COOKIE_LENGTH = 30;
    
    // If no ID Token was passed, return an error
    if (!req.body.idToken) {
      return res.status(400).end();
    }

    // The ID Token passed as a POST parameter
    const idToken = req.body.idToken.toString().trim();
    
    // Verify the ID Token
    admin.auth().verifyIdToken(idToken)
      .then(async (user) => {
        // Cookie expires 
        const expiresIn = 60 * 60 * 24 * AUTH_COOKIE_LENGTH * 1000;

        // Generate the session cookie
        admin.auth().createSessionCookie(idToken, {expiresIn})
          .then((sessionCookie) => {
            // Add the set-cookie parameter to the response
            res.cookie("__session", sessionCookie, {
              domain: '.example.com',
              secure: true,
              sameSite: 'strict',
              expires: expiresIn
            });

            res.json({
              success: true
            }).end();
          }, (error: any) => {
            res.status(503).json({success: false}).end();
          });
      }).catch((error: any) => {
        res.status(401).json({success: false, error: "INVALID_TOKEN"}).end();
    });
  }
Related