@@ -21,12 +21,47 @@ import {
21
21
import { FirebaseUIError } from './errors' ;
22
22
import { type TranslationsConfig } from './translations' ;
23
23
24
- function handleFirebaseError ( error : any , translations ?: TranslationsConfig , language ?: string ) : never {
24
+ async function handleFirebaseError (
25
+ error : any ,
26
+ opts ?: { language ?: string ; translations ?: TranslationsConfig ; enableHandleExistingCredential ?: boolean }
27
+ ) : Promise < never | UserCredential > {
28
+ if ( error ?. code === 'auth/account-exists-with-different-credential' && opts ?. enableHandleExistingCredential ) {
29
+ if ( error . credential ) {
30
+ window . sessionStorage . setItem ( 'pendingCred' , JSON . stringify ( error . credential ) ) ;
31
+ }
32
+
33
+ throw new FirebaseUIError (
34
+ {
35
+ code : 'auth/account-exists-with-different-credential' ,
36
+ customData : {
37
+ email : error . customData ?. email ,
38
+ } ,
39
+ } ,
40
+ opts ?. translations ,
41
+ opts ?. language
42
+ ) ;
43
+ }
44
+
25
45
// TODO: Debug why instanceof FirebaseError is not working
26
46
if ( error ?. name === 'FirebaseError' ) {
27
- throw new FirebaseUIError ( error , translations , language ) ;
47
+ throw new FirebaseUIError ( error , opts ?. translations , opts ?. language ) ;
48
+ }
49
+ throw new FirebaseUIError ( { code : 'unknown' } , opts ?. translations , opts ?. language ) ;
50
+ }
51
+
52
+ async function handlePendingCredential ( user : UserCredential ) : Promise < UserCredential > {
53
+ const pendingCredString = window . sessionStorage . getItem ( 'pendingCred' ) ;
54
+ if ( ! pendingCredString ) return user ;
55
+
56
+ try {
57
+ const pendingCred = JSON . parse ( pendingCredString ) ;
58
+ const result = await linkWithCredential ( user . user , pendingCred ) ;
59
+ window . sessionStorage . removeItem ( 'pendingCred' ) ;
60
+ return result ;
61
+ } catch ( error ) {
62
+ window . sessionStorage . removeItem ( 'pendingCred' ) ;
63
+ return user ;
28
64
}
29
- throw new FirebaseUIError ( { code : 'unknown' } , translations , language ) ;
30
65
}
31
66
32
67
export async function fuiSignInWithEmailAndPassword (
@@ -37,19 +72,22 @@ export async function fuiSignInWithEmailAndPassword(
37
72
language ?: string ;
38
73
translations ?: TranslationsConfig ;
39
74
enableAutoUpgradeAnonymous ?: boolean ;
75
+ enableHandleExistingCredential ?: boolean ;
40
76
}
41
77
) : Promise < UserCredential > {
42
78
try {
43
79
const currentUser = auth . currentUser ;
44
80
const credential = EmailAuthProvider . credential ( email , password ) ;
45
81
46
82
if ( currentUser ?. isAnonymous && opts ?. enableAutoUpgradeAnonymous ) {
47
- return await linkWithCredential ( currentUser , credential ) ;
83
+ const result = await linkWithCredential ( currentUser , credential ) ;
84
+ return handlePendingCredential ( result ) ;
48
85
}
49
86
50
- return await signInWithCredential ( auth , credential ) ;
87
+ const result = await signInWithCredential ( auth , credential ) ;
88
+ return handlePendingCredential ( result ) ;
51
89
} catch ( error ) {
52
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
90
+ return await handleFirebaseError ( error , opts ) ;
53
91
}
54
92
}
55
93
@@ -61,19 +99,22 @@ export async function fuiCreateUserWithEmailAndPassword(
61
99
language ?: string ;
62
100
translations ?: TranslationsConfig ;
63
101
enableAutoUpgradeAnonymous ?: boolean ;
102
+ enableHandleExistingCredential ?: boolean ;
64
103
}
65
104
) : Promise < UserCredential > {
66
105
try {
67
106
const currentUser = auth . currentUser ;
68
107
const credential = EmailAuthProvider . credential ( email , password ) ;
69
108
70
109
if ( currentUser ?. isAnonymous && opts ?. enableAutoUpgradeAnonymous ) {
71
- return await linkWithCredential ( currentUser , credential ) ;
110
+ const result = await linkWithCredential ( currentUser , credential ) ;
111
+ return handlePendingCredential ( result ) ;
72
112
}
73
113
74
- return await createUserWithEmailAndPassword ( auth , email , password ) ;
114
+ const result = await createUserWithEmailAndPassword ( auth , email , password ) ;
115
+ return handlePendingCredential ( result ) ;
75
116
} catch ( error ) {
76
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
117
+ return await handleFirebaseError ( error , opts ) ;
77
118
}
78
119
}
79
120
@@ -89,7 +130,7 @@ export async function fuiSignInWithPhoneNumber(
89
130
try {
90
131
return await signInWithPhoneNumber ( auth , phoneNumber , recaptchaVerifier ) ;
91
132
} catch ( error ) {
92
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
133
+ return ( await handleFirebaseError ( error , opts ) ) as never ;
93
134
}
94
135
}
95
136
@@ -100,6 +141,7 @@ export async function fuiConfirmPhoneNumber(
100
141
language ?: string ;
101
142
translations ?: TranslationsConfig ;
102
143
enableAutoUpgradeAnonymous ?: boolean ;
144
+ enableHandleExistingCredential ?: boolean ;
103
145
}
104
146
) : Promise < UserCredential > {
105
147
try {
@@ -109,12 +151,13 @@ export async function fuiConfirmPhoneNumber(
109
151
110
152
if ( currentUser ?. isAnonymous && opts ?. enableAutoUpgradeAnonymous ) {
111
153
const result = await linkWithCredential ( currentUser , credential ) ;
112
- return result ;
154
+ return handlePendingCredential ( result ) ;
113
155
}
114
156
115
- return await signInWithCredential ( auth , credential ) ;
157
+ const result = await signInWithCredential ( auth , credential ) ;
158
+ return handlePendingCredential ( result ) ;
116
159
} catch ( error ) {
117
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
160
+ return await handleFirebaseError ( error , opts ) ;
118
161
}
119
162
}
120
163
@@ -129,7 +172,7 @@ export async function fuiSendPasswordResetEmail(
129
172
try {
130
173
await sendPasswordResetEmail ( auth , email ) ;
131
174
} catch ( error ) {
132
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
175
+ return ( await handleFirebaseError ( error , opts ) ) as never ;
133
176
}
134
177
}
135
178
@@ -156,7 +199,7 @@ export async function fuiSendSignInLinkToEmail(
156
199
await sendSignInLinkToEmail ( auth , email , actionCodeSettings ) ;
157
200
window . localStorage . setItem ( 'emailForSignIn' , email ) ;
158
201
} catch ( error ) {
159
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
202
+ return ( await handleFirebaseError ( error , opts ) ) as never ;
160
203
}
161
204
}
162
205
@@ -172,6 +215,7 @@ export async function fuiSignInWithEmailLink(
172
215
language ?: string ;
173
216
translations ?: TranslationsConfig ;
174
217
enableAutoUpgradeAnonymous ?: boolean ;
218
+ enableHandleExistingCredential ?: boolean ;
175
219
}
176
220
) : Promise < UserCredential > {
177
221
try {
@@ -182,14 +226,14 @@ export async function fuiSignInWithEmailLink(
182
226
if ( currentUser ?. isAnonymous && isAnonymousUpgrade && opts ?. enableAutoUpgradeAnonymous ) {
183
227
const result = await linkWithCredential ( currentUser , credential ) ;
184
228
window . localStorage . removeItem ( 'emailLinkAnonymousUpgrade' ) ;
185
- return result ;
229
+ return handlePendingCredential ( result ) ;
186
230
}
187
231
188
232
const result = await signInWithCredential ( auth , credential ) ;
189
233
window . localStorage . removeItem ( 'emailLinkAnonymousUpgrade' ) ;
190
- return result ;
234
+ return handlePendingCredential ( result ) ;
191
235
} catch ( error ) {
192
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
236
+ return await handleFirebaseError ( error , opts ) ;
193
237
}
194
238
}
195
239
@@ -201,9 +245,10 @@ export async function fuiSignInAnonymously(
201
245
}
202
246
) : Promise < UserCredential > {
203
247
try {
204
- return await signInAnonymously ( auth ) ;
248
+ const result = await signInAnonymously ( auth ) ;
249
+ return handlePendingCredential ( result ) ;
205
250
} catch ( error ) {
206
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
251
+ return await handleFirebaseError ( error , opts ) ;
207
252
}
208
253
}
209
254
@@ -214,6 +259,7 @@ export async function fuiSignInWithOAuth(
214
259
language ?: string ;
215
260
translations ?: TranslationsConfig ;
216
261
enableAutoUpgradeAnonymous ?: boolean ;
262
+ enableHandleExistingCredential ?: boolean ;
217
263
}
218
264
) : Promise < void > {
219
265
try {
@@ -225,7 +271,7 @@ export async function fuiSignInWithOAuth(
225
271
await signInWithRedirect ( auth , provider ) ;
226
272
}
227
273
} catch ( error ) {
228
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
274
+ return ( await handleFirebaseError ( error , opts ) ) as never ;
229
275
}
230
276
}
231
277
@@ -236,6 +282,7 @@ export async function fuiCompleteEmailLinkSignIn(
236
282
language ?: string ;
237
283
translations ?: TranslationsConfig ;
238
284
enableAutoUpgradeAnonymous ?: boolean ;
285
+ enableHandleExistingCredential ?: boolean ;
239
286
}
240
287
) : Promise < UserCredential | null > {
241
288
try {
@@ -248,8 +295,8 @@ export async function fuiCompleteEmailLinkSignIn(
248
295
249
296
const result = await fuiSignInWithEmailLink ( auth , email , currentUrl , opts ) ;
250
297
window . localStorage . removeItem ( 'emailForSignIn' ) ;
251
- return result ;
298
+ return handlePendingCredential ( result ) ;
252
299
} catch ( error ) {
253
- handleFirebaseError ( error , opts ?. translations , opts ?. language ) ;
300
+ return await handleFirebaseError ( error , opts ) ;
254
301
}
255
302
}
0 commit comments