'Firebase Typescript API auth - account-exists-with-different-credential
hope anyone can help me with my problems. I created a login page with a firebase where I can login with facebook and gmail. but unfortunately, it gives me an error with a code (auth/account-exists-with-different-credential). can somebody give me a clue what can I do to solve this problem?
here is my code
const actions: ActionTree<RootState, RootState> = {
onAuthStateChangedAction(
state,
{ authUser }: { authUser: User; additionalUserInfo: AdditionalUserInfo }
) {
if (authUser) {
// bind user data, so do not need to bind on each components
this.dispatch('users/bindCurrentUser')
}
if (!authUser) {
// remove state
state.commit('SET_USER', null)
// redirect from here
return this.$router.push({
path: '/',
})
}
// check login or register
const { uid, email, emailVerified, displayName, photoURL } = authUser
state.commit('SET_USER', {
uid,
email,
emailVerified,
displayName,
photoURL,
})
},
// request otp
async requestOTP(_state, { email }: { email: string }) {
const functionRef = this.$fire.functions.httpsCallable('authRequestOTP')
await functionRef({ email })
},
// login with otp
async loginWithOTP(
_state,
{
email,
otp,
referralCode,
}: { email: string; otp: string; referralCode?: string }
) {
const functionRef = this.$fire.functions.httpsCallable('authVerifyOTP')
const token = (await functionRef({ email, otp })).data
if (!token) throw new Error('token not valid')
// login with selected auth provider
const result = await this.$fire.auth.signInWithCustomToken(token)
if (!result) throw new Error('error')
// check if new user
const { user } = result
if (!user || !user.uid) throw new Error('no user object')
const userSnap = await this.$fire.firestore
.collection(COLLECTION.USER)
.doc(user.uid)
.get()
// if new user, add to collection
// and go to
let nextPage = 'profile-user'
if (!userSnap.exists) {
const newUserData = {
id: user.uid,
name: '',
email,
phone: '',
imageUrl: '',
}
this.dispatch('users/add', newUserData)
nextPage = 'auth-profile'
}
return this.$router.push({ name: nextPage, query: { code: referralCode } })
},
// login with provider
async login(
_state,
{ provider, referralCode }: { provider: string; referralCode?: string }
) {
let authProvider = null
// prepare auth provider
if (provider === 'google')
authProvider = new this.$fireModule.auth.GoogleAuthProvider()
if (provider === 'facebook')
authProvider = new this.$fireModule.auth.FacebookAuthProvider()
if (!authProvider) throw new Error('error')
// login with selected auth provider
const result = await this.$fire.auth.signInWithPopup(authProvider)
if (!result) throw new Error('error')
// parse result
const { user, additionalUserInfo } = result
if (!user) throw new Error('no user object')
const { isNewUser, profile, username } = additionalUserInfo ?? {}
const userProfile = profile as
| GoogleAdditionalUserInfo
| FacebookAdditionalUserInfo
| null
// if new user, add to collection
let nextPage = 'profile-user'
if (isNewUser) {
const newUserData = {
id: user.uid,
name: username ?? user.displayName,
email: userProfile?.email ?? user.email,
phone: user.phoneNumber ?? '',
imageUrl: userProfile?.picture ?? user.photoURL,
}
this.dispatch('users/add', newUserData)
nextPage = 'auth-profile'
}
this.$router.push({ name: nextPage, query: { code: referralCode } })
},
// complete profile
async completeProfile(
_state,
{
id,
phone,
name,
referralCode,
}: { id: string; phone: string; name: string; referralCode: string }
) {
// update user profile
await this.$fire.firestore.collection(COLLECTION.USER).doc(id).update({
phone,
name,
})
// claim referral reward
if (referralCode) {
await this.$fire.functions.httpsCallable('referralClaim')({
referredId: id,
code: referralCode,
})
}
return true
},
}
Solution 1:[1]
That error message typically indicates that an account exists with that email address, but that either the password doesn't match or (more likely here) that the existing account is with a different provider than the one that's trying to sign in now. Simpler put: you signed in to that account with Facebook before and are now trying to sign in with Google (or vice versa).
While it is possible to associate multiple providers (like Facebook and Google) with a single user account, this does require that you link those providers to the account.
If you're not trying to link multiple providers, but don't know what provider the user used previously, the flow normally is:
- Ask the user to enter their email address (or get it from somewhere else).
- Call
fetchSignInMethodsForEmailto determine which providers can be used to sign in with that email address. - Call the correct sign-in method, or show a screen allowing the user to pick the provider to sign in with (if there are multiple providers in step 2).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Frank van Puffelen |
