Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject login when external oauth login matches a different account #34

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ayush-goyal
Copy link
Member

Closes #31

@hackgt-beekeeper hackgt-beekeeper bot temporarily deployed to login-dev December 5, 2020 22:38 Inactive
Copy link
Member

@petschekr petschekr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM aside from the wording of some of the error messages

@@ -81,7 +88,7 @@ export async function ExternalServiceCallback(
}

if (!user) {
done(null, false, { "message": "Could not match login to existing account" });
done(null, false, { message: "Could not match login to an existing account. Please try again with a different login method." });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda picky but this can also be triggered by someone choosing the wrong account in the account picker (i.e. for Google which allows multiple user accounts to be logged in) but if there isn't a Ground Truth account with that other account. So I'd say Please try again with a different account or login method instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, if the third-party IdP email doesn't correspond to the email they entered originally, we should:

  1. Just tell people that, or
  2. Change the UX so you can directly pick 3rd-party IdPs on the initial login screen (which may have other implications I'm not thinking of right now)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if picking 3rd party IdPs directly is an option anymore, since there are so many accounts whose 3rd party IdP email doesn't match their main email address on their account, so it wouldn't work.

@@ -25,6 +25,12 @@ export async function ExternalServiceCallback(
// If `user` exists, the user has already logged in with this service and is good-to-go
let user = await User.findOne({ [`services.${serviceName}.id`]: id });

// Ensure that the oauth method used is linked to the user with the same email address that is entered
if (session.email && user && session.email !== user.email) {
done(null, false, { message: "Login method is linked to another email. Please try again with a different email address." });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message is kind of confusing imo. Perhaps The 3rd party account you chose does not match the email address that you are trying to log in with. Please make sure your email address and the selected account match.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to this, users will be confused by this if we aren't really clear. So it would be good to include the original email the user entered in the error message to. As in, if I enter [email protected] on the initial login screen, then choose a Google account with the email [email protected], the error message might show, "The Google account you signed in with ([email protected]) has a different email than what you originally entered ([email protected]). Please ensure your email address and the account you select have the same email address.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone uses their gt email, [email protected], but chooses to sign in with google ([email protected]), and on the first screen they enter their google email, how should the error message read?

Copy link
Member

@evan10s evan10s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a great start, but I have a few concerns we need to address:

  • I am almost certain there are a few users who will be locked out if we merge this change as-is (I can probably find you an example account). That means we need to check the database for accounts where the account email != the third-party IdP email, or if we can't do that, then we ought to develop a way for those users to rectify the problem.
  • Do these changes also apply when someone is making a new account with a third-party IdP? Or just new sign-ins?

@@ -25,6 +25,12 @@ export async function ExternalServiceCallback(
// If `user` exists, the user has already logged in with this service and is good-to-go
let user = await User.findOne({ [`services.${serviceName}.id`]: id });

// Ensure that the oauth method used is linked to the user with the same email address that is entered
if (session.email && user && session.email !== user.email) {
done(null, false, { message: "Login method is linked to another email. Please try again with a different email address." });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to this, users will be confused by this if we aren't really clear. So it would be good to include the original email the user entered in the error message to. As in, if I enter [email protected] on the initial login screen, then choose a Google account with the email [email protected], the error message might show, "The Google account you signed in with ([email protected]) has a different email than what you originally entered ([email protected]). Please ensure your email address and the account you select have the same email address.

@@ -25,6 +25,12 @@ export async function ExternalServiceCallback(
// If `user` exists, the user has already logged in with this service and is good-to-go
let user = await User.findOne({ [`services.${serviceName}.id`]: id });

// Ensure that the oauth method used is linked to the user with the same email address that is entered
if (session.email && user && session.email !== user.email) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure we're using the trimmed and lowercased email for all comparisons.

@@ -81,7 +88,7 @@ export async function ExternalServiceCallback(
}

if (!user) {
done(null, false, { "message": "Could not match login to existing account" });
done(null, false, { message: "Could not match login to an existing account. Please try again with a different login method." });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, if the third-party IdP email doesn't correspond to the email they entered originally, we should:

  1. Just tell people that, or
  2. Change the UX so you can directly pick 3rd-party IdPs on the initial login screen (which may have other implications I'm not thinking of right now)

@ayush-goyal
Copy link
Member Author

So it's a little weird how it works, for every user, there is an email field, and then each 3rd party IdP they use also has an associated email in the db. These two emails can be different.

So when the user enters their email on the first screen, the system finds a user object with the corresponding email. Then, based on this, they are redirected to the corresponding service based on what they use. Once they login, they are essentially logged in based on their 3rd part IdP.

This check that I implemented, it only makes sure that the initial email they enter matches the email address of the user which they select from the IdP.

For example, if a user has an account with email address [email protected], but uses GitHub login on which service their email is [email protected], they must enter [email protected] on the first login screen. That's essentially what my check is doing

@hackgt-beekeeper hackgt-beekeeper bot temporarily deployed to login-dev December 9, 2020 01:35 Inactive
Copy link
Member

@evan10s evan10s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds like the check you're doing is what makes the most sense here, just a small thing with the error message wording


// Ensure that the oauth method used is linked to the user with the same email address that is entered
if (enteredEmail && user && enteredEmail !== user.email) {
done(null, false, { message: "The 3rd party account you chose does not match the email address that you are trying to log in with. Please make sure your email address and the selected account match." });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify the exact expectation in the error message by adding what aspect of the third-party account doesn't match (you mention the email address the user entered but the rest is vague)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, I want them to login with a different 3rd party account. So Ill just tell them that. Let me know if this is good instead.

The {serviceName} account you selected is linked to a different email address than typed below. Please try again with a different 3rd party account.

Where service name is google, github, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider rejecting sign-ins where third-party IdP email does not match the initial email entered
3 participants