I have successfully implemented authentication using gmail account in my app.
The problem is when the user signs-in again, the browser automatically picks the previous account which breaks the flow as I will explain below. p
Based on my research, adding prompt: "select_account" here should have solved the issue. But, it had no effect.
router.get(
"/auth/google",
passport.authenticate("google", {
scope: [
"email",
"profile",
],
prompt: "select_account",
})
);
Here's how automatically picking the user account that was previously used to sign-in breaks the sign-in if the user tries to sign-in again.
This is how the sign-in works:
- STEP 1:
This endpoint is called from the frontend:
router.get(
"/auth/google",
passport.authenticate("google", {
scope: [
"email",
"profile",
],
prompt: "select_account",
})
);
- STEP 2:
After, the user picks an account, he is redirected to this callback endpoint:
router.get(
"/auth/google/callback",
passport.authenticate("google", {
failureRedirect: baseFrontendUrl,
session: false,
}),
function (req, res) {
User.findOne({ _id: req.user._id })
.then((user) => {
const payload = {
id: req.user._id,
};
console.log(" ~ file: users.js:178 ~ .then ~ payload", payload);
jwt.sign(
payload,
keys.SecretKey,
{ expiresIn: 3600 * 24 * 356 },
(error, token) => {
if (error) {
res.status(400).json({
message: "Error logging in user.",
});
} else {
const redirect_url = `${baseFrontendUrl}/OAuthRedirecting?token=${token}`;
res.redirect(redirect_url);
}
}
);
})
.catch((error) => {
res.status(500).json({
message: "An error occured authenticating user using google.",
});
});
}
);
The problem is that if the user does not pick an account, he does not get redirected to that endpoint. So the second sign-in fails.
A solution to this could be to force the user to pick an account every time he signs-in but I couldn't find a way to do this.
This is how the google passport strategy is implemented:
passport.use(
new GoogleStrategy(googe_passport_config, function (
request,
accessToken,
refreshToken,
google_profile,
done
) {
let name = !!google_profile._json.given_name
? google_profile.given_name
: "Name";
let surname = !!google_profile._json.family_name
? google_profile.family_name
: "Surname";
let email = !!google_profile._json.email ? google_profile.email : "";
User.findOne({ email: google_profile._json.email })
.then((user) => {
if (!!user) {
return done(null, user);
} else {
userServices
.registerUserThroughGoogleAuth(
name,
surname,
email,
google_profile.id
)
.then((created_user) => {
if (!!created_user) {
return done(null, created_user);
}
})
.catch((error) => {
const error_to_be_returned = new Error("Error creating user");
return done(error_to_be_returned, null);
});
}
})
.catch((error) => {
const error_to_be_returned = new Error("Error finding user");
return done(error_to_be_returned, null);
});
})
);
I added some console logs there and nothing gets logged the second time the user tries to sign-in. So it's not even getting called.