@react-native-firebase/auth 24.1.1 → 25.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java +16 -4
  3. package/dist/module/ActionCodeURL.js +140 -0
  4. package/dist/module/ActionCodeURL.js.map +1 -0
  5. package/{lib → dist/module}/ConfirmationResult.js +4 -5
  6. package/dist/module/ConfirmationResult.js.map +1 -0
  7. package/{lib → dist/module}/MultiFactorResolver.js +14 -5
  8. package/dist/module/MultiFactorResolver.js.map +1 -0
  9. package/{lib → dist/module}/PhoneAuthListener.js +52 -75
  10. package/dist/module/PhoneAuthListener.js.map +1 -0
  11. package/dist/module/PhoneAuthState.js +25 -0
  12. package/dist/module/PhoneAuthState.js.map +1 -0
  13. package/dist/module/PhoneMultiFactorGenerator.js +39 -0
  14. package/dist/module/PhoneMultiFactorGenerator.js.map +1 -0
  15. package/{lib → dist/module}/Settings.js +3 -7
  16. package/dist/module/Settings.js.map +1 -0
  17. package/{lib → dist/module}/TotpMultiFactorGenerator.js +20 -15
  18. package/dist/module/TotpMultiFactorGenerator.js.map +1 -0
  19. package/{lib → dist/module}/TotpSecret.js +7 -5
  20. package/dist/module/TotpSecret.js.map +1 -0
  21. package/dist/module/User.js +245 -0
  22. package/dist/module/User.js.map +1 -0
  23. package/dist/module/constants.js +54 -0
  24. package/dist/module/constants.js.map +1 -0
  25. package/dist/module/credentials/AuthCredential.js +51 -0
  26. package/dist/module/credentials/AuthCredential.js.map +1 -0
  27. package/dist/module/credentials/EmailAuthCredential.js +51 -0
  28. package/dist/module/credentials/EmailAuthCredential.js.map +1 -0
  29. package/dist/module/credentials/OAuthCredential.js +84 -0
  30. package/dist/module/credentials/OAuthCredential.js.map +1 -0
  31. package/dist/module/credentials/PhoneAuthCredential.js +50 -0
  32. package/dist/module/credentials/PhoneAuthCredential.js.map +1 -0
  33. package/{lib/providers/GoogleAuthProvider.js → dist/module/credentials/index.js} +7 -19
  34. package/dist/module/credentials/index.js.map +1 -0
  35. package/{lib → dist/module}/getMultiFactorResolver.js +5 -8
  36. package/dist/module/getMultiFactorResolver.js.map +1 -0
  37. package/{lib/providers/FacebookAuthProvider.js → dist/module/index.js} +11 -18
  38. package/dist/module/index.js.map +1 -0
  39. package/dist/module/modular.js +779 -0
  40. package/dist/module/modular.js.map +1 -0
  41. package/{lib → dist/module}/multiFactor.js +16 -14
  42. package/dist/module/multiFactor.js.map +1 -0
  43. package/dist/module/namespaced.js +522 -0
  44. package/dist/module/namespaced.js.map +1 -0
  45. package/dist/module/package.json +1 -0
  46. package/dist/module/password-policy/PasswordPolicyImpl.js +103 -0
  47. package/dist/module/password-policy/PasswordPolicyImpl.js.map +1 -0
  48. package/{lib → dist/module}/password-policy/PasswordPolicyMixin.js +14 -16
  49. package/dist/module/password-policy/PasswordPolicyMixin.js.map +1 -0
  50. package/{lib → dist/module}/password-policy/passwordPolicyApi.js +18 -12
  51. package/dist/module/password-policy/passwordPolicyApi.js.map +1 -0
  52. package/{lib → dist/module}/providers/AppleAuthProvider.js +14 -7
  53. package/dist/module/providers/AppleAuthProvider.js.map +1 -0
  54. package/{lib → dist/module}/providers/EmailAuthProvider.js +10 -25
  55. package/dist/module/providers/EmailAuthProvider.js.map +1 -0
  56. package/dist/module/providers/FacebookAuthProvider.js +56 -0
  57. package/dist/module/providers/FacebookAuthProvider.js.map +1 -0
  58. package/dist/module/providers/GithubAuthProvider.js +49 -0
  59. package/dist/module/providers/GithubAuthProvider.js.map +1 -0
  60. package/dist/module/providers/GoogleAuthProvider.js +57 -0
  61. package/dist/module/providers/GoogleAuthProvider.js.map +1 -0
  62. package/dist/module/providers/OAuthProvider.js +116 -0
  63. package/dist/module/providers/OAuthProvider.js.map +1 -0
  64. package/{lib → dist/module}/providers/OIDCAuthProvider.js +15 -7
  65. package/dist/module/providers/OIDCAuthProvider.js.map +1 -0
  66. package/dist/module/providers/PhoneAuthProvider.js +87 -0
  67. package/dist/module/providers/PhoneAuthProvider.js.map +1 -0
  68. package/dist/module/providers/TwitterAuthProvider.js +50 -0
  69. package/dist/module/providers/TwitterAuthProvider.js.map +1 -0
  70. package/dist/module/types/auth.js +43 -0
  71. package/dist/module/types/auth.js.map +1 -0
  72. package/dist/module/types/internal.js +4 -0
  73. package/dist/module/types/internal.js.map +1 -0
  74. package/dist/module/types/namespaced.js +62 -0
  75. package/dist/module/types/namespaced.js.map +1 -0
  76. package/dist/module/version.js +5 -0
  77. package/dist/module/version.js.map +1 -0
  78. package/dist/module/web/RNFBAuthModule.android.js +5 -0
  79. package/dist/module/web/RNFBAuthModule.android.js.map +1 -0
  80. package/dist/module/web/RNFBAuthModule.ios.js +5 -0
  81. package/dist/module/web/RNFBAuthModule.ios.js.map +1 -0
  82. package/{lib → dist/module}/web/RNFBAuthModule.js +104 -321
  83. package/dist/module/web/RNFBAuthModule.js.map +1 -0
  84. package/dist/typescript/lib/ActionCodeURL.d.ts +41 -0
  85. package/dist/typescript/lib/ActionCodeURL.d.ts.map +1 -0
  86. package/dist/typescript/lib/ConfirmationResult.d.ts +10 -0
  87. package/dist/typescript/lib/ConfirmationResult.d.ts.map +1 -0
  88. package/dist/typescript/lib/MultiFactorResolver.d.ts +24 -0
  89. package/dist/typescript/lib/MultiFactorResolver.d.ts.map +1 -0
  90. package/dist/typescript/lib/PhoneAuthListener.d.ts +34 -0
  91. package/dist/typescript/lib/PhoneAuthListener.d.ts.map +1 -0
  92. package/dist/typescript/lib/PhoneAuthState.d.ts +7 -0
  93. package/dist/typescript/lib/PhoneAuthState.d.ts.map +1 -0
  94. package/dist/typescript/lib/PhoneMultiFactorGenerator.d.ts +7 -0
  95. package/dist/typescript/lib/PhoneMultiFactorGenerator.d.ts.map +1 -0
  96. package/dist/typescript/lib/Settings.d.ts +13 -0
  97. package/dist/typescript/lib/Settings.d.ts.map +1 -0
  98. package/dist/typescript/lib/TotpMultiFactorGenerator.d.ts +11 -0
  99. package/dist/typescript/lib/TotpMultiFactorGenerator.d.ts.map +1 -0
  100. package/dist/typescript/lib/TotpSecret.d.ts +33 -0
  101. package/dist/typescript/lib/TotpSecret.d.ts.map +1 -0
  102. package/dist/typescript/lib/User.d.ts +51 -0
  103. package/dist/typescript/lib/User.d.ts.map +1 -0
  104. package/dist/typescript/lib/constants.d.ts +35 -0
  105. package/dist/typescript/lib/constants.d.ts.map +1 -0
  106. package/dist/typescript/lib/credentials/AuthCredential.d.ts +12 -0
  107. package/dist/typescript/lib/credentials/AuthCredential.d.ts.map +1 -0
  108. package/dist/typescript/lib/credentials/EmailAuthCredential.d.ts +8 -0
  109. package/dist/typescript/lib/credentials/EmailAuthCredential.d.ts.map +1 -0
  110. package/dist/typescript/lib/credentials/OAuthCredential.d.ts +22 -0
  111. package/dist/typescript/lib/credentials/OAuthCredential.d.ts.map +1 -0
  112. package/dist/typescript/lib/credentials/PhoneAuthCredential.d.ts +8 -0
  113. package/dist/typescript/lib/credentials/PhoneAuthCredential.d.ts.map +1 -0
  114. package/dist/typescript/lib/credentials/index.d.ts +5 -0
  115. package/dist/typescript/lib/credentials/index.d.ts.map +1 -0
  116. package/dist/typescript/lib/getMultiFactorResolver.d.ts +19 -0
  117. package/dist/typescript/lib/getMultiFactorResolver.d.ts.map +1 -0
  118. package/dist/typescript/lib/index.d.ts +8 -0
  119. package/dist/typescript/lib/index.d.ts.map +1 -0
  120. package/dist/typescript/lib/modular.d.ts +360 -0
  121. package/dist/typescript/lib/modular.d.ts.map +1 -0
  122. package/dist/typescript/lib/multiFactor.d.ts +26 -0
  123. package/dist/typescript/lib/multiFactor.d.ts.map +1 -0
  124. package/dist/typescript/lib/namespaced.d.ts +12 -0
  125. package/dist/typescript/lib/namespaced.d.ts.map +1 -0
  126. package/dist/typescript/lib/password-policy/PasswordPolicyImpl.d.ts +19 -0
  127. package/dist/typescript/lib/password-policy/PasswordPolicyImpl.d.ts.map +1 -0
  128. package/dist/typescript/lib/password-policy/PasswordPolicyMixin.d.ts +11 -0
  129. package/dist/typescript/lib/password-policy/PasswordPolicyMixin.d.ts.map +1 -0
  130. package/dist/typescript/lib/password-policy/passwordPolicyApi.d.ts +10 -0
  131. package/dist/typescript/lib/password-policy/passwordPolicyApi.d.ts.map +1 -0
  132. package/dist/typescript/lib/providers/AppleAuthProvider.d.ts +16 -0
  133. package/dist/typescript/lib/providers/AppleAuthProvider.d.ts.map +1 -0
  134. package/dist/typescript/lib/providers/EmailAuthProvider.d.ts +11 -0
  135. package/dist/typescript/lib/providers/EmailAuthProvider.d.ts.map +1 -0
  136. package/dist/typescript/lib/providers/FacebookAuthProvider.d.ts +19 -0
  137. package/dist/typescript/lib/providers/FacebookAuthProvider.d.ts.map +1 -0
  138. package/dist/typescript/lib/providers/GithubAuthProvider.d.ts +15 -0
  139. package/dist/typescript/lib/providers/GithubAuthProvider.d.ts.map +1 -0
  140. package/dist/typescript/lib/providers/GoogleAuthProvider.d.ts +21 -0
  141. package/dist/typescript/lib/providers/GoogleAuthProvider.d.ts.map +1 -0
  142. package/dist/typescript/lib/providers/OAuthProvider.d.ts +33 -0
  143. package/dist/typescript/lib/providers/OAuthProvider.d.ts.map +1 -0
  144. package/dist/typescript/lib/providers/OIDCAuthProvider.d.ts +16 -0
  145. package/dist/typescript/lib/providers/OIDCAuthProvider.d.ts.map +1 -0
  146. package/dist/typescript/lib/providers/PhoneAuthProvider.d.ts +16 -0
  147. package/dist/typescript/lib/providers/PhoneAuthProvider.d.ts.map +1 -0
  148. package/dist/typescript/lib/providers/TwitterAuthProvider.d.ts +15 -0
  149. package/dist/typescript/lib/providers/TwitterAuthProvider.d.ts.map +1 -0
  150. package/dist/typescript/lib/types/auth.d.ts +305 -0
  151. package/dist/typescript/lib/types/auth.d.ts.map +1 -0
  152. package/dist/typescript/lib/types/internal.d.ts +292 -0
  153. package/dist/typescript/lib/types/internal.d.ts.map +1 -0
  154. package/dist/typescript/lib/types/namespaced.d.ts +2185 -0
  155. package/dist/typescript/lib/types/namespaced.d.ts.map +1 -0
  156. package/dist/typescript/lib/version.d.ts +2 -0
  157. package/dist/typescript/lib/version.d.ts.map +1 -0
  158. package/dist/typescript/lib/web/RNFBAuthModule.android.d.ts +3 -0
  159. package/dist/typescript/lib/web/RNFBAuthModule.android.d.ts.map +1 -0
  160. package/dist/typescript/lib/web/RNFBAuthModule.d.ts +406 -0
  161. package/dist/typescript/lib/web/RNFBAuthModule.d.ts.map +1 -0
  162. package/dist/typescript/lib/web/RNFBAuthModule.ios.d.ts +3 -0
  163. package/dist/typescript/lib/web/RNFBAuthModule.ios.d.ts.map +1 -0
  164. package/dist/typescript/package.json +1 -0
  165. package/ios/RNFBAuth/RNFBAuthModule.m +4 -2
  166. package/lib/ActionCodeURL.ts +174 -0
  167. package/lib/ConfirmationResult.ts +42 -0
  168. package/lib/MultiFactorResolver.ts +51 -0
  169. package/lib/PhoneAuthListener.ts +312 -0
  170. package/lib/PhoneAuthState.ts +22 -0
  171. package/lib/{PhoneMultiFactorGenerator.js → PhoneMultiFactorGenerator.ts} +8 -2
  172. package/lib/Settings.ts +59 -0
  173. package/lib/TotpMultiFactorGenerator.ts +78 -0
  174. package/lib/TotpSecret.ts +71 -0
  175. package/lib/{User.js → User.ts} +127 -83
  176. package/lib/constants.ts +55 -0
  177. package/lib/credentials/AuthCredential.ts +55 -0
  178. package/lib/credentials/EmailAuthCredential.ts +70 -0
  179. package/lib/credentials/OAuthCredential.ts +113 -0
  180. package/lib/credentials/PhoneAuthCredential.ts +66 -0
  181. package/lib/{providers/GithubAuthProvider.js → credentials/index.ts} +4 -19
  182. package/lib/getMultiFactorResolver.ts +40 -0
  183. package/lib/{providers/TwitterAuthProvider.js → index.ts} +14 -19
  184. package/lib/modular.ts +1158 -0
  185. package/lib/multiFactor.ts +83 -0
  186. package/lib/namespaced.ts +846 -0
  187. package/lib/password-policy/{PasswordPolicyImpl.js → PasswordPolicyImpl.ts} +37 -19
  188. package/lib/password-policy/PasswordPolicyMixin.ts +83 -0
  189. package/lib/password-policy/passwordPolicyApi.ts +60 -0
  190. package/lib/providers/AppleAuthProvider.ts +44 -0
  191. package/lib/providers/EmailAuthProvider.ts +42 -0
  192. package/lib/providers/FacebookAuthProvider.ts +58 -0
  193. package/lib/providers/GithubAuthProvider.ts +51 -0
  194. package/lib/providers/GoogleAuthProvider.ts +60 -0
  195. package/lib/providers/OAuthProvider.ts +150 -0
  196. package/lib/providers/OIDCAuthProvider.ts +49 -0
  197. package/lib/providers/PhoneAuthProvider.ts +161 -0
  198. package/lib/providers/TwitterAuthProvider.ts +52 -0
  199. package/lib/types/auth.ts +393 -0
  200. package/lib/types/internal.ts +474 -0
  201. package/lib/{index.d.ts → types/namespaced.ts} +52 -41
  202. package/lib/version.ts +2 -0
  203. package/lib/web/RNFBAuthModule.ts +1359 -0
  204. package/package.json +41 -9
  205. package/plugin/tsconfig.tsbuildinfo +1 -1
  206. package/tsconfig.json +26 -0
  207. package/tsdoc.json +22 -0
  208. package/typedoc.json +9 -2
  209. package/lib/index.js +0 -572
  210. package/lib/modular/index.d.ts +0 -801
  211. package/lib/modular/index.js +0 -651
  212. package/lib/providers/OAuthProvider.js +0 -70
  213. package/lib/providers/PhoneAuthProvider.js +0 -52
  214. package/lib/version.js +0 -2
  215. /package/lib/web/{RNFBAuthModule.android.js → RNFBAuthModule.android.ts} +0 -0
  216. /package/lib/web/{RNFBAuthModule.ios.js → RNFBAuthModule.ios.ts} +0 -0
@@ -0,0 +1,1359 @@
1
+ import { Platform } from 'react-native';
2
+ import * as firebaseAuthModule from '@react-native-firebase/app/dist/module/internal/web/firebaseAuth';
3
+ import {
4
+ getApp,
5
+ initializeAuth,
6
+ onAuthStateChanged,
7
+ onIdTokenChanged,
8
+ signInAnonymously,
9
+ sendSignInLinkToEmail,
10
+ getAdditionalUserInfo,
11
+ multiFactor,
12
+ getMultiFactorResolver,
13
+ TotpMultiFactorGenerator,
14
+ createUserWithEmailAndPassword,
15
+ signInWithEmailAndPassword,
16
+ isSignInWithEmailLink,
17
+ signInWithEmailLink,
18
+ signInWithCustomToken,
19
+ sendPasswordResetEmail,
20
+ useDeviceLanguage,
21
+ verifyPasswordResetCode,
22
+ connectAuthEmulator,
23
+ fetchSignInMethodsForEmail,
24
+ sendEmailVerification,
25
+ verifyBeforeUpdateEmail,
26
+ confirmPasswordReset,
27
+ updateEmail,
28
+ updatePassword,
29
+ updateProfile,
30
+ updatePhoneNumber,
31
+ signInWithCredential,
32
+ unlink,
33
+ linkWithCredential,
34
+ reauthenticateWithCredential,
35
+ getIdToken,
36
+ getIdTokenResult,
37
+ applyActionCode,
38
+ checkActionCode,
39
+ EmailAuthProvider,
40
+ FacebookAuthProvider,
41
+ GoogleAuthProvider,
42
+ TwitterAuthProvider,
43
+ GithubAuthProvider,
44
+ PhoneAuthProvider,
45
+ OAuthProvider,
46
+ } from '@react-native-firebase/app/dist/module/internal/web/firebaseAuth';
47
+ import type {
48
+ ActionCodeSettings,
49
+ Auth,
50
+ AuthCredential,
51
+ MultiFactorInfo,
52
+ MultiFactorError,
53
+ MultiFactorSession,
54
+ MultiFactorResolver,
55
+ PhoneAuthCredential,
56
+ TotpSecret as WebTotpSecret,
57
+ Unsubscribe,
58
+ User,
59
+ UserCredential,
60
+ UserInfo,
61
+ UserMetadata,
62
+ } from '@react-native-firebase/app/dist/module/internal/web/firebaseAuth';
63
+ import {
64
+ guard,
65
+ getWebError,
66
+ emitEvent,
67
+ } from '@react-native-firebase/app/dist/module/internal/web/utils';
68
+ import {
69
+ getReactNativeAsyncStorageInternal,
70
+ isMemoryStorage,
71
+ } from '@react-native-firebase/app/dist/module/internal/asyncStorage';
72
+ type UserInfoObject = {
73
+ providerId: string;
74
+ uid: string;
75
+ displayName: string | null;
76
+ email: string | null;
77
+ photoURL: string | null;
78
+ phoneNumber: string | null;
79
+ };
80
+
81
+ type WebErrorLike = {
82
+ name?: string;
83
+ code?: string;
84
+ message: string;
85
+ details?: unknown;
86
+ customData?: unknown;
87
+ userInfo?: Record<string, unknown>;
88
+ };
89
+
90
+ type MultiFactorInfoObject = {
91
+ displayName?: string | null;
92
+ enrollmentTime: string;
93
+ factorId: string;
94
+ uid: string;
95
+ phoneNumber?: string | null;
96
+ };
97
+
98
+ type UserMetadataObject = {
99
+ creationTime: string | null;
100
+ lastSignInTime: string | null;
101
+ };
102
+
103
+ type UserObject = UserInfoObject & {
104
+ emailVerified: boolean;
105
+ isAnonymous: boolean;
106
+ tenantId: string | null;
107
+ providerData: UserInfoObject[];
108
+ metadata: UserMetadataObject;
109
+ multiFactor: {
110
+ enrolledFactors: MultiFactorInfoObject[];
111
+ };
112
+ };
113
+
114
+ type AuthResultObject = {
115
+ user: UserObject;
116
+ additionalUserInfo: {
117
+ isNewUser: boolean;
118
+ profile: Record<string, unknown> | null;
119
+ providerId: string | null;
120
+ username?: string | null;
121
+ } | null;
122
+ };
123
+
124
+ const getReactNativePersistence =
125
+ (
126
+ firebaseAuthModule as unknown as {
127
+ getReactNativePersistence?: (storage: unknown) => unknown;
128
+ }
129
+ ).getReactNativePersistence ?? ((storage: unknown) => storage);
130
+
131
+ /**
132
+ * Resolves or rejects an auth method promise without a user (user was missing).
133
+ * @param {boolean} isError whether to reject the promise.
134
+ * @returns {Promise<void>} - Void promise.
135
+ */
136
+ function promiseNoUser(isError = false): Promise<null> {
137
+ if (isError) {
138
+ return rejectPromiseWithCodeAndMessage('no-current-user', 'No user currently signed in.');
139
+ }
140
+
141
+ // TODO(ehesp): Should this be null, or undefined?
142
+ return Promise.resolve(null);
143
+ }
144
+
145
+ /**
146
+ * Returns a structured error object.
147
+ * @param {string} code - The error code.
148
+ * @param {string} message - The error message.
149
+ */
150
+ function rejectPromiseWithCodeAndMessage(code: string, message: string): Promise<never> {
151
+ return rejectPromise(getWebError({ name: 'FirebaseError', code: `auth/${code}`, message }));
152
+ }
153
+
154
+ function rejectWithCodeAndMessage(code: string, message: string): Promise<never> {
155
+ return Promise.reject(
156
+ getWebError({
157
+ name: 'FirebaseError',
158
+ code,
159
+ message,
160
+ }),
161
+ );
162
+ }
163
+
164
+ /**
165
+ * Returns a structured error object.
166
+ * @param {error} error The error object.
167
+ * @returns {never}
168
+ */
169
+ function rejectPromise(error: WebErrorLike): Promise<never> {
170
+ const { code, message, details } = error;
171
+ const nativeError = {
172
+ code: code ?? 'auth/unknown',
173
+ message,
174
+ userInfo: {
175
+ code: code ? code.replace('auth/', '') : 'unknown',
176
+ message,
177
+ details,
178
+ },
179
+ };
180
+ return Promise.reject(nativeError);
181
+ }
182
+
183
+ /**
184
+ * Converts a user object to a plain object.
185
+ * @param {User} user - The User object to convert.
186
+ * @returns {object}
187
+ */
188
+ function userToObject(user: User): UserObject {
189
+ return {
190
+ ...userInfoToObject(user),
191
+ emailVerified: user.emailVerified,
192
+ isAnonymous: user.isAnonymous,
193
+ tenantId: user.tenantId !== null && user.tenantId !== '' ? user.tenantId : null,
194
+ providerData: user.providerData.map(userInfoToObject),
195
+ metadata: userMetadataToObject(user.metadata),
196
+ multiFactor: {
197
+ enrolledFactors: multiFactor(user).enrolledFactors.map(multiFactorInfoToObject),
198
+ },
199
+ };
200
+ }
201
+
202
+ /**
203
+ * Returns an AuthCredential object for the given provider.
204
+ * @param {Auth} auth - The Auth instance to use.
205
+ * @param {string} provider - The provider to get the credential for.
206
+ * @param {string} token - The token to use for the credential.
207
+ * @param {string|null} secret - The secret to use for the credential.
208
+ * @returns {AuthCredential|null} - The AuthCredential object.
209
+ */
210
+ function getAuthCredential(
211
+ _auth: Auth,
212
+ provider: string,
213
+ token: string,
214
+ secret?: string | null,
215
+ ): AuthCredential | null {
216
+ if (provider.startsWith('oidc.')) {
217
+ return new OAuthProvider(provider).credential({
218
+ idToken: token,
219
+ });
220
+ }
221
+
222
+ switch (provider) {
223
+ case 'facebook.com':
224
+ return FacebookAuthProvider.credential(token);
225
+ case 'google.com':
226
+ return GoogleAuthProvider.credential(token, secret ?? null);
227
+ case 'twitter.com':
228
+ return TwitterAuthProvider.credential(token, secret ?? '');
229
+ case 'github.com':
230
+ return GithubAuthProvider.credential(token);
231
+ case 'apple.com':
232
+ return new OAuthProvider(provider).credential({
233
+ idToken: token,
234
+ rawNonce: secret ?? undefined,
235
+ });
236
+ case 'oauth':
237
+ return new OAuthProvider(provider).credential({
238
+ idToken: token || undefined,
239
+ accessToken: secret ?? undefined,
240
+ });
241
+ case 'phone':
242
+ return PhoneAuthProvider.credential(token, secret ?? '');
243
+ case 'password':
244
+ return EmailAuthProvider.credential(token, secret ?? '');
245
+ case 'emailLink':
246
+ return EmailAuthProvider.credentialWithLink(token, secret ?? '');
247
+ default:
248
+ return null;
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Converts a user info object to a plain object.
254
+ * @param {UserInfo} userInfo - The UserInfo object to convert.
255
+ */
256
+ function userInfoToObject(userInfo: UserInfo): UserInfoObject {
257
+ return {
258
+ providerId: userInfo.providerId,
259
+ uid: userInfo.uid,
260
+ displayName:
261
+ userInfo.displayName !== null && userInfo.displayName !== '' ? userInfo.displayName : null,
262
+ email: userInfo.email !== null && userInfo.email !== '' ? userInfo.email : null,
263
+ photoURL: userInfo.photoURL !== null && userInfo.photoURL !== '' ? userInfo.photoURL : null,
264
+ phoneNumber:
265
+ userInfo.phoneNumber !== null && userInfo.phoneNumber !== '' ? userInfo.phoneNumber : null,
266
+ };
267
+ }
268
+
269
+ /**
270
+ * Converts a user metadata object to a plain object.
271
+ * @param {UserMetadata} metadata - The UserMetadata object to convert.
272
+ */
273
+ function userMetadataToObject(metadata: UserMetadata): UserMetadataObject {
274
+ return {
275
+ creationTime: metadata.creationTime ? new Date(metadata.creationTime).toISOString() : null,
276
+ lastSignInTime: metadata.lastSignInTime
277
+ ? new Date(metadata.lastSignInTime).toISOString()
278
+ : null,
279
+ };
280
+ }
281
+
282
+ /**
283
+ * Converts a MultiFactorInfo object to a plain object.
284
+ * @param {MultiFactorInfo} multiFactorInfo - The MultiFactorInfo object to convert.
285
+ */
286
+ function multiFactorInfoToObject(multiFactorInfo: MultiFactorInfo): MultiFactorInfoObject {
287
+ const obj: MultiFactorInfoObject = {
288
+ displayName: multiFactorInfo.displayName,
289
+ enrollmentTime: multiFactorInfo.enrollmentTime,
290
+ factorId: multiFactorInfo.factorId,
291
+ uid: multiFactorInfo.uid,
292
+ };
293
+
294
+ // If https://firebase.google.com/docs/reference/js/auth.phonemultifactorinfo
295
+ if ('phoneNumber' in multiFactorInfo) {
296
+ obj.phoneNumber = (
297
+ multiFactorInfo as MultiFactorInfo & { phoneNumber?: string | null }
298
+ ).phoneNumber;
299
+ }
300
+
301
+ return obj;
302
+ }
303
+
304
+ /**
305
+ * Converts a user credential object to a plain object.
306
+ * @param {UserCredential} userCredential - The user credential object to convert.
307
+ */
308
+ function authResultToObject(userCredential: UserCredential): AuthResultObject {
309
+ const additional = getAdditionalUserInfo(userCredential);
310
+ return {
311
+ user: userToObject(userCredential.user),
312
+ additionalUserInfo: additional
313
+ ? {
314
+ isNewUser: additional.isNewUser,
315
+ profile: (additional.profile as Record<string, unknown> | null) ?? null,
316
+ providerId: additional.providerId,
317
+ username: additional.username,
318
+ }
319
+ : null,
320
+ };
321
+ }
322
+
323
+ const instances: Record<string, Auth | undefined> = {};
324
+ const authStateListeners: Record<string, Unsubscribe | undefined> = {};
325
+ const idTokenListeners: Record<string, Unsubscribe | undefined> = {};
326
+ const sessionMap = new Map<string, MultiFactorSession>();
327
+ const totpSecretMap = new Map<string, WebTotpSecret>();
328
+ let sessionId = 0;
329
+
330
+ // Returns a cached Firestore instance.
331
+ function getCachedAuthInstance(appName: string): Auth {
332
+ if (!instances[appName]) {
333
+ if (isMemoryStorage()) {
334
+ // Warn auth persistence is is disabled unless Async Storage implementation is provided.
335
+ // eslint-disable-next-line no-console
336
+ console.warn(
337
+ 'Firebase Auth persistence is disabled. To enable persistence, provide an Async Storage implementation.\n' +
338
+ '\n' +
339
+ 'For example, to use React Native Async Storage:\n' +
340
+ '\n' +
341
+ " import AsyncStorage from '@react-native-async-storage/async-storage';\n" +
342
+ '\n' +
343
+ ' // Before initializing Firebase set the Async Storage implementation\n' +
344
+ ' // that will be used to persist user sessions.\n' +
345
+ ' firebase.setReactNativeAsyncStorage(AsyncStorage);\n' +
346
+ '\n' +
347
+ ' // Then initialize Firebase as normal.\n' +
348
+ ' await firebase.initializeApp({ ... });\n',
349
+ );
350
+ }
351
+
352
+ const authOptions: { persistence?: unknown } = {};
353
+ if (Platform.OS !== 'web') {
354
+ // Non-web platforms pull the react-native export from package.json and
355
+ // get a bundle that defines `getReactNativePersistence` etc, but web platforms
356
+ // do *not* have that method defined. So we only call it for non-web platforms
357
+ authOptions.persistence = getReactNativePersistence(getReactNativeAsyncStorageInternal());
358
+ }
359
+
360
+ instances[appName] = initializeAuth(getApp(appName), authOptions as never);
361
+ }
362
+ return instances[appName];
363
+ }
364
+
365
+ // getConstants
366
+ const CONSTANTS: {
367
+ APP_LANGUAGE: Record<string, string | null | undefined>;
368
+ APP_USER: Record<string, UserObject | undefined>;
369
+ } = {
370
+ APP_LANGUAGE: {},
371
+ APP_USER: {},
372
+ };
373
+
374
+ // Not required for web, since it's dynamic initialization
375
+ // and we are not making instances of auth based on apps that already exist
376
+ // since there are none that exist before we initialize them in our code below.
377
+ // for (const appName of getApps()) {
378
+ // const instance = getAuth(getApp(appName));
379
+ // CONSTANTS.APP_LANGUAGE[appName] = instance.languageCode;
380
+ // if (instance.currentUser) {
381
+ // CONSTANTS.APP_USER[appName] = userToObject(instance.currentUser);
382
+ // }
383
+ // }
384
+
385
+ /**
386
+ * This is a 'NativeModule' for the web platform.
387
+ * Methods here are identical to the ones found in
388
+ * the native android/ios modules e.g. `@ReactMethod` annotated
389
+ * java methods on Android.
390
+ */
391
+ export default {
392
+ // Expose all the constants.
393
+ ...CONSTANTS,
394
+
395
+ async useUserAccessGroup() {
396
+ // noop
397
+ },
398
+
399
+ configureAuthDomain() {
400
+ return rejectPromiseWithCodeAndMessage(
401
+ 'unsupported',
402
+ 'This operation is not supported in this environment.',
403
+ );
404
+ },
405
+
406
+ async getCustomAuthDomain() {
407
+ return rejectPromiseWithCodeAndMessage(
408
+ 'unsupported',
409
+ 'This operation is not supported in this environment.',
410
+ );
411
+ },
412
+
413
+ /**
414
+ * Create a new auth state listener instance for a given app.
415
+ * @param {string} appName - The name of the app to get the auth instance for.
416
+ * @returns {Promise<void>} - Void promise.
417
+ */
418
+ addAuthStateListener(appName: string) {
419
+ if (authStateListeners[appName]) {
420
+ return;
421
+ }
422
+
423
+ return guard(async () => {
424
+ const auth = getCachedAuthInstance(appName);
425
+
426
+ authStateListeners[appName] = onAuthStateChanged(auth, (user: User | null) => {
427
+ emitEvent('auth_state_changed', {
428
+ appName,
429
+ user: user ? userToObject(user) : null,
430
+ });
431
+ });
432
+ });
433
+ },
434
+
435
+ /**
436
+ * Remove an auth state listener instance for a given app.
437
+ * @param {string} appName - The name of the app to get the auth instance for.
438
+ * @returns {Promise<void>} - Void promise.
439
+ */
440
+ removeAuthStateListener(appName: string) {
441
+ if (authStateListeners[appName]) {
442
+ authStateListeners[appName]();
443
+ delete authStateListeners[appName];
444
+ }
445
+ },
446
+
447
+ /**
448
+ * Create a new ID token listener instance for a given app.
449
+ * @param {string} appName - The name of the app to get the auth instance for.
450
+ * @returns {Promise<void>} - Void promise.
451
+ */
452
+ addIdTokenListener(appName: string) {
453
+ if (idTokenListeners[appName]) {
454
+ return;
455
+ }
456
+
457
+ return guard(async () => {
458
+ const auth = getCachedAuthInstance(appName);
459
+
460
+ idTokenListeners[appName] = onIdTokenChanged(auth, (user: User | null) => {
461
+ emitEvent('auth_id_token_changed', {
462
+ authenticated: !!user,
463
+ appName,
464
+ user: user ? userToObject(user) : null,
465
+ });
466
+ });
467
+ });
468
+ },
469
+
470
+ /**
471
+ * Remove an ID token listener instance for a given app.
472
+ * @param {string} appName - The name of the app to get the auth instance for.
473
+ * @returns {Promise<void>} - Void promise.
474
+ */
475
+ removeIdTokenListener(appName: string) {
476
+ if (idTokenListeners[appName]) {
477
+ idTokenListeners[appName]();
478
+ delete idTokenListeners[appName];
479
+ }
480
+ },
481
+
482
+ async forceRecaptchaFlowForTesting(): Promise<never> {
483
+ return rejectPromiseWithCodeAndMessage(
484
+ 'unsupported',
485
+ 'This operation is not supported in this environment.',
486
+ );
487
+ },
488
+
489
+ async setAutoRetrievedSmsCodeForPhoneNumber(): Promise<never> {
490
+ return rejectPromiseWithCodeAndMessage(
491
+ 'unsupported',
492
+ 'This operation is not supported in this environment.',
493
+ );
494
+ },
495
+
496
+ async setAppVerificationDisabledForTesting(): Promise<never> {
497
+ return rejectPromiseWithCodeAndMessage(
498
+ 'unsupported',
499
+ 'This operation is not supported in this environment.',
500
+ );
501
+ },
502
+
503
+ /**
504
+ * Sign out the current user.
505
+ * @param {string} appName - The name of the app to get the auth instance for.
506
+ * @returns {Promise<void>} - Void promise.
507
+ */
508
+ signOut(appName: string) {
509
+ return guard(async () => {
510
+ const auth = getCachedAuthInstance(appName);
511
+
512
+ if (auth.currentUser === null) {
513
+ return promiseNoUser(true);
514
+ }
515
+
516
+ await auth.signOut();
517
+ return promiseNoUser();
518
+ });
519
+ },
520
+
521
+ /**
522
+ * Sign in anonymously.
523
+ * @param {*} appName - The name of the app to get the auth instance for.
524
+ * @returns
525
+ */
526
+ signInAnonymously(appName: string) {
527
+ return guard(async () => {
528
+ const auth = getCachedAuthInstance(appName);
529
+ const credential = await signInAnonymously(auth);
530
+ return authResultToObject(credential);
531
+ });
532
+ },
533
+
534
+ /**
535
+ * Sign in with email and password.
536
+ * @param {string} appName - The name of the app to get the auth instance for.
537
+ * @param {string} email - The email to sign in with.
538
+ * @param {string} password - The password to sign in with.
539
+ * @returns {Promise<object>} - The result of the sign in.
540
+ */
541
+ async createUserWithEmailAndPassword(appName: string, email: string, password: string) {
542
+ return guard(async () => {
543
+ const auth = getCachedAuthInstance(appName);
544
+ const credential = await createUserWithEmailAndPassword(auth, email, password);
545
+ return authResultToObject(credential);
546
+ });
547
+ },
548
+
549
+ /**
550
+ * Sign in with email and password.
551
+ * @param {string} appName - The name of the app to get the auth instance for.
552
+ * @param {string} email - The email to sign in with.
553
+ * @param {string} password - The password to sign in with.
554
+ * @returns {Promise<object>} - The result of the sign in.
555
+ */
556
+ async signInWithEmailAndPassword(appName: string, email: string, password: string) {
557
+ // The default guard / getWebError process doesn't work well here,
558
+ // since it creates a new error object that is then passed through
559
+ // a native module proxy and gets processed again.
560
+ // We need lots of information from the error so that MFA will work
561
+ // later if needed. So we handle the error custom here.
562
+ // return guard(async () => {
563
+ try {
564
+ const credential = await signInWithEmailAndPassword(
565
+ getCachedAuthInstance(appName),
566
+ email,
567
+ password,
568
+ );
569
+ return authResultToObject(credential);
570
+ } catch (e: unknown) {
571
+ const error = e as WebErrorLike;
572
+ error.userInfo = {
573
+ code: error.code?.split('/')[1] ?? 'unknown',
574
+ message: error.message,
575
+ customData: error.customData,
576
+ };
577
+ throw error;
578
+ }
579
+ // });
580
+ },
581
+
582
+ /**
583
+ * Check if a sign in with email link is valid
584
+ * @param {string} appName - The name of the app to get the auth instance for.
585
+ * @param {string} emailLink - The email link to sign in with.
586
+ * @returns {Promise<boolean>} - Whether the link is a valid sign in with email link.
587
+ */
588
+ async isSignInWithEmailLink(appName: string, emailLink: string) {
589
+ return guard(async () => {
590
+ const auth = getCachedAuthInstance(appName);
591
+ return await isSignInWithEmailLink(auth, emailLink);
592
+ });
593
+ },
594
+
595
+ /**
596
+ * Sign in with email link.
597
+ * @param {string} appName - The name of the app to get the auth instance for.
598
+ * @param {string} email - The email to sign in with.
599
+ * @param {string} emailLink - The email link to sign in with.
600
+ * @returns {Promise<object>} - The result of the sign in.
601
+ */
602
+ async signInWithEmailLink(appName: string, email: string, emailLink: string) {
603
+ return guard(async () => {
604
+ const auth = getCachedAuthInstance(appName);
605
+ const credential = await signInWithEmailLink(auth, email, emailLink);
606
+ return authResultToObject(credential);
607
+ });
608
+ },
609
+
610
+ /**
611
+ * Sign in with a custom token.
612
+ * @param {string} appName - The name of the app to get the auth instance for.
613
+ * @param {string} token - The token to sign in with.
614
+ * @returns {Promise<object>} - The result of the sign in.
615
+ */
616
+ async signInWithCustomToken(appName: string, token: string) {
617
+ return guard(async () => {
618
+ const auth = getCachedAuthInstance(appName);
619
+ const credential = await signInWithCustomToken(auth, token);
620
+ return authResultToObject(credential);
621
+ });
622
+ },
623
+
624
+ /**
625
+ * Not implemented on web.
626
+ */
627
+ async revokeToken() {
628
+ return promiseNoUser();
629
+ },
630
+
631
+ /**
632
+ * Send a password reset email.
633
+ * @param {string} appName - The name of the app to get the auth instance for.
634
+ * @param {string} email - The email to send the password reset email to.
635
+ * @param {ActionCodeSettings} settings - The settings to use for the password reset email.
636
+ * @returns {Promise<null>}
637
+ */
638
+ async sendPasswordResetEmail(appName: string, email: string, settings?: ActionCodeSettings) {
639
+ return guard(async () => {
640
+ const auth = getCachedAuthInstance(appName);
641
+ await sendPasswordResetEmail(auth, email, settings);
642
+ return promiseNoUser();
643
+ });
644
+ },
645
+
646
+ /**
647
+ * Send a sign in link to an email.
648
+ * @param {string} appName - The name of the app to get the auth instance for.
649
+ * @param {string} email - The email to send the password reset email to.
650
+ * @param {ActionCodeSettings} settings - The settings to use for the password reset email.
651
+ * @returns {Promise<null>}
652
+ */
653
+ async sendSignInLinkToEmail(appName: string, email: string, settings: ActionCodeSettings) {
654
+ return guard(async () => {
655
+ const auth = getCachedAuthInstance(appName);
656
+ await sendSignInLinkToEmail(auth, email, settings);
657
+ return promiseNoUser();
658
+ });
659
+ },
660
+
661
+ /* ----------------------
662
+ * .currentUser methods
663
+ * ---------------------- */
664
+
665
+ /**
666
+ * Delete the current user.
667
+ * @param {string} appName - The name of the app to get the auth instance for.
668
+ * @returns {Promise<null>}
669
+ */
670
+ async delete(appName: string) {
671
+ return guard(async () => {
672
+ const auth = getCachedAuthInstance(appName);
673
+
674
+ if (auth.currentUser === null) {
675
+ return promiseNoUser(true);
676
+ }
677
+
678
+ await auth.currentUser.delete();
679
+ return promiseNoUser();
680
+ });
681
+ },
682
+
683
+ /**
684
+ * Reload the current user.
685
+ * @param {string} appName - The name of the app to get the auth instance for.
686
+ * @returns {Promise<object>} - The current user object.
687
+ */
688
+ async reload(appName: string) {
689
+ return guard(async () => {
690
+ const auth = getCachedAuthInstance(appName);
691
+
692
+ if (auth.currentUser === null) {
693
+ return promiseNoUser(true);
694
+ }
695
+
696
+ await auth.currentUser.reload();
697
+ return userToObject(auth.currentUser);
698
+ });
699
+ },
700
+
701
+ /**
702
+ * Send a verification email to the current user.
703
+ * @param {string} appName - The name of the app to get the auth instance for.
704
+ * @param {ActionCodeSettings} actionCodeSettings - The settings to use for the email verification.
705
+ * @returns {Promise<object>} - The current user object.
706
+ */
707
+ async sendEmailVerification(appName: string, actionCodeSettings?: ActionCodeSettings | null) {
708
+ return guard(async () => {
709
+ const auth = getCachedAuthInstance(appName);
710
+
711
+ if (auth.currentUser === null) {
712
+ return promiseNoUser(true);
713
+ }
714
+
715
+ await sendEmailVerification(auth.currentUser, actionCodeSettings);
716
+ return userToObject(auth.currentUser);
717
+ });
718
+ },
719
+
720
+ /**
721
+ * Verify the email before updating it.
722
+ * @param {string} appName - The name of the app to get the auth instance for.
723
+ * @param {string} email - The email to verify.
724
+ * @param {ActionCodeSettings} actionCodeSettings - The settings to use for the email verification.
725
+ * @returns {Promise<object>} - The current user object.
726
+ */
727
+ async verifyBeforeUpdateEmail(
728
+ appName: string,
729
+ email: string,
730
+ actionCodeSettings?: ActionCodeSettings | null,
731
+ ) {
732
+ return guard(async () => {
733
+ const auth = getCachedAuthInstance(appName);
734
+
735
+ if (auth.currentUser === null) {
736
+ return promiseNoUser(true);
737
+ }
738
+
739
+ await verifyBeforeUpdateEmail(auth.currentUser, email, actionCodeSettings);
740
+ return userToObject(auth.currentUser);
741
+ });
742
+ },
743
+
744
+ /**
745
+ * Update the current user's email.
746
+ * @param {string} appName - The name of the app to get the auth instance for.
747
+ * @param {string} email - The email to update.
748
+ * @returns {Promise<object>} - The current user object.
749
+ */
750
+ async updateEmail(appName: string, email: string) {
751
+ return guard(async () => {
752
+ const auth = getCachedAuthInstance(appName);
753
+
754
+ if (auth.currentUser === null) {
755
+ return promiseNoUser(true);
756
+ }
757
+
758
+ await updateEmail(auth.currentUser, email);
759
+ return userToObject(auth.currentUser);
760
+ });
761
+ },
762
+
763
+ /**
764
+ * Update the current user's password.
765
+ * @param {string} appName - The name of the app to get the auth instance for.
766
+ * @param {string} password - The password to update.
767
+ * @returns {Promise<object>} - The current user object.
768
+ */
769
+ async updatePassword(appName: string, password: string) {
770
+ return guard(async () => {
771
+ const auth = getCachedAuthInstance(appName);
772
+
773
+ if (auth.currentUser === null) {
774
+ return promiseNoUser(true);
775
+ }
776
+
777
+ await updatePassword(auth.currentUser, password);
778
+ return userToObject(auth.currentUser);
779
+ });
780
+ },
781
+
782
+ /**
783
+ * Update the current user's phone number.
784
+ * @param {string} appName - The name of the app to get the auth instance for.
785
+ * @param {string} provider - The provider to update the phone number with.
786
+ * @param {string} authToken - The auth token to update the phone number with.
787
+ * @param {string} authSecret - The auth secret to update the phone number with.
788
+ * @returns {Promise<object>} - The current user object.
789
+ */
790
+ async updatePhoneNumber(
791
+ appName: string,
792
+ provider: string,
793
+ authToken: string,
794
+ authSecret?: string | null,
795
+ ) {
796
+ return guard(async () => {
797
+ const auth = getCachedAuthInstance(appName);
798
+
799
+ if (auth.currentUser === null) {
800
+ return promiseNoUser(true);
801
+ }
802
+
803
+ if (provider !== 'phone') {
804
+ return rejectPromiseWithCodeAndMessage(
805
+ 'invalid-credential',
806
+ 'The supplied auth credential does not have a phone provider.',
807
+ );
808
+ }
809
+
810
+ const credential = getAuthCredential(auth, provider, authToken, authSecret);
811
+
812
+ if (!credential) {
813
+ return rejectPromiseWithCodeAndMessage(
814
+ 'invalid-credential',
815
+ 'The supplied auth credential is malformed, has expired or is not currently supported.',
816
+ );
817
+ }
818
+
819
+ await updatePhoneNumber(auth.currentUser, credential as PhoneAuthCredential);
820
+
821
+ return userToObject(auth.currentUser);
822
+ });
823
+ },
824
+
825
+ /**
826
+ * Update the current user's profile.
827
+ * @param {string} appName - The name of the app to get the auth instance for.
828
+ * @param {object} props - The properties to update.
829
+ * @returns {Promise<object>} - The current user object.
830
+ */
831
+ async updateProfile(
832
+ appName: string,
833
+ props: { displayName?: string | null; photoURL?: string | null },
834
+ ) {
835
+ return guard(async () => {
836
+ const auth = getCachedAuthInstance(appName);
837
+
838
+ if (auth.currentUser === null) {
839
+ return promiseNoUser(true);
840
+ }
841
+
842
+ await updateProfile(auth.currentUser, {
843
+ displayName: props.displayName,
844
+ photoURL: props.photoURL,
845
+ });
846
+
847
+ return userToObject(auth.currentUser);
848
+ });
849
+ },
850
+
851
+ /**
852
+ * Sign in with a credential.
853
+ * @param {string} appName - The name of the app to get the auth instance for.
854
+ * @param {string} provider - The provider to sign in with.
855
+ * @param {string} authToken - The auth token to sign in with.
856
+ * @param {string} authSecret - The auth secret to sign in with.
857
+ * @returns {Promise<object>} - The result of the sign in.
858
+ */
859
+ async signInWithCredential(
860
+ appName: string,
861
+ provider: string,
862
+ authToken: string,
863
+ authSecret?: string | null,
864
+ ) {
865
+ return guard(async () => {
866
+ const auth = getCachedAuthInstance(appName);
867
+ const credential = getAuthCredential(auth, provider, authToken, authSecret);
868
+
869
+ if (credential === null) {
870
+ return rejectPromiseWithCodeAndMessage(
871
+ 'invalid-credential',
872
+ 'The supplied auth credential is malformed, has expired or is not currently supported.',
873
+ );
874
+ }
875
+
876
+ const credentialResult = await signInWithCredential(auth, credential);
877
+ return authResultToObject(credentialResult);
878
+ });
879
+ },
880
+
881
+ async signInWithProvider() {
882
+ return rejectPromiseWithCodeAndMessage(
883
+ 'unsupported',
884
+ 'This operation is not supported in this environment.',
885
+ );
886
+ },
887
+
888
+ async signInWithPhoneNumber() {
889
+ return rejectPromiseWithCodeAndMessage(
890
+ 'unsupported',
891
+ 'This operation is not supported in this environment.',
892
+ );
893
+ },
894
+
895
+ /**
896
+ * Get a multi-factor session.
897
+ * @param {string} appName - The name of the app to get the auth instance for.
898
+ * @returns {Promise<string>} - The session ID.
899
+ */
900
+ async getSession(appName: string) {
901
+ return guard(async () => {
902
+ const auth = getCachedAuthInstance(appName);
903
+
904
+ if (auth.currentUser === null) {
905
+ return promiseNoUser(true);
906
+ }
907
+
908
+ const session = await multiFactor(auth.currentUser).getSession();
909
+
910
+ // Increment the session ID.
911
+ sessionId++;
912
+
913
+ const key = `${sessionId}`;
914
+ sessionMap.set(key, session);
915
+ return key;
916
+ });
917
+ },
918
+
919
+ verifyPhoneNumberForMultiFactor() {
920
+ return rejectPromiseWithCodeAndMessage(
921
+ 'unsupported',
922
+ 'This operation is not supported in this environment.',
923
+ );
924
+ },
925
+
926
+ finalizeMultiFactorEnrollment() {
927
+ return rejectPromiseWithCodeAndMessage(
928
+ 'unsupported',
929
+ 'This operation is not supported in this environment.',
930
+ );
931
+ },
932
+
933
+ resolveMultiFactorSignIn() {
934
+ return rejectPromiseWithCodeAndMessage(
935
+ 'unsupported',
936
+ 'This operation is not supported in this environment.',
937
+ );
938
+ },
939
+
940
+ confirmationResultConfirm() {
941
+ return rejectPromiseWithCodeAndMessage(
942
+ 'unsupported',
943
+ 'This operation is not supported in this environment.',
944
+ );
945
+ },
946
+
947
+ verifyPhoneNumber() {
948
+ return rejectPromiseWithCodeAndMessage(
949
+ 'unsupported',
950
+ 'This operation is not supported in this environment.',
951
+ );
952
+ },
953
+
954
+ /**
955
+ * Confirm the password reset code.
956
+ * @param {string} appName - The name of the app to get the auth instance for.
957
+ * @param {string} code - The code to confirm.
958
+ * @param {string} newPassword - The new password to set.
959
+ * @returns {Promise<null>}
960
+ */
961
+ async confirmPasswordReset(appName: string, code: string, newPassword: string) {
962
+ return guard(async () => {
963
+ const auth = getCachedAuthInstance(appName);
964
+ await confirmPasswordReset(auth, code, newPassword);
965
+ return promiseNoUser();
966
+ });
967
+ },
968
+
969
+ /**
970
+ * Apply an action code.
971
+ * @param {string} appName - The name of the app to get the auth instance for.
972
+ * @param {string} code - The code to apply.
973
+ * @returns {Promise<void>} - Void promise.
974
+ */
975
+ async applyActionCode(appName: string, code: string) {
976
+ return guard(async () => {
977
+ const auth = getCachedAuthInstance(appName);
978
+ await applyActionCode(auth, code);
979
+ });
980
+ },
981
+
982
+ /**
983
+ * Check an action code.
984
+ * @param {string} appName - The name of the app to get the auth instance for.
985
+ * @param {string} code - The code to check.
986
+ * @returns {Promise<object>} - The result of the check.
987
+ */
988
+ async checkActionCode(appName: string, code: string) {
989
+ return guard(async () => {
990
+ const auth = getCachedAuthInstance(appName);
991
+ const result = await checkActionCode(auth, code);
992
+
993
+ return {
994
+ operation: result.operation,
995
+ data: {
996
+ email: result.data.email,
997
+ fromEmail: result.data.previousEmail,
998
+ // multiFactorInfo - not implemented
999
+ },
1000
+ };
1001
+ });
1002
+ },
1003
+
1004
+ /**
1005
+ * Link a credential to the current user.
1006
+ * @param {string} appName - The name of the app to get the auth instance for.
1007
+ * @param {string} provider - The provider to link.
1008
+ * @param {string} authToken - The auth token to link.
1009
+ * @param {string} authSecret - The auth secret to link.
1010
+ * @returns {Promise<object>} - The current user object.
1011
+ */
1012
+ async linkWithCredential(
1013
+ appName: string,
1014
+ provider: string,
1015
+ authToken: string,
1016
+ authSecret?: string | null,
1017
+ ) {
1018
+ return guard(async () => {
1019
+ const auth = getCachedAuthInstance(appName);
1020
+ const credential = getAuthCredential(auth, provider, authToken, authSecret);
1021
+
1022
+ if (credential === null) {
1023
+ return rejectPromiseWithCodeAndMessage(
1024
+ 'invalid-credential',
1025
+ 'The supplied auth credential is malformed, has expired or is not currently supported.',
1026
+ );
1027
+ }
1028
+
1029
+ if (auth.currentUser === null) {
1030
+ return promiseNoUser(true);
1031
+ }
1032
+
1033
+ return authResultToObject(await linkWithCredential(auth.currentUser, credential));
1034
+ });
1035
+ },
1036
+
1037
+ async linkWithProvider() {
1038
+ // TODO: We could check if window is available here, but for now it's not supported.
1039
+ return rejectPromiseWithCodeAndMessage(
1040
+ 'unsupported',
1041
+ 'This operation is not supported in this environment.',
1042
+ );
1043
+ },
1044
+
1045
+ /**
1046
+ * Unlink a provider from the current user.
1047
+ * @param {string} appName - The name of the app to get the auth instance for.
1048
+ * @param {string} providerId - The provider ID to unlink.
1049
+ * @returns {Promise<object>} - The current user object.
1050
+ */
1051
+ async unlink(appName: string, providerId: string) {
1052
+ return guard(async () => {
1053
+ const auth = getCachedAuthInstance(appName);
1054
+
1055
+ if (auth.currentUser === null) {
1056
+ return promiseNoUser(true);
1057
+ }
1058
+
1059
+ const user = await unlink(auth.currentUser, providerId);
1060
+ return userToObject(user);
1061
+ });
1062
+ },
1063
+
1064
+ /**
1065
+ * Reauthenticate with a credential.
1066
+ * @param {string} appName - The name of the app to get the auth instance for.
1067
+ * @param {string} provider - The provider to reauthenticate with.
1068
+ * @param {string} authToken - The auth token to reauthenticate with.
1069
+ * @param {string} authSecret - The auth secret to reauthenticate with.
1070
+ * @returns {Promise<object>} - The current user object.
1071
+ */
1072
+ async reauthenticateWithCredential(
1073
+ appName: string,
1074
+ provider: string,
1075
+ authToken: string,
1076
+ authSecret?: string | null,
1077
+ ) {
1078
+ return guard(async () => {
1079
+ const auth = getCachedAuthInstance(appName);
1080
+ const credential = getAuthCredential(auth, provider, authToken, authSecret);
1081
+
1082
+ if (credential === null) {
1083
+ return rejectPromiseWithCodeAndMessage(
1084
+ 'invalid-credential',
1085
+ 'The supplied auth credential is malformed, has expired or is not currently supported.',
1086
+ );
1087
+ }
1088
+
1089
+ if (auth.currentUser === null) {
1090
+ return promiseNoUser(true);
1091
+ }
1092
+
1093
+ return authResultToObject(await reauthenticateWithCredential(auth.currentUser, credential));
1094
+ });
1095
+ },
1096
+
1097
+ async reauthenticateWithProvider() {
1098
+ // TODO: We could check if window is available here, but for now it's not supported.
1099
+ return rejectPromiseWithCodeAndMessage(
1100
+ 'unsupported',
1101
+ 'This operation is not supported in this environment.',
1102
+ );
1103
+ },
1104
+
1105
+ /**
1106
+ * Get the ID token for the current user.
1107
+ * @param {string} appName - The name of the app to get the auth instance for.
1108
+ * @param {boolean} forceRefresh - Whether to force a token refresh.
1109
+ * @returns {Promise<string>} - The ID token.
1110
+ */
1111
+ async getIdToken(appName: string, forceRefresh: boolean) {
1112
+ return guard(async () => {
1113
+ const auth = getCachedAuthInstance(appName);
1114
+
1115
+ if (auth.currentUser === null) {
1116
+ return promiseNoUser(true);
1117
+ }
1118
+
1119
+ const token = await getIdToken(auth.currentUser, forceRefresh);
1120
+ return token;
1121
+ });
1122
+ },
1123
+
1124
+ /**
1125
+ * Get the ID token result for the current user.
1126
+ * @param {string} appName - The name of the app to get the auth instance for.
1127
+ * @param {boolean} forceRefresh - Whether to force a token refresh.
1128
+ * @returns {Promise<object>} - The ID token result.
1129
+ */
1130
+ async getIdTokenResult(appName: string, forceRefresh: boolean) {
1131
+ return guard(async () => {
1132
+ const auth = getCachedAuthInstance(appName);
1133
+
1134
+ if (auth.currentUser === null) {
1135
+ return promiseNoUser(true);
1136
+ }
1137
+
1138
+ const result = await getIdTokenResult(auth.currentUser, forceRefresh);
1139
+
1140
+ // TODO(ehesp): Result looks expected, might be safer to keep fixed object?
1141
+ return {
1142
+ authTime: result.authTime,
1143
+ expirationTime: result.expirationTime,
1144
+ issuedAtTime: result.issuedAtTime,
1145
+ claims: result.claims,
1146
+ signInProvider: result.signInProvider,
1147
+ token: result.token,
1148
+ };
1149
+ });
1150
+ },
1151
+
1152
+ /**
1153
+ * Get a MultiFactorResolver from the underlying SDK
1154
+ * @param {*} _appName the name of the app to get the auth instance for
1155
+ * @param {*} uid the uid of the TOTP MFA attempt
1156
+ * @param {*} code the code from the user TOTP app
1157
+ * @return TotpMultiFactorAssertion to use for resolving
1158
+ */
1159
+ assertionForSignIn(_appName: string, uid: string, code: string) {
1160
+ return TotpMultiFactorGenerator.assertionForSignIn(uid, code);
1161
+ },
1162
+
1163
+ /**
1164
+ * Get a MultiFactorResolver from the underlying SDK
1165
+ * @param {*} appName the name of the app to get the auth instance for
1166
+ * @param {*} error the MFA error returned from initial factor login attempt
1167
+ * @return MultiFactorResolver to use for verifying the second factor
1168
+ */
1169
+ getMultiFactorResolver(appName: string, error: MultiFactorError): MultiFactorResolver | null {
1170
+ return getMultiFactorResolver(getCachedAuthInstance(appName), error);
1171
+ },
1172
+
1173
+ /**
1174
+ * generate a TOTP secret
1175
+ * @param {*} _appName - The name of the app to get the auth instance for.
1176
+ * @param {*} session - The MultiFactorSession to associate with the secret
1177
+ * @returns object with secretKey to associate with TotpSecret
1178
+ */
1179
+ async generateTotpSecret(_appName: string, session: string) {
1180
+ return guard(async () => {
1181
+ const mappedSession = sessionMap.get(session);
1182
+ if (!mappedSession) {
1183
+ return rejectPromiseWithCodeAndMessage(
1184
+ 'invalid-multi-factor-session',
1185
+ 'The supplied multi-factor session is invalid or has expired.',
1186
+ );
1187
+ }
1188
+ const totpSecret = await TotpMultiFactorGenerator.generateSecret(mappedSession);
1189
+ totpSecretMap.set(totpSecret.secretKey, totpSecret);
1190
+ return { secretKey: totpSecret.secretKey };
1191
+ });
1192
+ },
1193
+
1194
+ /**
1195
+ * unenroll from TOTP
1196
+ * @param {*} appName - The name of the app to get the auth instance for.
1197
+ * @param {*} enrollmentId - The ID to associate with the enrollment
1198
+ * @returns
1199
+ */
1200
+ async unenrollMultiFactor(appName: string, enrollmentId: string) {
1201
+ return guard(async () => {
1202
+ const auth = getCachedAuthInstance(appName);
1203
+ if (auth.currentUser === null) {
1204
+ return promiseNoUser(true);
1205
+ }
1206
+ await multiFactor(auth.currentUser).unenroll(enrollmentId);
1207
+ return promiseNoUser();
1208
+ });
1209
+ },
1210
+
1211
+ /**
1212
+ * finalize a TOTP enrollment
1213
+ * @param {*} appName - The name of the app to get the auth instance for.
1214
+ * @param {*} secretKey - The secretKey to associate native TotpSecret
1215
+ * @param {*} verificationCode - The TOTP to verify
1216
+ * @param {*} displayName - The name to associate as a hint
1217
+ * @returns
1218
+ */
1219
+ async finalizeTotpEnrollment(
1220
+ appName: string,
1221
+ secretKey: string,
1222
+ verificationCode: string,
1223
+ displayName?: string | null,
1224
+ ) {
1225
+ return guard(async () => {
1226
+ const auth = getCachedAuthInstance(appName);
1227
+ if (auth.currentUser === null) {
1228
+ return promiseNoUser(true);
1229
+ }
1230
+ const totpSecret = totpSecretMap.get(secretKey);
1231
+ if (!totpSecret) {
1232
+ return rejectPromiseWithCodeAndMessage(
1233
+ 'invalid-multi-factor-secret',
1234
+ "can't find secret for provided key",
1235
+ );
1236
+ }
1237
+ const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
1238
+ totpSecret,
1239
+ verificationCode,
1240
+ );
1241
+ await multiFactor(auth.currentUser).enroll(multiFactorAssertion, displayName);
1242
+ return promiseNoUser();
1243
+ });
1244
+ },
1245
+
1246
+ /**
1247
+ * generate a TOTP QR Code URL
1248
+ * @param {*} _appName - The name of the app to get the auth instance for.
1249
+ * @param {*} secretKey - The secretKey to associate with the TotpSecret
1250
+ * @param {*} accountName - The account name to use in auth app
1251
+ * @param {*} issuer - The issuer to use in auth app
1252
+ * @returns QR Code URL
1253
+ */
1254
+ generateQrCodeUrl(_appName: string, secretKey: string, accountName?: string, issuer?: string) {
1255
+ const totpSecret = totpSecretMap.get(secretKey);
1256
+ if (!totpSecret) {
1257
+ return rejectPromiseWithCodeAndMessage(
1258
+ 'invalid-multi-factor-secret',
1259
+ "can't find secret for provided key",
1260
+ );
1261
+ }
1262
+ return totpSecret.generateQrCodeUrl(accountName, issuer);
1263
+ },
1264
+
1265
+ /**
1266
+ * open a QR Code URL in an app directly
1267
+ * @param {*} appName - The name of the app to get the auth instance for.
1268
+ * @param {*} qrCodeUrl the URL to open in the app, from generateQrCodeUrl
1269
+ * @throws Error not supported in this environment
1270
+ */
1271
+ openInOtpApp() {
1272
+ return rejectWithCodeAndMessage(
1273
+ 'unsupported',
1274
+ 'This operation is not supported in this environment.',
1275
+ );
1276
+ },
1277
+
1278
+ /* ----------------------
1279
+ * other methods
1280
+ * ---------------------- */
1281
+
1282
+ /**
1283
+ * Fetch the sign in methods for an email.
1284
+ * @param {string} appName - The name of the app to get the auth instance for.
1285
+ * @param {string} email - The email to fetch the sign in methods for.
1286
+ * @returns {Promise<string[]>} - The sign in methods for the email.
1287
+ */
1288
+ async fetchSignInMethodsForEmail(appName: string, email: string) {
1289
+ return guard(async () => {
1290
+ const auth = getCachedAuthInstance(appName);
1291
+ const methods = await fetchSignInMethodsForEmail(auth, email);
1292
+ return methods;
1293
+ });
1294
+ },
1295
+
1296
+ /**
1297
+ * Set the language code.
1298
+ * @param {string} appName - The name of the app to get the auth instance for.
1299
+ * @param {string} code - The language code to set.
1300
+ * @returns {void}
1301
+ */
1302
+ setLanguageCode(appName: string, code: string | null) {
1303
+ return guard(async () => {
1304
+ const auth = getCachedAuthInstance(appName);
1305
+ auth.languageCode = code;
1306
+ });
1307
+ },
1308
+
1309
+ /**
1310
+ * Set the tenant ID.
1311
+ * @param {string} appName - The name of the app to get the auth instance for.
1312
+ * @param {string} tenantId - The tenant ID to set.
1313
+ * @returns {void}
1314
+ */
1315
+ setTenantId(appName: string, tenantId: string | null) {
1316
+ return guard(async () => {
1317
+ const auth = getCachedAuthInstance(appName);
1318
+ auth.tenantId = tenantId;
1319
+ });
1320
+ },
1321
+
1322
+ /**
1323
+ * Use the device language.
1324
+ * @param {string} appName - The name of the app to get the auth instance for.
1325
+ * @returns void
1326
+ */
1327
+ useDeviceLanguage(appName: string) {
1328
+ return guard(async () => {
1329
+ const auth = getCachedAuthInstance(appName);
1330
+ useDeviceLanguage(auth);
1331
+ });
1332
+ },
1333
+
1334
+ /**
1335
+ * Verify the provided password reset code.
1336
+ * @returns {string} - The users email address if valid.
1337
+ */
1338
+ verifyPasswordResetCode(appName: string, code: string) {
1339
+ return guard(async () => {
1340
+ const auth = getCachedAuthInstance(appName);
1341
+ const email = await verifyPasswordResetCode(auth, code);
1342
+ return email;
1343
+ });
1344
+ },
1345
+
1346
+ /**
1347
+ * Connect to the auth emulator.
1348
+ * @param {string} appName - The name of the app to get the auth instance for.
1349
+ * @param {string} host - The host to use for the auth emulator.
1350
+ * @param {number} port - The port to use for the auth emulator.
1351
+ * @returns {void}
1352
+ */
1353
+ useEmulator(appName: string, host: string, port: number) {
1354
+ return guard(async () => {
1355
+ const auth = getCachedAuthInstance(appName);
1356
+ connectAuthEmulator(auth, `http://${host}:${port}`);
1357
+ });
1358
+ },
1359
+ };