-
Notifications
You must be signed in to change notification settings - Fork 14
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.
- Open the authentication URL (which passes a callback url)
- 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
// ...