firebase / firebaseui-web

FirebaseUI is an open-source JavaScript library for Web that provides simple, customizable UI bindings on top of Firebase SDKs to eliminate boilerplate code and promote best practices.
https://firebase.google.com/
Apache License 2.0
4.55k stars 1.05k forks source link

Link Multiple Accounts doesn't work! auth/account-exists-with-different-credential #1038

Open AntonioVentilii opened 1 year ago

AntonioVentilii commented 1 year ago

If the user first login using google, and then using any other provider (for example github) the result is below... (it can be tested in the demo, same results)

Screenshot 2023-08-04 at 17 08 40
brayo-pip commented 1 year ago

I have been experiencing a related issue with Google and Github providers. When I first login with Github all goes well. When I later login with Google, same email, I get logged in but the two providers are not linked. The Github authentication is replaced with just google in the Firebase console. When I later try to login with Github I am unable but no error is displayed. I have tested with the demo app and I have been able to reproduce the error.

mahmoudaboalwafa1 commented 1 year ago

التقاط

Hello Antonio you should go to authentication and then Settings and select create multiple accounts for each identity provider

brayo-pip commented 1 year ago

التقاط

Hello Antonio you should go to authentication and then Settings and select create multiple accounts for each identity provider

That doesn't fix the issue, he wants as I do too, to link multiple auth providers to a single account.

mahmoudaboalwafa1 commented 1 year ago

@brayo-pip Hello brayo I have been facing this problem and I have selected the option that is in the image and I succeeded I think it is preferable to delete all users and make an update to the cookies

brayo-pip commented 1 year ago

That will make two accounts for each Provider. If I have email example@gmail.com and I sign with Google, I'll have a google entry in firebase console. When I sign in with Github using example@gmail.com that will create a separate entry in the firebase console. But we want to have a single entry with both providers linked. I don't have a screenshot to link right now but I hope you are familiar with what I hope to achieve. The linked entry should show both icons of the linked providers, Google and Github.

mahmoudaboalwafa1 commented 1 year ago

I understand you now, you want when a user registers with a Google account, and we assume that there is another button on a site when logging in, and this button registers with a GitHub account, meaning two accounts are added and not a change between a Google account and a GitHub, right

damencho commented 1 year ago

@brayo-pip Hello brayo I have been facing this problem and I have selected the option that is in the image and I succeeded I think it is preferable to delete all users and make an update to the cookies

But this way the faceboook email is missing in the token after login.

damencho commented 1 year ago

The problem is that in case of an error like auth/account-exists-with-different-credential the signInFailure callback is not executed. The case when using a popup the problem is more visible as the popup closes without any notification and you are left with an empty page.

dbrody commented 8 months ago

Is there a fix for this? Ideally the signIfFailure would be called and worst case our callback can try to merge accounts. I would expect this UI to handle this use case by default but since it doesnt what is the recommended fix for this?

aress31 commented 7 months ago

Any update on this?

It seems to me that the Link accounts that use the same email is a bit useless as not working as one's would expect and not preventing auth/account-exists-with-different-credential, for instance:

      try {
        const userCredential = await signInWithPopup(auth, provider);

        console.log("userCredential", userCredential);
        const { isNewUser } = getAdditionalUserInfo(userCredential);
        console.log("isNewUser", isNewUser);

        if (isNewUser) {
          await auth.currentUser.delete();
          throw new Error(`${email} is not registered.`);
        } else navigate(`/${auth.currentUser.tenantId}/projects`);
      } catch (error) {
        if (error.code === "auth/account-exists-with-different-credential") {
          const test = OAuthProvider.credentialFromError(error);
          console.log("test", test);
        } else throw error;
      }
    };

I have multiple providers, Google and Microsoft for instance and I would expect this code to work seamlessly regardless of the selected provider.

dimitriz09 commented 4 months ago

Same issue here, on version 6.1.0. It can result on user being stuck on a white page. The UI container is present in the DOM, but no content, no loading, nothing.

pamafe1976 commented 4 months ago

Im having this same problem while trying to login with Google and Facebook with the same email. At first login with Facebook works, but one I log with Google, then Facebook login returns firebase_auth/account-exists-with-different-credential

ms-aija commented 3 months ago

I am facing the same issue - I can link accounts when user first logs in with gmail and then Github. However, when the user first logs in with Github and then with Gmail the "account-exists-with-different-credential" doesn't get thrown thus the linking doesn't happen and the Github account gets overwritten with Gmail. Afterwards if the user tries to log in with Github they are prompted to link the accounts and both accounts are finally linked.

kbrennan7272 commented 3 months ago

I'm also facing this issue.

kdawgwilk commented 3 months ago

I am also noticing this happening when there are no providers linked at all when trying to login with microsoft for the first time.

FinestMaximus commented 2 months ago

works on google, but not on msft - when initial account is mail/pass

kdawgwilk commented 2 months ago

I reached out to firebase support and they told me this is specific to Microsoft 365 business accounts? Why would the providers account type have any result on this auth error?

roberthangu commented 2 months ago

I can confirm this. Also, the signInSuccessWithAuthResult() callback is not called.

I have also tried to upgrade Firebase Auth to the version that uses Google Cloud Identity Platform, but with no success. (I assumed that it might be a "newer" version than the so-called "legacy", i.e. Firebase Auth alone).

Neither of the two executes the signInSuccessWithAuthResult() callback and get stuck at a white screen, as described above.

Is it a Firebase/Identity Platform bug then?

kdawgwilk commented 2 months ago

Found this in the docs and working on implementation to see if it fixes the issue. It's really odd that we have to link the provider to another one despite the setting to merge the accounts with the same email turned on https://firebase.google.com/docs/auth/web/microsoft-oauth#expandable-1

neil-119 commented 1 month ago

Having to manually link accounts by saving and loading credentials and asking the user to sign in via some identity provider they have used in the past (out of many) is not good design/UX. The "link accounts with same email" does not work the way it implies to.

asoseil commented 1 month ago

is there any workaround to sign in the first time with Microsoft 365?

Panigale commented 1 week ago

got same issue here. when using google and facebook.

jacobshirley commented 1 week ago

Have the same issue, when using a custom token implementation to sign in first, then signing in with a Microsoft account with the same email, I get this error

akroll1 commented 1 week ago

Same issue here, looking for a solution.

FabriceBazzaro commented 5 days ago

Same issue here,

First approch

I've tried the code pointed by @kdawgwilk with no success

Found this in the docs and working on implementation to see if it fixes the issue. It's really odd that we have to link the provider to another one despite the setting to merge the accounts with the same email turned on firebase.google.com/docs/auth/web/microsoft-oauth#expandable-1

There is no "credential" field in the error (step 2) but a customData with a lot of information : federatedId or id in the rawUserInfo marked as KEY below is the key of the Microsoft account. I can link this id with a backend function in a second step and launch again the signIn.

customData: {
    appName: "[DEFAULT]"
    email: XXX,
    _tokenResponse: {
        context: ""
        displayName: XXX
        email: XXX
        emailVerified: false
        federatedId: "http://microsoft.com/KEY"
        fullName:  XXX
        kind: "identitytoolkit#VerifyAssertionResponse",
        localId: Firebase UID
        needConfirmation: true
        oauthAccessToken: XXX
        oauthExpireIn: 3743
        oauthIdToken: XXX
        pendingToken: XXX
        providerId: "microsoft.com"
        rawUserInfo:  "{\"businessPhones\" :[],\"preferredLanguage\":null,\"mail\":null,\"mobilePhone\":null,\"officeLocation\":null,\"displayName\":\"XXX\",\"surname\":null,\"givenName\":null,\"jobTitle\":null,\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users/$entity\",\"id\":\"KEY\",\"userPrincipalName\":\"XXX\"}"
        verifiedProvider: Array(1)
            0: "microsoft.com"

BTW it's not a proper solution for a production usage just a temporary workaround. Do you have a better workaround ? It seems very fragile...

Second approch and solution I used

Presentation of my own case:

  1. an administrator register the user (I store a token and the associated email in my rtdb)
  2. the user follow a link with the token and signup with the provider
export async function signUpWithMicrosoftProvider(
    temporaryId: SignInEmailAndPasswordProps,
) {
    const provider = new OAuthProvider("microsoft.com");
    const result = await signInEmailAndPassword(temporaryId);
    await linkWithPopup(result.user, provider);
    await unlink(result.user, "password");
    return result;
}

In the callback function of my Microsoft button, I call a backend function (which checks the token and creates the new account with the user's e-mail address in the rtdb and a temporarily generated password). The password is returned and passed as a parameter along with the email to log the user in before linking the Microsoft account and removing the password provider.

I'll add error handling and reinforcement of the password validity period to avoid security problems.