Skip to content

Logging in on staging instances

Jacob Sommer edited this page Jun 1, 2023 · 3 revisions

In order to authenticate with Google there are 2 steps.

  1. Open the authentication URL (which passes a callback url)
  2. Handle the callback in our back end.

The problem with staging instances is that each callback url must be registered in google cloud e.g https://peterportal.org/api/users/auth/callback or http://localhost:5000/api/users/auth/callback. Each staging instances has a unique hostname and it is not feasible to register every callback url.

The workaround is to have the passed callback url be the prod callback URL and then to have prod's backend redirect the callback to staging instance if necessary. In order for the prod backend to know the callback is meant for staging, it is defined using the state parameter in the authentication URL, which gets passed back in the callback.

/api/src/controllers/user.ts

/**
 * Initiate authentication with Google
 */
router.get('/auth/google',
  function (req, res) {
    
    req.session.returnTo = req.headers.referer;
    passport.authenticate('google', {
      scope: ['https://www.googleapis.com/auth/userinfo.profile',
        'https://www.googleapis.com/auth/userinfo.email'],
      state: req.headers.host
    })(req, res);
  }
);

/**
 * Callback for Google authentication
 */
router.get('/auth/google/callback', function (req, res) {
  const returnTo = req.session.returnTo;
  let host: string = req.query.state as string;
  // all staging auths will redirect their callback to prod since all callback URLs must be registered
  // with google cloud for security reasons and it isn't feasible to register the callback URLs for all
  // staging instances
  // if we are not on a staging instance (on prod or local) but original host is a staging instance, redirect back to host
  if (host.startsWith('staging-') && !req.headers.host?.startsWith('staging')) {
    // req.url doesn't include /api/users part, only /auth/google/callback? and whatever params after that
    res.redirect('https://' + host + '/api/users' + req.url);
    return;
  }
  // authentication below
  // ...
Clone this wiki locally