anvilresearch / connect

A modern authorization server built to authenticate your users and protect your APIs
http://anvil.io
MIT License
361 stars 86 forks source link

Signin via third party where there is an existing account with the same email #47

Open christiansmith opened 10 years ago

christiansmith commented 10 years ago

When a user has already registered with an email address and they try to auth via a third party that's registered with the same email address, we get a unique error.

What's the sensible way to handle this situation? Do we want to automatically merge the accounts? Prompt to merge? Require additional authentication with the existing account? To connect an account, should we require a user to already be signed in?

ovi-tamasan-3pg commented 9 years ago

Getting the unique error in this situation is fine, IMO. The user should either log in with that email address (if it's the same user) or use another third party account for signing up. The problem is that the login with email/password doesn't work in this situation; we get this API error {"error":"invalid_request","error_description":"Missing redirect uri"} Is this a known issue?

christiansmith commented 9 years ago

@ovi-tamasan-3pg something doesn't sound quite right. I just tried to reproduce this and ran into the initial "email must be unique" error in the form. Then tried to sign up with a different email, and it worked fine.

Have you modified the views for your project? If I had to guess, it sounds like some hidden fields might be missing from your sign up form. Can you confirm that these fields are present?

christiansmith commented 9 years ago

I should also comment for the record that we've implemented a stopgap to avoid the "email must be unique error". In case a user is already registered with a given email, we now re-render the signin form with only the providers already connected to that user. This is perhaps not the most desirable of all possible behaviors, but it's better than showing the user a JSON error. We'll revisit this and figure out the best approach as time permits and/or users make specific requests.

adalinesimonian commented 9 years ago

I believe this should be carefully implemented, as to steer clear of any potential security implications.

For example, if a malicious entity were to compromise a user's account on a provider that is not one of the providers already registered, for example, that would mean that the attacker could gain access to their account on Connect without knowing the user's credentials for the provider already associated with Connect.

I propose the following, which is what I think would be a reasonable, yet secure, set of steps.

Assuming that the user has Provider A associated with their account on Connect, the process could resemble:

  1. The user signs in with Provider B, which has not yet been associated with their account, but uses the same e-mail.
  2. Connect prompts the user with a message similar to "It looks like this is the first time you're logging in with Provider B. Please log in with Provider A to verify your identity."
  3. User authenticates with Provider A.
  4. If successful, Connect associates Provider B with the user's account.
bnb commented 9 years ago

@vsimonian Very good idea. I've struggled with how to conceptually implement this flow in the past, but I think you've nailed the solution on the head. :clap:

christiansmith commented 9 years ago

@vsimonian That's probably the right way to do it. The potential for account hijacking is one reason we've taken some time to think this through. There may be other attacks that prey on this mechanism as well. Before we start writing code, it's probably a good idea to whiteboard the flow and look for other logical weaknesses.