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

Facebook login after Google login fails. #7

Open
agentphantom opened this issue Feb 2, 2017 · 5 comments
Open

Facebook login after Google login fails. #7

agentphantom opened this issue Feb 2, 2017 · 5 comments
Assignees

Comments

@agentphantom
Copy link
Member

agentphantom commented Feb 2, 2017

Hello @reyco1 and @sfxworks

I was researching about the issue of using the same email address for Facebook and Google login, it seems it doesn't work for security reasons.

You can see in this thread an explanation about it.

I will quote the relevant part for future readers:

To minimize the login UI clicks without compromising the account security, Firebase Authentication has a concept of 'trusted provider', where the identity provider is also the email service provider. For example, Google is the trusted provider for @gmail.com addresses, Yahoo is the trusted provider for @yahoo.com addresses, and Microsoft for @outlook.com addresses.

In the "One Account per Email address" mode, Firebase Authentication tries to link account based on email address. If a user logins from trusted provider, the user immediately signs into the account since we know the user owns the email address.

If there is an existing account with the same email address but created with non-trusted credentials (e.g. non-trusted provider or password), the previous credentials are removed for security reason. A phisher (who is not the email address owner) might create the initial account - removing the initial credential would prevent the phisher from accessing the account afterwards.

I will also update the examples later today to add a popup explaining the error.

@sfxworks
Copy link

sfxworks commented Feb 2, 2017

So allowing the user to login from multiple providers would fix this option?

@agentphantom
Copy link
Member Author

agentphantom commented Feb 2, 2017

The problem happens only with Facebook -> Google.

The Google login provider will always take precedence over the Facebook one, here's an example:

Let's say my email address for Facebook and Google is the same: john.smith@gmail.com

  1. If I login with Firebase using my Facebook account it will register with my email address, but it won't be trusted.

  2. If I then login with my Google account, the Facebook data will be overwritten with the Google one and the email address will become trusted.

  3. At this step I can't login anymore with Facebook, I will need to login with Google or it won't work at all (the Facebook login doesn't return the refreshToken anymore).

In this case you will have to tell the user that they can't login with Facebook anymore and they should use Google instead.

@rl-pavel
Copy link

rl-pavel commented Mar 23, 2017

Found a hack. Not 100% sure if this is a good idea, but it works.
Basically, if you log in with Facebook after you've used Google, Firebase will return errorCodeEmailAlreadyInUse error, so all we have to do is check if the error is of that type and just log the user in with Google.

FIRAuth.auth()?.signIn(with: FIRCredentials, completion: { (user, error) in
  if let errorCode = error?._code,
    let authError = FIRAuthErrorCode(rawValue: errorCode) {
    switch authError {
    case .errorCodeEmailAlreadyInUse:
      GIDSignIn.sharedInstance().signIn()
    default: self.showError(withMessage: "Couldn't sign in with Facebook")
    }
  }
})

@agentphantom
Copy link
Member Author

Nice find!

Tonight I will give it another shot at this issue and document my results.

@agentphantom
Copy link
Member Author

I tried the following:

I had already my account with Gmail and logged in with Facebook, the login was successful and this was the response:

{
    "kind": "identitytoolkit#VerifyAssertionResponse",
    "federatedId": "http://facebook.com/1127852910645790",
    "providerId": "facebook.com",
    "localId": "QcGrHghblIg4T2qLWP0RVJL8AQf2",
    "emailVerified": false,
    "email": "phantom@phantom.im",
    "oauthAccessToken": "<Medium sized string>",
    "oauthExpireIn": 5183999,
    "firstName": "John",
    "lastName": "Smith",
    "fullName": "John Smith",
    "displayName": "John Smith",
    "idToken": "<Long String>",
    "timeZone": "-6",
    "photoUrl": "https://scontent.xx.fbcdn.net/v/t1.0-1/p100x100/418143_223575787734578_1621690654_n.jpg?oh=25b36d4a93ebcede1245e2944b188130&oe=596B6757",
    "context": "",
    "verifiedProvider": [
        "google.com"
    ],
    "needConfirmation": true,
    "rawUserInfo": "{my Facebook profile information as sent from the Graph API}"
}

The important things to notice are:

  • There's not a refreshToken in the response, which is the key for doing anything with auth in Firebase.
  • emailVerified is set to false. This value is set to true when I log in with Google.
  • needConfirmation parameter which only appears when I try the previous sequence of actions.

My guess is that the Swift API already knows about this and gives you this particular error. In my case I will need to manually detect if the refreshToken exists and if not, redirect the user to the Google Auth.

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

No branches or pull requests

3 participants