fix: find linked account from authentication error and link it (#2662)
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
@@ -129,7 +129,6 @@ import {
|
|||||||
setProviderInfo,
|
setProviderInfo,
|
||||||
currentUser$,
|
currentUser$,
|
||||||
signInWithEmail,
|
signInWithEmail,
|
||||||
linkWithFBCredential,
|
|
||||||
linkWithFBCredentialFromAuthError,
|
linkWithFBCredentialFromAuthError,
|
||||||
getGithubCredentialFromResult,
|
getGithubCredentialFromResult,
|
||||||
} from "~/helpers/fb/auth"
|
} from "~/helpers/fb/auth"
|
||||||
@@ -191,32 +190,11 @@ export default defineComponent({
|
|||||||
this.showLoginSuccess()
|
this.showLoginSuccess()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
// An error happened.
|
/*
|
||||||
if (
|
A auth/account-exists-with-different-credential Firebase error wont happen between Google and any other providers
|
||||||
(e as any).code === "auth/account-exists-with-different-credential"
|
Seems Google account overwrites accounts of other providers https://github.com/firebase/firebase-android-sdk/issues/25
|
||||||
) {
|
*/
|
||||||
// Step 2.
|
this.toast.error(`${this.t("error.something_went_wrong")}`)
|
||||||
// User's email already exists.
|
|
||||||
// The pending Google credential.
|
|
||||||
const pendingCred = (e as any).credential
|
|
||||||
this.toast.info(`${this.t("auth.account_exists")}`, {
|
|
||||||
duration: 0,
|
|
||||||
closeOnSwipe: false,
|
|
||||||
action: {
|
|
||||||
text: `${this.t("action.yes")}`,
|
|
||||||
onClick: async (_, toastObject) => {
|
|
||||||
const { user } = await signInUserWithGithub()
|
|
||||||
await linkWithFBCredential(user, pendingCred)
|
|
||||||
|
|
||||||
this.showLoginSuccess()
|
|
||||||
|
|
||||||
toastObject.goAway(0)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.toast.error(`${this.t("error.something_went_wrong")}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.signingInWithGoogle = false
|
this.signingInWithGoogle = false
|
||||||
@@ -228,27 +206,22 @@ export default defineComponent({
|
|||||||
const result = await signInUserWithGithub()
|
const result = await signInUserWithGithub()
|
||||||
const credential = getGithubCredentialFromResult(result)!
|
const credential = getGithubCredentialFromResult(result)!
|
||||||
const token = credential.accessToken
|
const token = credential.accessToken
|
||||||
|
|
||||||
setProviderInfo(result.providerId!, token!)
|
setProviderInfo(result.providerId!, token!)
|
||||||
|
|
||||||
this.showLoginSuccess()
|
this.showLoginSuccess()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
// An error happened.
|
// This user's email is already present in Firebase but with other providers, namely Google or Microsoft
|
||||||
if (
|
if (
|
||||||
(e as any).code === "auth/account-exists-with-different-credential"
|
(e as any).code === "auth/account-exists-with-different-credential"
|
||||||
) {
|
) {
|
||||||
// Step 2.
|
|
||||||
// User's email already exists.
|
|
||||||
this.toast.info(`${this.t("auth.account_exists")}`, {
|
this.toast.info(`${this.t("auth.account_exists")}`, {
|
||||||
duration: 0,
|
duration: 0,
|
||||||
closeOnSwipe: false,
|
closeOnSwipe: false,
|
||||||
action: {
|
action: {
|
||||||
text: `${this.t("action.yes")}`,
|
text: `${this.t("action.yes")}`,
|
||||||
onClick: async (_, toastObject) => {
|
onClick: async (_, toastObject) => {
|
||||||
const { user } = await signInUserWithGoogle()
|
await linkWithFBCredentialFromAuthError(e)
|
||||||
await linkWithFBCredentialFromAuthError(user, e)
|
|
||||||
|
|
||||||
this.showLoginSuccess()
|
this.showLoginSuccess()
|
||||||
|
|
||||||
toastObject.goAway(0)
|
toastObject.goAway(0)
|
||||||
@@ -270,32 +243,15 @@ export default defineComponent({
|
|||||||
this.showLoginSuccess()
|
this.showLoginSuccess()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
// An error happened.
|
/*
|
||||||
if (
|
A auth/account-exists-with-different-credential Firebase error wont happen between MS with Google or Github
|
||||||
(e as any).code === "auth/account-exists-with-different-credential"
|
If a Github account exists and user then logs in with MS email we get a "Something went wrong toast" and console errors and MS replaces GH as only provider.
|
||||||
) {
|
The error messages are as follows:
|
||||||
// Step 2.
|
FirebaseError: Firebase: Error (auth/popup-closed-by-user).
|
||||||
// User's email already exists.
|
@firebase/auth: Auth (9.6.11): INTERNAL ASSERTION FAILED: Pending promise was never set
|
||||||
// The pending Microsoft credential.
|
They may be related to https://github.com/firebase/firebaseui-web/issues/947
|
||||||
const pendingCred = (e as any).credential
|
*/
|
||||||
this.toast.info(`${this.t("auth.account_exists")}`, {
|
this.toast.error(`${this.t("error.something_went_wrong")}`)
|
||||||
duration: 0,
|
|
||||||
closeOnSwipe: false,
|
|
||||||
action: {
|
|
||||||
text: `${this.t("action.yes")}`,
|
|
||||||
onClick: async (_, toastObject) => {
|
|
||||||
const { user } = await signInUserWithGithub()
|
|
||||||
await linkWithFBCredential(user, pendingCred)
|
|
||||||
|
|
||||||
this.showLoginSuccess()
|
|
||||||
|
|
||||||
toastObject.goAway(0)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.toast.error(`${this.t("error.something_went_wrong")}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.signingInWithMicrosoft = false
|
this.signingInWithMicrosoft = false
|
||||||
|
|||||||
@@ -237,19 +237,30 @@ export async function linkWithFBCredential(
|
|||||||
/**
|
/**
|
||||||
* Links account with another account given in a auth/account-exists-with-different-credential error
|
* Links account with another account given in a auth/account-exists-with-different-credential error
|
||||||
*
|
*
|
||||||
* @param user - User who has the errors
|
|
||||||
*
|
|
||||||
* @param error - Error caught after trying to login
|
* @param error - Error caught after trying to login
|
||||||
*
|
*
|
||||||
* @returns Promise of UserCredential
|
* @returns Promise of UserCredential
|
||||||
*/
|
*/
|
||||||
export async function linkWithFBCredentialFromAuthError(
|
export async function linkWithFBCredentialFromAuthError(error: unknown) {
|
||||||
user: User,
|
// credential is not null since this function is called after an auth/account-exists-with-different-credential error, ie credentials actually exist
|
||||||
error: unknown
|
|
||||||
) {
|
|
||||||
// Marked as not null since this function is supposed to be called after an auth/account-exists-with-different-credential error, ie credentials actually exist
|
|
||||||
const credentials = OAuthProvider.credentialFromError(error as AuthError)!
|
const credentials = OAuthProvider.credentialFromError(error as AuthError)!
|
||||||
return await linkWithCredential(user, credentials)
|
|
||||||
|
const otherLinkedProviders = (
|
||||||
|
await getSignInMethodsForEmail((error as AuthError).customData.email!)
|
||||||
|
).filter((providerId) => credentials.providerId !== providerId)
|
||||||
|
|
||||||
|
let user: User | null = null
|
||||||
|
|
||||||
|
if (otherLinkedProviders.indexOf("google.com") >= -1) {
|
||||||
|
user = (await signInUserWithGoogle()).user
|
||||||
|
} else if (otherLinkedProviders.indexOf("github.com") >= -1) {
|
||||||
|
user = (await signInUserWithGithub()).user
|
||||||
|
} else if (otherLinkedProviders.indexOf("microsoft.com") >= -1) {
|
||||||
|
user = (await signInUserWithMicrosoft()).user
|
||||||
|
}
|
||||||
|
|
||||||
|
// user is not null since going through each provider will return a user
|
||||||
|
return await linkWithCredential(user!, credentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user