@react-native-firebase/auth 26.0.0 → 26.2.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 (54) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/RNFBAuth.podspec +2 -1
  3. package/android/src/main/java/io/invertase/firebase/auth/NativeRNFBTurboAuth.java +9 -1
  4. package/android/src/main/java/io/invertase/firebase/auth/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboAuthSpec.java +1 -1
  5. package/android/src/main/java/io/invertase/firebase/auth/generated/jni/RNFBAuthTurboModules-generated.cpp +2 -2
  6. package/android/src/main/java/io/invertase/firebase/auth/generated/jni/react/renderer/components/RNFBAuthTurboModules/RNFBAuthTurboModulesJSI-generated.cpp +3 -2
  7. package/android/src/main/java/io/invertase/firebase/auth/generated/jni/react/renderer/components/RNFBAuthTurboModules/RNFBAuthTurboModulesJSI.h +5 -5
  8. package/dist/module/credentials/OAuthCredential.js +22 -1
  9. package/dist/module/credentials/OAuthCredential.js.map +1 -1
  10. package/dist/module/index.js +6 -1
  11. package/dist/module/index.js.map +1 -1
  12. package/dist/module/providers/AppleAuthProvider.js +17 -4
  13. package/dist/module/providers/AppleAuthProvider.js.map +1 -1
  14. package/dist/module/providers/OAuthProvider.js +4 -2
  15. package/dist/module/providers/OAuthProvider.js.map +1 -1
  16. package/dist/module/types/auth.js +8 -0
  17. package/dist/module/types/auth.js.map +1 -1
  18. package/dist/module/version.js +1 -1
  19. package/dist/module/web/RNFBAuthModule.js +13 -11
  20. package/dist/module/web/RNFBAuthModule.js.map +1 -1
  21. package/dist/typescript/lib/credentials/OAuthCredential.d.ts +6 -0
  22. package/dist/typescript/lib/credentials/OAuthCredential.d.ts.map +1 -1
  23. package/dist/typescript/lib/index.d.ts.map +1 -1
  24. package/dist/typescript/lib/providers/AppleAuthProvider.d.ts +10 -3
  25. package/dist/typescript/lib/providers/AppleAuthProvider.d.ts.map +1 -1
  26. package/dist/typescript/lib/providers/OAuthProvider.d.ts.map +1 -1
  27. package/dist/typescript/lib/types/auth.d.ts +26 -0
  28. package/dist/typescript/lib/types/auth.d.ts.map +1 -1
  29. package/dist/typescript/lib/types/internal.d.ts +1 -1
  30. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  31. package/dist/typescript/lib/version.d.ts +1 -1
  32. package/dist/typescript/lib/web/RNFBAuthModule.d.ts +3 -1
  33. package/dist/typescript/lib/web/RNFBAuthModule.d.ts.map +1 -1
  34. package/ios/RNFBAuth/RNFBAuthHelper.h +338 -0
  35. package/ios/RNFBAuth/RNFBAuthHelper.m +2221 -0
  36. package/ios/RNFBAuth/RNFBAuthModule.h +7 -64
  37. package/ios/RNFBAuth/RNFBAuthModule.mm +177 -1638
  38. package/ios/generated/RNFBAuthTurboModules/RNFBAuthTurboModules-generated.mm +2 -2
  39. package/ios/generated/RNFBAuthTurboModules/RNFBAuthTurboModules.h +1 -0
  40. package/ios/generated/RNFBAuthTurboModulesJSI-generated.cpp +3 -2
  41. package/ios/generated/RNFBAuthTurboModulesJSI.h +5 -5
  42. package/lib/credentials/OAuthCredential.ts +44 -0
  43. package/lib/index.ts +13 -1
  44. package/lib/providers/AppleAuthProvider.ts +21 -5
  45. package/lib/providers/OAuthProvider.ts +2 -0
  46. package/lib/types/auth.ts +27 -0
  47. package/lib/types/internal.ts +2 -0
  48. package/lib/version.ts +1 -1
  49. package/lib/web/RNFBAuthModule.ts +34 -23
  50. package/package.json +7 -8
  51. package/plugin/build/ios/urlTypes.js +1 -1
  52. package/plugin/src/ios/urlTypes.ts +1 -1
  53. package/plugin/tsconfig.json +2 -1
  54. package/specs/NativeRNFBTurboAuth.ts +2 -0
@@ -0,0 +1,2221 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ #if __has_include(<Firebase/Firebase.h>)
19
+ #import <Firebase/Firebase.h>
20
+ #else
21
+ @import FirebaseCore;
22
+ @import FirebaseAuth;
23
+ // `@import FirebaseAuth` alone only exposes the Swift-generated interop header
24
+ // (the real `FIRAuth`/`FIRUser` classes). The hand-written ObjC compatibility
25
+ // headers under `Public/FirebaseAuth/` (typedefs like
26
+ // `FIRAuthStateDidChangeListenerHandle`, error userInfo key constants, etc.)
27
+ // are vended by the separate `FirebaseAuthInternal` Clang module, which isn't
28
+ // automatically re-exported by `@import FirebaseAuth` -- it must be imported
29
+ // explicitly too, even though it's a direct (not transitive) SPM dependency of
30
+ // `FirebaseAuth`. See okf-bundle/ios-spm-native-imports.md.
31
+ @import FirebaseAuthInternal;
32
+ #endif
33
+ #import <React/RCTConvert.h>
34
+ #import <React/RCTUtils.h>
35
+
36
+ #import "RNFBApp/RCTConvert+FIRApp.h"
37
+ #import "RNFBApp/RNFBAppModule.h"
38
+ #import "RNFBApp/RNFBSharedUtils.h"
39
+ #import "RNFBAuthHelper.h"
40
+
41
+ static void RNFBAuthThrowSyncErrorWithCode(NSString *code, NSString *message) {
42
+ @throw [NSException exceptionWithName:code
43
+ reason:message
44
+ userInfo:@{@"code" : code, @"message" : message}];
45
+ }
46
+
47
+ static NSString *const keyIOS = @"iOS";
48
+ static NSString *const keyUrl = @"url";
49
+ static NSString *const keyUid = @"uid";
50
+ static NSString *const keyUser = @"user";
51
+ static NSString *const keyEmail = @"email";
52
+ static NSString *const keyAndroid = @"android";
53
+ static NSString *const keyProfile = @"profile";
54
+ static NSString *const keyNewUser = @"isNewUser";
55
+ static NSString *const keyUsername = @"username";
56
+ static NSString *const keyMultiFactor = @"multiFactor";
57
+ static NSString *const keyPhotoUrl = @"photoURL";
58
+ static NSString *const keyBundleId = @"bundleId";
59
+ static NSString *const keyInstallApp = @"installApp";
60
+ static NSString *const keyProviderId = @"providerId";
61
+ static NSString *const keyPhoneNumber = @"phoneNumber";
62
+ static NSString *const keyDisplayName = @"displayName";
63
+ static NSString *const keyPackageName = @"packageName";
64
+ static NSString *const keyMinVersion = @"minimumVersion";
65
+ static NSString *const constAppLanguage = @"APP_LANGUAGE";
66
+ static NSString *const constAppUser = @"APP_USER";
67
+ static NSString *const keyHandleCodeInApp = @"handleCodeInApp";
68
+ static NSString *const keyLinkDomain = @"linkDomain";
69
+ static NSString *const keyAdditionalUserInfo = @"additionalUserInfo";
70
+ static NSString *const AUTH_STATE_CHANGED_EVENT = @"auth_state_changed";
71
+ static NSString *const AUTH_ID_TOKEN_CHANGED_EVENT = @"auth_id_token_changed";
72
+ static NSString *const PHONE_AUTH_STATE_CHANGED_EVENT = @"phone_auth_state_changed";
73
+
74
+ static NSString *const AuthErrorCode_toJSErrorCode[] = {
75
+ [FIRAuthErrorCodeInvalidCustomToken] = @"invalid-custom-token",
76
+ [FIRAuthErrorCodeCustomTokenMismatch] = @"custom-token-mismatch",
77
+ [FIRAuthErrorCodeInvalidCredential] = @"invalid-credential",
78
+ [FIRAuthErrorCodeUserDisabled] = @"user-disabled",
79
+ [FIRAuthErrorCodeOperationNotAllowed] = @"operation-not-allowed",
80
+ [FIRAuthErrorCodeEmailAlreadyInUse] = @"email-already-in-use",
81
+ [FIRAuthErrorCodeInvalidEmail] = @"invalid-email",
82
+ [FIRAuthErrorCodeWrongPassword] = @"wrong-password",
83
+ [FIRAuthErrorCodeTooManyRequests] = @"too-many-requests",
84
+ [FIRAuthErrorCodeUserNotFound] = @"user-not-found",
85
+ [FIRAuthErrorCodeAccountExistsWithDifferentCredential] =
86
+ @"account-exists-with-different-credential",
87
+ [FIRAuthErrorCodeRequiresRecentLogin] = @"requires-recent-login",
88
+ [FIRAuthErrorCodeProviderAlreadyLinked] = @"provider-already-linked",
89
+ [FIRAuthErrorCodeNoSuchProvider] = @"no-such-provider",
90
+ [FIRAuthErrorCodeInvalidUserToken] = @"invalid-user-token",
91
+ [FIRAuthErrorCodeNetworkError] = @"network-request-failed",
92
+ [FIRAuthErrorCodeUserTokenExpired] = @"user-token-expired",
93
+ [FIRAuthErrorCodeInvalidAPIKey] = @"invalid-api-key",
94
+ [FIRAuthErrorCodeUserMismatch] = @"user-mismatch",
95
+ [FIRAuthErrorCodeCredentialAlreadyInUse] = @"credential-already-in-use",
96
+ [FIRAuthErrorCodeWeakPassword] = @"weak-password",
97
+ [FIRAuthErrorCodeAppNotAuthorized] = @"app-not-authorized",
98
+ [FIRAuthErrorCodeExpiredActionCode] = @"expired-action-code",
99
+ [FIRAuthErrorCodeInvalidActionCode] = @"invalid-action-code",
100
+ [FIRAuthErrorCodeInvalidMessagePayload] = @"invalid-message-payload",
101
+ [FIRAuthErrorCodeInvalidSender] = @"invalid-sender",
102
+ [FIRAuthErrorCodeInvalidRecipientEmail] = @"invalid-recipient-email",
103
+ [FIRAuthErrorCodeMissingEmail] = @"invalid-email",
104
+ [FIRAuthErrorCodeMissingIosBundleID] = @"missing-ios-bundle-id",
105
+ [FIRAuthErrorCodeMissingAndroidPackageName] = @"missing-android-pkg-name",
106
+ [FIRAuthErrorCodeUnauthorizedDomain] = @"unauthorized-domain",
107
+ [FIRAuthErrorCodeInvalidContinueURI] = @"invalid-continue-uri",
108
+ [FIRAuthErrorCodeMissingContinueURI] = @"missing-continue-uri",
109
+ [FIRAuthErrorCodeMissingPhoneNumber] = @"missing-phone-number",
110
+ [FIRAuthErrorCodeInvalidPhoneNumber] = @"invalid-phone-number",
111
+ [FIRAuthErrorCodeMissingVerificationCode] = @"missing-verification-code",
112
+ [FIRAuthErrorCodeInvalidVerificationCode] = @"invalid-verification-code",
113
+ [FIRAuthErrorCodeMissingVerificationID] = @"missing-verification-id",
114
+ [FIRAuthErrorCodeInvalidVerificationID] = @"invalid-verification-id",
115
+ [FIRAuthErrorCodeMissingAppCredential] = @"missing-app-credential",
116
+ [FIRAuthErrorCodeInvalidAppCredential] = @"invalid-app-credential",
117
+ [FIRAuthErrorCodeSessionExpired] = @"code-expired",
118
+ [FIRAuthErrorCodeQuotaExceeded] = @"quota-exceeded",
119
+ [FIRAuthErrorCodeMissingAppToken] = @"missing-apns-token",
120
+ [FIRAuthErrorCodeNotificationNotForwarded] = @"notification-not-forwarded",
121
+ [FIRAuthErrorCodeAppNotVerified] = @"app-not-verified",
122
+ [FIRAuthErrorCodeCaptchaCheckFailed] = @"captcha-check-failed",
123
+ [FIRAuthErrorCodeWebContextAlreadyPresented] = @"cancelled-popup-request",
124
+ [FIRAuthErrorCodeWebContextCancelled] = @"popup-closed-by-user",
125
+ [FIRAuthErrorCodeAppVerificationUserInteractionFailure] =
126
+ @"app-verification-user-interaction-failure",
127
+ [FIRAuthErrorCodeInvalidClientID] = @"invalid-oauth-client-id",
128
+ [FIRAuthErrorCodeWebNetworkRequestFailed] = @"network-request-failed",
129
+ [FIRAuthErrorCodeWebInternalError] = @"internal-error",
130
+ [FIRAuthErrorCodeNullUser] = @"null-user",
131
+ [FIRAuthErrorCodeKeychainError] = @"keychain-error",
132
+ [FIRAuthErrorCodeInternalError] = @"internal-error",
133
+ [FIRAuthErrorCodeMalformedJWT] = @"malformed-jwt",
134
+ [FIRAuthErrorCodeSecondFactorRequired] = @"multi-factor-auth-required"};
135
+
136
+ static __strong NSMutableDictionary *authStateHandlers;
137
+ static __strong NSMutableDictionary *idTokenHandlers;
138
+ static __strong NSMutableDictionary *emulatorConfigs;
139
+ // Used for caching credentials between method calls.
140
+ static __strong NSMutableDictionary<NSString *, FIRAuthCredential *> *credentials;
141
+ #if TARGET_OS_IOS
142
+ static __strong NSMutableDictionary<NSString *, FIRMultiFactorResolver *> *cachedResolver;
143
+ static __strong NSMutableDictionary<NSString *, FIRMultiFactorSession *> *cachedSessions;
144
+ static __strong NSMutableDictionary<NSString *, FIRTOTPSecret *> *cachedTotpSecrets;
145
+ #endif
146
+
147
+ @interface RNFBAuthHelper ()
148
+
149
+ + (NSString *)nonEmptyStringFromDictionary:(NSDictionary *)dictionary key:(NSString *)key;
150
+ + (NSPersonNameComponents *)personNameComponentsFromDictionary:(NSDictionary *)dictionary;
151
+
152
+ + (FIRAuthCredential *)getCredentialForProvider:(NSString *)provider
153
+ token:(NSString *)authToken
154
+ secret:(NSString *)authTokenSecret
155
+ firebaseApp:(FIRApp *)firebaseApp;
156
+
157
+ + (void)reloadAndReturnUser:(FIRUser *)user
158
+ resolver:(RCTPromiseResolveBlock)resolve
159
+ rejecter:(RCTPromiseRejectBlock)reject
160
+ firebaseApp:(FIRApp *)firebaseApp;
161
+
162
+ + (void)promiseNoUser:(RCTPromiseResolveBlock)resolve
163
+ rejecter:(RCTPromiseRejectBlock)reject
164
+ isError:(BOOL)isError;
165
+
166
+ #if TARGET_OS_IOS
167
+ + (NSDictionary *)multiFactorResolverToDict:(FIRMultiFactorResolver *)resolver;
168
+ #endif
169
+
170
+ + (void)promiseRejectAuthException:(RCTPromiseRejectBlock)reject error:(NSError *)error;
171
+ + (NSDictionary *)getJSError:(NSError *)error;
172
+
173
+ + (void)promiseWithUser:(RCTPromiseResolveBlock)resolve
174
+ rejecter:(RCTPromiseRejectBlock)reject
175
+ user:(FIRUser *)user;
176
+
177
+ + (void)promiseWithAuthResult:(RCTPromiseResolveBlock)resolve
178
+ rejecter:(RCTPromiseRejectBlock)reject
179
+ authResult:(FIRAuthDataResult *)authResult;
180
+
181
+ + (NSArray<NSObject *> *)convertProviderData:(NSArray<id<FIRUserInfo>> *)providerData;
182
+ + (NSDictionary *)firebaseUserToDict:(FIRUser *)user;
183
+
184
+ #if TARGET_OS_IOS
185
+ + (NSArray<NSMutableDictionary *> *)convertMultiFactorData:(NSArray<FIRMultiFactorInfo *> *)hints;
186
+ #endif
187
+
188
+ + (NSDictionary *)authCredentialToDict:(FIRAuthCredential *)authCredential;
189
+ + (FIRActionCodeSettings *)buildActionCodeSettings:(NSDictionary *)actionCodeSettings;
190
+
191
+ + (void)initializeSharedStateOnce;
192
+
193
+ @end
194
+
195
+ @implementation RNFBAuthHelper
196
+
197
+ #pragma mark -
198
+ #pragma mark Shared state
199
+
200
+ + (void)initializeSharedStateOnce {
201
+ static dispatch_once_t onceToken;
202
+ dispatch_once(&onceToken, ^{
203
+ authStateHandlers = [[NSMutableDictionary alloc] init];
204
+ idTokenHandlers = [[NSMutableDictionary alloc] init];
205
+ emulatorConfigs = [[NSMutableDictionary alloc] init];
206
+ credentials = [[NSMutableDictionary alloc] init];
207
+ #if TARGET_OS_IOS
208
+ cachedResolver = [[NSMutableDictionary alloc] init];
209
+ cachedSessions = [[NSMutableDictionary alloc] init];
210
+ cachedTotpSecrets = [[NSMutableDictionary alloc] init];
211
+ #endif
212
+ });
213
+ }
214
+
215
+ + (void)invalidate {
216
+ [self initializeSharedStateOnce];
217
+
218
+ for (NSString *key in authStateHandlers) {
219
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:key];
220
+
221
+ [[FIRAuth authWithApp:firebaseApp]
222
+ removeAuthStateDidChangeListener:[authStateHandlers valueForKey:key]];
223
+ }
224
+ [authStateHandlers removeAllObjects];
225
+
226
+ for (NSString *key in idTokenHandlers) {
227
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:key];
228
+ [[FIRAuth authWithApp:firebaseApp]
229
+ removeIDTokenDidChangeListener:[idTokenHandlers valueForKey:key]];
230
+ }
231
+ [idTokenHandlers removeAllObjects];
232
+
233
+ [credentials removeAllObjects];
234
+ #if TARGET_OS_IOS
235
+ [cachedResolver removeAllObjects];
236
+ [cachedSessions removeAllObjects];
237
+ [cachedTotpSecrets removeAllObjects];
238
+ #endif
239
+ }
240
+
241
+ #pragma mark -
242
+ #pragma mark Firebase Auth Methods
243
+
244
+ + (void)addAuthStateListener:(NSString *)appName {
245
+ [self initializeSharedStateOnce];
246
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
247
+
248
+ if (![authStateHandlers valueForKey:firebaseApp.name]) {
249
+ FIRAuthStateDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firebaseApp]
250
+ addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) {
251
+ if (user != nil) {
252
+ [RNFBSharedUtils sendJSEventForApp:firebaseApp
253
+ name:AUTH_STATE_CHANGED_EVENT
254
+ body:@{keyUser : [self firebaseUserToDict:user]}];
255
+ } else {
256
+ [RNFBSharedUtils sendJSEventForApp:firebaseApp name:AUTH_STATE_CHANGED_EVENT body:@{}];
257
+ }
258
+ }];
259
+ authStateHandlers[firebaseApp.name] = newListenerHandle;
260
+ }
261
+ }
262
+
263
+ + (void)removeAuthStateListener:(NSString *)appName {
264
+ [self initializeSharedStateOnce];
265
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
266
+
267
+ if ([authStateHandlers valueForKey:firebaseApp.name]) {
268
+ [[FIRAuth authWithApp:firebaseApp]
269
+ removeAuthStateDidChangeListener:[authStateHandlers valueForKey:firebaseApp.name]];
270
+ [authStateHandlers removeObjectForKey:firebaseApp.name];
271
+ }
272
+ }
273
+
274
+ + (void)addIdTokenListener:(NSString *)appName {
275
+ [self initializeSharedStateOnce];
276
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
277
+
278
+ if (![idTokenHandlers valueForKey:firebaseApp.name]) {
279
+ FIRIDTokenDidChangeListenerHandle newListenerHandle = [[FIRAuth authWithApp:firebaseApp]
280
+ addIDTokenDidChangeListener:^(FIRAuth *_Nonnull auth, FIRUser *_Nullable user) {
281
+ if (user != nil) {
282
+ [RNFBSharedUtils sendJSEventForApp:firebaseApp
283
+ name:AUTH_ID_TOKEN_CHANGED_EVENT
284
+ body:@{keyUser : [self firebaseUserToDict:user]}];
285
+ } else {
286
+ [RNFBSharedUtils sendJSEventForApp:firebaseApp
287
+ name:AUTH_ID_TOKEN_CHANGED_EVENT
288
+ body:@{}];
289
+ }
290
+ }];
291
+ idTokenHandlers[firebaseApp.name] = newListenerHandle;
292
+ }
293
+ }
294
+
295
+ + (void)removeIdTokenListener:(NSString *)appName {
296
+ [self initializeSharedStateOnce];
297
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
298
+
299
+ if ([idTokenHandlers valueForKey:firebaseApp.name]) {
300
+ [[FIRAuth authWithApp:firebaseApp]
301
+ removeIDTokenDidChangeListener:[idTokenHandlers valueForKey:firebaseApp.name]];
302
+ [idTokenHandlers removeObjectForKey:firebaseApp.name];
303
+ }
304
+ }
305
+
306
+ + (void)configureAuthDomain:(NSString *)appName {
307
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
308
+
309
+ NSString *authDomain = [RNFBAppModule getCustomDomain:firebaseApp.name];
310
+ DLog(@"RNFBAuth app: %@ customAuthDomain: %@", firebaseApp.name, authDomain);
311
+ if (authDomain != nil) {
312
+ [FIRAuth authWithApp:firebaseApp].customAuthDomain = authDomain;
313
+ }
314
+ }
315
+
316
+ + (void)getCustomAuthDomain:(NSString *)appName
317
+ resolve:(RCTPromiseResolveBlock)resolve
318
+ reject:(RCTPromiseRejectBlock)reject {
319
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
320
+
321
+ resolve([FIRAuth authWithApp:firebaseApp].customAuthDomain);
322
+ }
323
+
324
+ + (void)setAppVerificationDisabledForTesting:(NSString *)appName
325
+ disabled:(BOOL)disabled
326
+ resolve:(RCTPromiseResolveBlock)resolve
327
+ reject:(RCTPromiseRejectBlock)reject {
328
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
329
+
330
+ [FIRAuth authWithApp:firebaseApp].settings.appVerificationDisabledForTesting = disabled;
331
+ resolve([NSNull null]);
332
+ }
333
+
334
+ + (void)useUserAccessGroup:(NSString *)appName
335
+ userAccessGroup:(NSString *)userAccessGroup
336
+ resolve:(RCTPromiseResolveBlock)resolve
337
+ reject:(RCTPromiseRejectBlock)reject {
338
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
339
+
340
+ NSError *error;
341
+ [[FIRAuth authWithApp:firebaseApp] useUserAccessGroup:userAccessGroup error:&error];
342
+
343
+ if (!error) {
344
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
345
+ } else {
346
+ [self promiseRejectAuthException:reject error:error];
347
+ }
348
+ return;
349
+ }
350
+
351
+ + (void)signOut:(NSString *)appName
352
+ resolve:(RCTPromiseResolveBlock)resolve
353
+ reject:(RCTPromiseRejectBlock)reject {
354
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
355
+
356
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
357
+
358
+ if (user) {
359
+ NSError *error;
360
+ [[FIRAuth authWithApp:firebaseApp] signOut:&error];
361
+ if (!error) {
362
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
363
+ } else {
364
+ [self promiseRejectAuthException:reject error:error];
365
+ }
366
+ return;
367
+ }
368
+
369
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
370
+ }
371
+
372
+ + (void)signInAnonymously:(NSString *)appName
373
+ resolve:(RCTPromiseResolveBlock)resolve
374
+ reject:(RCTPromiseRejectBlock)reject {
375
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
376
+
377
+ [[FIRAuth authWithApp:firebaseApp]
378
+ signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) {
379
+ if (error) {
380
+ [self promiseRejectAuthException:reject error:error];
381
+ } else {
382
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
383
+ }
384
+ }];
385
+ }
386
+
387
+ + (void)signInWithEmailAndPassword:(NSString *)appName
388
+ email:(NSString *)email
389
+ password:(NSString *)password
390
+ resolve:(RCTPromiseResolveBlock)resolve
391
+ reject:(RCTPromiseRejectBlock)reject {
392
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
393
+
394
+ [[FIRAuth authWithApp:firebaseApp]
395
+ signInWithEmail:email
396
+ password:password
397
+ completion:^(FIRAuthDataResult *authResult, NSError *error) {
398
+ if (error) {
399
+ [self promiseRejectAuthException:reject error:error];
400
+ } else {
401
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
402
+ }
403
+ }];
404
+ }
405
+
406
+ + (NSNumber *)isSignInWithEmailLink:(NSString *)appName emailLink:(NSString *)emailLink {
407
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
408
+
409
+ return
410
+ @([RCTConvert BOOL:@([[FIRAuth authWithApp:firebaseApp] isSignInWithEmailLink:emailLink])]);
411
+ }
412
+
413
+ + (void)signInWithEmailLink:(NSString *)appName
414
+ email:(NSString *)email
415
+ emailLink:(NSString *)emailLink
416
+ resolve:(RCTPromiseResolveBlock)resolve
417
+ reject:(RCTPromiseRejectBlock)reject {
418
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
419
+
420
+ [[FIRAuth authWithApp:firebaseApp]
421
+ signInWithEmail:email
422
+ link:emailLink
423
+ completion:^(FIRAuthDataResult *authResult, NSError *error) {
424
+ if (error) {
425
+ [self promiseRejectAuthException:reject error:error];
426
+ } else {
427
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
428
+ }
429
+ }];
430
+ }
431
+
432
+ + (void)createUserWithEmailAndPassword:(NSString *)appName
433
+ email:(NSString *)email
434
+ password:(NSString *)password
435
+ resolve:(RCTPromiseResolveBlock)resolve
436
+ reject:(RCTPromiseRejectBlock)reject {
437
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
438
+
439
+ [[FIRAuth authWithApp:firebaseApp]
440
+ createUserWithEmail:email
441
+ password:password
442
+ completion:^(FIRAuthDataResult *authResult, NSError *error) {
443
+ if (error) {
444
+ [self promiseRejectAuthException:reject error:error];
445
+ } else {
446
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
447
+ }
448
+ }];
449
+ }
450
+
451
+ + (void)deleteUser:(NSString *)appName
452
+ resolve:(RCTPromiseResolveBlock)resolve
453
+ reject:(RCTPromiseRejectBlock)reject {
454
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
455
+
456
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
457
+
458
+ if (user) {
459
+ [user deleteWithCompletion:^(NSError *_Nullable error) {
460
+ if (error) {
461
+ [self promiseRejectAuthException:reject error:error];
462
+ } else {
463
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
464
+ }
465
+ }];
466
+ } else {
467
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
468
+ }
469
+ }
470
+
471
+ + (void)reload:(NSString *)appName
472
+ resolve:(RCTPromiseResolveBlock)resolve
473
+ reject:(RCTPromiseRejectBlock)reject {
474
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
475
+
476
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
477
+ if (user) {
478
+ [self reloadAndReturnUser:user resolver:resolve rejecter:reject firebaseApp:firebaseApp];
479
+ } else {
480
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
481
+ }
482
+ }
483
+
484
+ + (void)sendEmailVerification:(NSString *)appName
485
+ actionCodeSettings:(NSDictionary *)actionCodeSettings
486
+ resolve:(RCTPromiseResolveBlock)resolve
487
+ reject:(RCTPromiseRejectBlock)reject {
488
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
489
+
490
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
491
+ if (user) {
492
+ id handler = ^(NSError *_Nullable error) {
493
+ if (error) {
494
+ [self promiseRejectAuthException:reject error:error];
495
+ } else {
496
+ FIRUser *userAfterUpdate = [FIRAuth authWithApp:firebaseApp].currentUser;
497
+ [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate];
498
+ }
499
+ };
500
+ if (actionCodeSettings) {
501
+ FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
502
+ [user sendEmailVerificationWithActionCodeSettings:settings completion:handler];
503
+ } else {
504
+ [user sendEmailVerificationWithCompletion:handler];
505
+ }
506
+ } else {
507
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
508
+ }
509
+ }
510
+
511
+ + (void)verifyBeforeUpdateEmail:(NSString *)appName
512
+ email:(NSString *)email
513
+ actionCodeSettings:(NSDictionary *)actionCodeSettings
514
+ resolve:(RCTPromiseResolveBlock)resolve
515
+ reject:(RCTPromiseRejectBlock)reject {
516
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
517
+
518
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
519
+ if (user) {
520
+ id handler = ^(NSError *_Nullable error) {
521
+ if (error) {
522
+ [self promiseRejectAuthException:reject error:error];
523
+ } else {
524
+ FIRUser *userAfterUpdate = [FIRAuth authWithApp:firebaseApp].currentUser;
525
+ [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate];
526
+ }
527
+ };
528
+ if (actionCodeSettings) {
529
+ FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
530
+ [user sendEmailVerificationBeforeUpdatingEmail:email
531
+ actionCodeSettings:settings
532
+ completion:handler];
533
+ } else {
534
+ [user sendEmailVerificationBeforeUpdatingEmail:email completion:handler];
535
+ }
536
+ } else {
537
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
538
+ }
539
+ }
540
+
541
+ + (void)updateEmail:(NSString *)appName
542
+ email:(NSString *)email
543
+ resolve:(RCTPromiseResolveBlock)resolve
544
+ reject:(RCTPromiseRejectBlock)reject {
545
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
546
+
547
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
548
+
549
+ if (user) {
550
+ [user updateEmail:email
551
+ completion:^(NSError *_Nullable error) {
552
+ if (error) {
553
+ [self promiseRejectAuthException:reject error:error];
554
+ } else {
555
+ [self reloadAndReturnUser:user
556
+ resolver:resolve
557
+ rejecter:reject
558
+ firebaseApp:firebaseApp];
559
+ }
560
+ }];
561
+ } else {
562
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
563
+ }
564
+ }
565
+
566
+ + (void)updatePassword:(NSString *)appName
567
+ password:(NSString *)password
568
+ resolve:(RCTPromiseResolveBlock)resolve
569
+ reject:(RCTPromiseRejectBlock)reject {
570
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
571
+
572
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
573
+
574
+ if (user) {
575
+ [user updatePassword:password
576
+ completion:^(NSError *_Nullable error) {
577
+ if (error) {
578
+ [self promiseRejectAuthException:reject error:error];
579
+ } else {
580
+ FIRUser *userAfterUpdate = [FIRAuth authWithApp:firebaseApp].currentUser;
581
+ [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate];
582
+ }
583
+ }];
584
+ } else {
585
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
586
+ }
587
+ }
588
+
589
+ #if TARGET_OS_IOS
590
+ + (void)updatePhoneNumber:(NSString *)appName
591
+ provider:(NSString *)provider
592
+ authToken:(NSString *)authToken
593
+ authSecret:(NSString *)authSecret
594
+ resolve:(RCTPromiseResolveBlock)resolve
595
+ reject:(RCTPromiseRejectBlock)reject {
596
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
597
+
598
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
599
+
600
+ if (user) {
601
+ FIRPhoneAuthCredential *credential =
602
+ (FIRPhoneAuthCredential *)[self getCredentialForProvider:provider
603
+ token:authToken
604
+ secret:authSecret
605
+ firebaseApp:firebaseApp];
606
+
607
+ if (credential == nil) {
608
+ [RNFBSharedUtils
609
+ rejectPromiseWithUserInfo:reject
610
+ userInfo:(NSMutableDictionary *)@{
611
+ @"code" : @"invalid-credential",
612
+ @"message" : @"The supplied auth credential is malformed, has expired "
613
+ @"or is not currently supported.",
614
+ }];
615
+ }
616
+
617
+ [user updatePhoneNumberCredential:credential
618
+ completion:^(NSError *_Nullable error) {
619
+ if (error) {
620
+ [self promiseRejectAuthException:reject error:error];
621
+ } else {
622
+ FIRUser *userAfterUpdate =
623
+ [FIRAuth authWithApp:firebaseApp].currentUser;
624
+ [self promiseWithUser:resolve rejecter:reject user:userAfterUpdate];
625
+ }
626
+ }];
627
+ } else {
628
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
629
+ }
630
+ }
631
+ #endif
632
+
633
+ + (void)updateProfile:(NSString *)appName
634
+ props:(NSDictionary *)props
635
+ resolve:(RCTPromiseResolveBlock)resolve
636
+ reject:(RCTPromiseRejectBlock)reject {
637
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
638
+
639
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
640
+
641
+ if (user) {
642
+ FIRUserProfileChangeRequest *changeRequest = [user profileChangeRequest];
643
+ NSMutableArray *allKeys = [[props allKeys] mutableCopy];
644
+
645
+ for (NSString *key in allKeys) {
646
+ @try {
647
+ if ([key isEqualToString:keyPhotoUrl]) {
648
+ NSURL *url = [NSURL URLWithString:[props valueForKey:key]];
649
+ [changeRequest setValue:url forKey:key];
650
+ } else {
651
+ [changeRequest setValue:props[key] forKey:key];
652
+ }
653
+ } @catch (NSException *exception) {
654
+ DLog(@"Exception occurred while configuring: %@", exception);
655
+ }
656
+ }
657
+
658
+ [changeRequest commitChangesWithCompletion:^(NSError *_Nullable error) {
659
+ if (error) {
660
+ [self promiseRejectAuthException:reject error:error];
661
+ } else {
662
+ [self reloadAndReturnUser:user resolver:resolve rejecter:reject firebaseApp:firebaseApp];
663
+ }
664
+ }];
665
+ } else {
666
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
667
+ }
668
+ }
669
+
670
+ + (void)getIdToken:(NSString *)appName
671
+ forceRefresh:(BOOL)forceRefresh
672
+ resolve:(RCTPromiseResolveBlock)resolve
673
+ reject:(RCTPromiseRejectBlock)reject {
674
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
675
+
676
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
677
+
678
+ if (user) {
679
+ [user getIDTokenForcingRefresh:(BOOL)forceRefresh
680
+ completion:^(NSString *token, NSError *_Nullable error) {
681
+ if (error) {
682
+ [self promiseRejectAuthException:reject error:error];
683
+ } else {
684
+ resolve(token);
685
+ }
686
+ }];
687
+ } else {
688
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
689
+ }
690
+ }
691
+
692
+ + (void)getIdTokenResult:(NSString *)appName
693
+ forceRefresh:(BOOL)forceRefresh
694
+ resolve:(RCTPromiseResolveBlock)resolve
695
+ reject:(RCTPromiseRejectBlock)reject {
696
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
697
+
698
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
699
+
700
+ if (user) {
701
+ [user
702
+ getIDTokenResultForcingRefresh:(BOOL)forceRefresh
703
+ completion:^(FIRAuthTokenResult *_Nullable tokenResult,
704
+ NSError *_Nullable error) {
705
+ if (error) {
706
+ [self promiseRejectAuthException:reject error:error];
707
+ } else {
708
+ NSMutableDictionary *tokenResultDict =
709
+ [NSMutableDictionary dictionary];
710
+ [tokenResultDict
711
+ setValue:[RNFBSharedUtils getISO8601String:tokenResult.authDate]
712
+ forKey:@"authTime"];
713
+ [tokenResultDict
714
+ setValue:[RNFBSharedUtils
715
+ getISO8601String:tokenResult.issuedAtDate]
716
+ forKey:@"issuedAtTime"];
717
+ [tokenResultDict
718
+ setValue:[RNFBSharedUtils
719
+ getISO8601String:tokenResult.expirationDate]
720
+ forKey:@"expirationTime"];
721
+
722
+ [tokenResultDict setValue:tokenResult.token forKey:@"token"];
723
+ [tokenResultDict setValue:tokenResult.claims forKey:@"claims"];
724
+
725
+ NSString *provider = tokenResult.signInProvider;
726
+ if (!provider) {
727
+ provider = tokenResult.claims[@"firebase"][@"sign_in_provider"];
728
+ }
729
+
730
+ [tokenResultDict setValue:provider forKey:@"signInProvider"];
731
+ resolve(tokenResultDict);
732
+ }
733
+ }];
734
+ } else {
735
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
736
+ }
737
+ }
738
+
739
+ + (void)signInWithCredential:(NSString *)appName
740
+ provider:(NSString *)provider
741
+ authToken:(NSString *)authToken
742
+ authSecret:(NSString *)authSecret
743
+ fullName:(NSDictionary *)fullName
744
+ resolve:(RCTPromiseResolveBlock)resolve
745
+ reject:(RCTPromiseRejectBlock)reject {
746
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
747
+
748
+ FIRAuthCredential *credential = [self getCredentialForProvider:provider
749
+ token:authToken
750
+ secret:authSecret
751
+ firebaseApp:firebaseApp];
752
+
753
+ // Sign in with Apple: if the caller supplied a non-empty fullName (only available on the
754
+ // user's first authorization), rebuild the credential so Firebase can store displayName.
755
+ // See AppleFullPersonName in auth.ts.
756
+ if ([provider compare:@"apple.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
757
+ NSPersonNameComponents *personNameComponents =
758
+ [self personNameComponentsFromDictionary:fullName];
759
+ if (personNameComponents != nil) {
760
+ credential = [FIROAuthProvider appleCredentialWithIDToken:authToken
761
+ rawNonce:authSecret
762
+ fullName:personNameComponents];
763
+ }
764
+ }
765
+
766
+ if (credential == nil) {
767
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
768
+ userInfo:(NSMutableDictionary *)@{
769
+ @"code" : @"invalid-credential",
770
+ @"message" : @"The supplied auth credential is malformed, "
771
+ @"has expired or is not currently supported.",
772
+ }];
773
+ }
774
+ DLog(@"using app SignInWithCredential: %@", firebaseApp.name);
775
+
776
+ [[FIRAuth authWithApp:firebaseApp]
777
+ signInWithCredential:credential
778
+ completion:^(FIRAuthDataResult *authResult, NSError *error) {
779
+ if (error) {
780
+ [self promiseRejectAuthException:reject error:error];
781
+ } else {
782
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
783
+ }
784
+ }];
785
+ }
786
+
787
+ + (void)signInWithProvider:(NSString *)appName
788
+ provider:(NSDictionary *)provider
789
+ resolve:(RCTPromiseResolveBlock)resolve
790
+ reject:(RCTPromiseRejectBlock)reject {
791
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
792
+
793
+ NSString *providerId = provider[@"providerId"];
794
+ if (providerId == nil) {
795
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
796
+ userInfo:(NSMutableDictionary *)@{
797
+ @"code" : @"invalid-credential",
798
+ @"message" : @"The supplied auth credential is malformed, "
799
+ @"has expired or is not currently supported.",
800
+ }];
801
+ }
802
+
803
+ __block FIROAuthProvider *builder =
804
+ [FIROAuthProvider providerWithProviderID:providerId auth:[FIRAuth authWithApp:firebaseApp]];
805
+ // Add scopes if present
806
+ if (provider[@"scopes"]) {
807
+ [builder setScopes:provider[@"scopes"]];
808
+ }
809
+ // Add custom parameters if present
810
+ if (provider[@"customParameters"]) {
811
+ [builder setCustomParameters:provider[@"customParameters"]];
812
+ }
813
+
814
+ #if TARGET_OS_IOS
815
+ [builder getCredentialWithUIDelegate:nil
816
+ completion:^(FIRAuthCredential *_Nullable credential,
817
+ NSError *_Nullable error) {
818
+ if (error) {
819
+ [self promiseRejectAuthException:reject error:error];
820
+ return;
821
+ }
822
+ if (credential) {
823
+ [[FIRAuth authWithApp:firebaseApp]
824
+ signInWithCredential:credential
825
+ completion:^(FIRAuthDataResult *_Nullable authResult,
826
+ NSError *_Nullable error) {
827
+ if (error) {
828
+ [self promiseRejectAuthException:reject
829
+ error:error];
830
+ return;
831
+ }
832
+
833
+ // NOTE: This variable has NO PURPOSE AT ALL, it is
834
+ // only to keep a strong reference to the builder
835
+ // variable so it is not deallocated prematurely by
836
+ // ARC.
837
+ NSString *providerID = builder.providerID;
838
+
839
+ [self promiseWithAuthResult:resolve
840
+ rejecter:reject
841
+ authResult:authResult];
842
+ }];
843
+ }
844
+ }];
845
+ #endif
846
+ }
847
+
848
+ + (void)confirmPasswordReset:(NSString *)appName
849
+ code:(NSString *)code
850
+ newPassword:(NSString *)newPassword
851
+ resolve:(RCTPromiseResolveBlock)resolve
852
+ reject:(RCTPromiseRejectBlock)reject {
853
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
854
+
855
+ [[FIRAuth authWithApp:firebaseApp]
856
+ confirmPasswordResetWithCode:code
857
+ newPassword:newPassword
858
+ completion:^(NSError *_Nullable error) {
859
+ if (error) {
860
+ [self promiseRejectAuthException:reject error:error];
861
+ } else {
862
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
863
+ }
864
+ }];
865
+ }
866
+
867
+ + (void)applyActionCode:(NSString *)appName
868
+ code:(NSString *)code
869
+ resolve:(RCTPromiseResolveBlock)resolve
870
+ reject:(RCTPromiseRejectBlock)reject {
871
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
872
+
873
+ [[FIRAuth authWithApp:firebaseApp]
874
+ applyActionCode:code
875
+ completion:^(NSError *_Nullable error) {
876
+ if (error) {
877
+ [self promiseRejectAuthException:reject error:error];
878
+ } else {
879
+ [self promiseWithUser:resolve
880
+ rejecter:reject
881
+ user:[FIRAuth authWithApp:firebaseApp].currentUser];
882
+ }
883
+ }];
884
+ }
885
+
886
+ + (void)checkActionCode:(NSString *)appName
887
+ code:(NSString *)code
888
+ resolve:(RCTPromiseResolveBlock)resolve
889
+ reject:(RCTPromiseRejectBlock)reject {
890
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
891
+
892
+ [[FIRAuth authWithApp:firebaseApp]
893
+ checkActionCode:code
894
+ completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) {
895
+ if (error) {
896
+ [self promiseRejectAuthException:reject error:error];
897
+ } else {
898
+ NSString *actionType = @"ERROR";
899
+ switch (info.operation) {
900
+ case FIRActionCodeOperationPasswordReset:
901
+ actionType = @"PASSWORD_RESET";
902
+ break;
903
+ case FIRActionCodeOperationVerifyEmail:
904
+ actionType = @"VERIFY_EMAIL";
905
+ break;
906
+ case FIRActionCodeOperationUnknown:
907
+ actionType = @"UNKNOWN";
908
+ break;
909
+ case FIRActionCodeOperationRecoverEmail:
910
+ actionType = @"RECOVER_EMAIL";
911
+ break;
912
+ case FIRActionCodeOperationEmailLink:
913
+ actionType = @"EMAIL_SIGNIN";
914
+ break;
915
+ case FIRActionCodeOperationVerifyAndChangeEmail:
916
+ case FIRActionCodeOperationRevertSecondFactorAddition:
917
+ default:
918
+ actionType = @"ERROR";
919
+ break;
920
+ }
921
+
922
+ NSMutableDictionary *data = [NSMutableDictionary dictionary];
923
+
924
+ if (info.email != nil) {
925
+ [data setValue:info.email forKey:keyEmail];
926
+ } else {
927
+ [data setValue:[NSNull null] forKey:keyEmail];
928
+ }
929
+
930
+ if (info.previousEmail != nil) {
931
+ [data setValue:info.previousEmail forKey:@"fromEmail"];
932
+ } else {
933
+ [data setValue:[NSNull null] forKey:@"fromEmail"];
934
+ }
935
+
936
+ NSDictionary *result = @{@"data" : data, @"operation" : actionType};
937
+
938
+ resolve(result);
939
+ }
940
+ }];
941
+ }
942
+
943
+ + (void)revokeToken:(NSString *)appName
944
+ authorizationCode:(NSString *)authorizationCode
945
+ resolve:(RCTPromiseResolveBlock)resolve
946
+ reject:(RCTPromiseRejectBlock)reject {
947
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
948
+
949
+ [[FIRAuth authWithApp:firebaseApp]
950
+ revokeTokenWithAuthorizationCode:authorizationCode
951
+ completion:^(NSError *_Nullable error) {
952
+ if (error) {
953
+ [self promiseRejectAuthException:reject error:error];
954
+ } else {
955
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
956
+ }
957
+ }];
958
+ }
959
+
960
+ + (void)sendPasswordResetEmail:(NSString *)appName
961
+ email:(NSString *)email
962
+ actionCodeSettings:(NSDictionary *)actionCodeSettings
963
+ resolve:(RCTPromiseResolveBlock)resolve
964
+ reject:(RCTPromiseRejectBlock)reject {
965
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
966
+
967
+ id handler = ^(NSError *_Nullable error) {
968
+ if (error) {
969
+ [self promiseRejectAuthException:reject error:error];
970
+ } else {
971
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
972
+ }
973
+ };
974
+
975
+ if (actionCodeSettings) {
976
+ FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
977
+ [[FIRAuth authWithApp:firebaseApp] sendPasswordResetWithEmail:email
978
+ actionCodeSettings:settings
979
+ completion:handler];
980
+ } else {
981
+ [[FIRAuth authWithApp:firebaseApp] sendPasswordResetWithEmail:email completion:handler];
982
+ }
983
+ }
984
+
985
+ + (void)sendSignInLinkToEmail:(NSString *)appName
986
+ email:(NSString *)email
987
+ actionCodeSettings:(NSDictionary *)actionCodeSettings
988
+ resolve:(RCTPromiseResolveBlock)resolve
989
+ reject:(RCTPromiseRejectBlock)reject {
990
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
991
+
992
+ id handler = ^(NSError *_Nullable error) {
993
+ if (error) {
994
+ [self promiseRejectAuthException:reject error:error];
995
+ } else {
996
+ [self promiseNoUser:resolve rejecter:reject isError:NO];
997
+ }
998
+ };
999
+
1000
+ FIRActionCodeSettings *settings = [self buildActionCodeSettings:actionCodeSettings];
1001
+ [[FIRAuth authWithApp:firebaseApp] sendSignInLinkToEmail:email
1002
+ actionCodeSettings:settings
1003
+ completion:handler];
1004
+ }
1005
+
1006
+ + (void)signInWithCustomToken:(NSString *)appName
1007
+ customToken:(NSString *)customToken
1008
+ resolve:(RCTPromiseResolveBlock)resolve
1009
+ reject:(RCTPromiseRejectBlock)reject {
1010
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1011
+
1012
+ [[FIRAuth authWithApp:firebaseApp]
1013
+ signInWithCustomToken:customToken
1014
+ completion:^(FIRAuthDataResult *authResult, NSError *error) {
1015
+ if (error) {
1016
+ [self promiseRejectAuthException:reject error:error];
1017
+ } else {
1018
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
1019
+ }
1020
+ }];
1021
+ }
1022
+
1023
+ #if TARGET_OS_IOS
1024
+ + (void)signInWithPhoneNumber:(NSString *)appName
1025
+ phoneNumber:(NSString *)phoneNumber
1026
+ forceResend:(BOOL)forceResend
1027
+ resolve:(RCTPromiseResolveBlock)resolve
1028
+ reject:(RCTPromiseRejectBlock)reject {
1029
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1030
+
1031
+ DLog(@"SignInWthPhoneNumber instance: %@", firebaseApp.name);
1032
+
1033
+ (void)forceResend;
1034
+
1035
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1036
+ verifyPhoneNumber:phoneNumber
1037
+ UIDelegate:nil
1038
+ completion:^(NSString *_Nullable verificationID, NSError *_Nullable error) {
1039
+ if (error) {
1040
+ [self promiseRejectAuthException:reject error:error];
1041
+ } else {
1042
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1043
+ [defaults setObject:verificationID forKey:@"authVerificationID"];
1044
+ resolve(@{@"verificationId" : verificationID});
1045
+ }
1046
+ }];
1047
+ }
1048
+
1049
+ + (void)verifyPhoneNumberWithMultiFactorInfo:(NSString *)appName
1050
+ hintUid:(NSString *)hintUid
1051
+ sessionKey:(NSString *)sessionKey
1052
+ resolve:(RCTPromiseResolveBlock)resolve
1053
+ reject:(RCTPromiseRejectBlock)reject {
1054
+ [self initializeSharedStateOnce];
1055
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1056
+
1057
+ if ([cachedResolver valueForKey:sessionKey] == nil) {
1058
+ [RNFBSharedUtils
1059
+ rejectPromiseWithUserInfo:reject
1060
+ userInfo:(NSMutableDictionary *)@{
1061
+ @"code" : @"invalid-multi-factor-session",
1062
+ @"message" : @"No resolver for session found. Is the session id correct?"
1063
+ }];
1064
+ return;
1065
+ }
1066
+ FIRMultiFactorSession *session = cachedResolver[sessionKey].session;
1067
+ NSPredicate *findByUid = [NSPredicate predicateWithFormat:@"UID == %@", hintUid];
1068
+ FIRMultiFactorInfo *_Nullable hint =
1069
+ [[cachedResolver[sessionKey].hints filteredArrayUsingPredicate:findByUid] firstObject];
1070
+ if (hint == nil) {
1071
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1072
+ userInfo:(NSMutableDictionary *)@{
1073
+ @"code" : @"multi-factor-info-not-found",
1074
+ @"message" : @"The user does not have a second factor "
1075
+ @"matching the identifier provided."
1076
+ }];
1077
+ return;
1078
+ }
1079
+ DLog(@"using instance verifyPhoneNumberWithMultiFactorInfo: %@", firebaseApp.name);
1080
+
1081
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1082
+ verifyPhoneNumberWithMultiFactorInfo:hint
1083
+ UIDelegate:nil
1084
+ multiFactorSession:session
1085
+ completion:^(NSString *_Nullable verificationID,
1086
+ NSError *_Nullable error) {
1087
+ if (error) {
1088
+ [self promiseRejectAuthException:reject error:error];
1089
+ } else {
1090
+ DLog(@"verificationID: %@", verificationID)
1091
+ resolve(verificationID);
1092
+ }
1093
+ }];
1094
+ }
1095
+
1096
+ + (void)verifyPhoneNumberForMultiFactor:(NSString *)appName
1097
+ phoneNumber:(NSString *)phoneNumber
1098
+ sessionKey:(NSString *)sessionKey
1099
+ resolve:(RCTPromiseResolveBlock)resolve
1100
+ reject:(RCTPromiseRejectBlock)reject {
1101
+ [self initializeSharedStateOnce];
1102
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1103
+
1104
+ DLog(@"verifyPhoneNumberForMultifactor using app: %@", firebaseApp.name);
1105
+ DLog(@"verifyPhoneNumberForMultifactor phoneNumber: %@", phoneNumber);
1106
+ DLog(@"verifyPhoneNumberForMultifactor sessionKey: %@", sessionKey);
1107
+ FIRMultiFactorSession *session = cachedSessions[sessionKey];
1108
+ if (session == nil) {
1109
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1110
+ userInfo:(NSMutableDictionary *)@{
1111
+ @"code" : @"invalid-multi-factor-session",
1112
+ @"message" : @"can't find session for provided key"
1113
+ }];
1114
+ return;
1115
+ }
1116
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1117
+ verifyPhoneNumber:phoneNumber
1118
+ UIDelegate:nil
1119
+ multiFactorSession:session
1120
+ completion:^(NSString *_Nullable verificationID, NSError *_Nullable error) {
1121
+ if (error != nil) {
1122
+ [self promiseRejectAuthException:reject error:error];
1123
+ return;
1124
+ }
1125
+
1126
+ resolve(verificationID);
1127
+ }];
1128
+ }
1129
+
1130
+ + (void)resolveMultiFactorSignIn:(NSString *)appName
1131
+ session:(NSString *)session
1132
+ verificationId:(NSString *)verificationId
1133
+ verificationCode:(NSString *)verificationCode
1134
+ resolve:(RCTPromiseResolveBlock)resolve
1135
+ reject:(RCTPromiseRejectBlock)reject {
1136
+ [self initializeSharedStateOnce];
1137
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1138
+
1139
+ DLog(@"using instance resolve MultiFactorSignIn: %@", firebaseApp.name);
1140
+
1141
+ FIRPhoneAuthCredential *credential =
1142
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1143
+ credentialWithVerificationID:verificationId
1144
+ verificationCode:verificationCode];
1145
+ DLog(@"credential: %@", credential);
1146
+
1147
+ FIRMultiFactorAssertion *assertion =
1148
+ [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
1149
+
1150
+ [cachedResolver[session] resolveSignInWithAssertion:assertion
1151
+ completion:^(FIRAuthDataResult *_Nullable authResult,
1152
+ NSError *_Nullable error) {
1153
+ DLog(@"authError: %@", error) if (error) {
1154
+ [self promiseRejectAuthException:reject error:error];
1155
+ }
1156
+ else {
1157
+ [self promiseWithAuthResult:resolve
1158
+ rejecter:reject
1159
+ authResult:authResult];
1160
+ }
1161
+ }];
1162
+ }
1163
+
1164
+ + (void)resolveTotpSignIn:(NSString *)appName
1165
+ sessionKey:(NSString *)sessionKey
1166
+ uid:(NSString *)uid
1167
+ oneTimePassword:(NSString *)oneTimePassword
1168
+ resolve:(RCTPromiseResolveBlock)resolve
1169
+ reject:(RCTPromiseRejectBlock)reject {
1170
+ [self initializeSharedStateOnce];
1171
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1172
+
1173
+ DLog(@"using instance resolve TotpSignIn: %@", firebaseApp.name);
1174
+
1175
+ FIRMultiFactorAssertion *assertion =
1176
+ [FIRTOTPMultiFactorGenerator assertionForSignInWithEnrollmentID:uid
1177
+ oneTimePassword:oneTimePassword];
1178
+ [cachedResolver[sessionKey] resolveSignInWithAssertion:assertion
1179
+ completion:^(FIRAuthDataResult *_Nullable authResult,
1180
+ NSError *_Nullable error) {
1181
+ DLog(@"authError: %@", error) if (error) {
1182
+ [self promiseRejectAuthException:reject
1183
+ error:error];
1184
+ }
1185
+ else {
1186
+ [self promiseWithAuthResult:resolve
1187
+ rejecter:reject
1188
+ authResult:authResult];
1189
+ }
1190
+ }];
1191
+ }
1192
+
1193
+ + (void)generateTotpSecret:(NSString *)appName
1194
+ sessionKey:(NSString *)sessionKey
1195
+ resolve:(RCTPromiseResolveBlock)resolve
1196
+ reject:(RCTPromiseRejectBlock)reject {
1197
+ [self initializeSharedStateOnce];
1198
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1199
+
1200
+ DLog(@"using instance resolve generateTotpSecret: %@", firebaseApp.name);
1201
+
1202
+ FIRMultiFactorSession *session = cachedSessions[sessionKey];
1203
+ DLog(@"using sessionKey: %@", sessionKey);
1204
+ DLog(@"using session: %@", session);
1205
+ [FIRTOTPMultiFactorGenerator
1206
+ generateSecretWithMultiFactorSession:session
1207
+ completion:^(FIRTOTPSecret *_Nullable totpSecret,
1208
+ NSError *_Nullable error) {
1209
+ DLog(@"authError: %@", error) if (error) {
1210
+ [self promiseRejectAuthException:reject error:error];
1211
+ }
1212
+ else {
1213
+ NSString *secretKey = totpSecret.sharedSecretKey;
1214
+ DLog(@"secretKey generated: %@", secretKey);
1215
+ cachedTotpSecrets[secretKey] = totpSecret;
1216
+ DLog(@"cachedSecret: %@", cachedTotpSecrets[secretKey]);
1217
+ resolve(@{
1218
+ @"secretKey" : secretKey,
1219
+ });
1220
+ }
1221
+ }];
1222
+ }
1223
+
1224
+ + (NSString *)generateQrCodeUrl:(NSString *)appName
1225
+ secretKey:(NSString *)secretKey
1226
+ account:(NSString *)account
1227
+ issuer:(NSString *)issuer {
1228
+ [self initializeSharedStateOnce];
1229
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1230
+
1231
+ DLog(@"generateQrCodeUrl using instance resolve generateQrCodeUrl: %@", firebaseApp.name);
1232
+ DLog(@"generateQrCodeUrl using secretKey: %@", secretKey);
1233
+ FIRTOTPSecret *totpSecret = cachedTotpSecrets[secretKey];
1234
+ if (!totpSecret) {
1235
+ RNFBAuthThrowSyncErrorWithCode(@"invalid-multi-factor-secret",
1236
+ @"can't find secret for provided key");
1237
+ }
1238
+ NSString *url = [totpSecret generateQRCodeURLWithAccountName:account issuer:issuer];
1239
+ DLog(@"generateQrCodeUrl got QR Code URL %@", url);
1240
+ return url;
1241
+ }
1242
+
1243
+ + (void)openInOtpApp:(NSString *)appName
1244
+ secretKey:(NSString *)secretKey
1245
+ qrCodeUri:(NSString *)qrCodeUri {
1246
+ [self initializeSharedStateOnce];
1247
+
1248
+ DLog(@"generateQrCodeUrl using secretKey: %@", secretKey);
1249
+ FIRTOTPSecret *totpSecret = cachedTotpSecrets[secretKey];
1250
+ DLog(@"openInOtpApp using qrCodeUri: %@", qrCodeUri);
1251
+ [totpSecret openInOTPAppWithQRCodeURL:qrCodeUri];
1252
+ }
1253
+
1254
+ + (void)getSession:(NSString *)appName
1255
+ resolve:(RCTPromiseResolveBlock)resolve
1256
+ reject:(RCTPromiseRejectBlock)reject {
1257
+ [self initializeSharedStateOnce];
1258
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1259
+
1260
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1261
+ [[user multiFactor] getSessionWithCompletion:^(FIRMultiFactorSession *_Nullable session,
1262
+ NSError *_Nullable error) {
1263
+ if (error != nil) {
1264
+ [self promiseRejectAuthException:reject error:error];
1265
+ return;
1266
+ }
1267
+
1268
+ NSString *sessionId = [NSString stringWithFormat:@"%@", @([session hash])];
1269
+ cachedSessions[sessionId] = session;
1270
+ resolve(sessionId);
1271
+ }];
1272
+ }
1273
+
1274
+ + (void)unenrollMultiFactor:(NSString *)appName
1275
+ factorUID:(NSString *)factorUID
1276
+ resolve:(RCTPromiseResolveBlock)resolve
1277
+ reject:(RCTPromiseRejectBlock)reject {
1278
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1279
+
1280
+ DLog(@"using instance unenrollMultiFactor: %@", firebaseApp.name);
1281
+
1282
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1283
+ [user.multiFactor unenrollWithFactorUID:factorUID
1284
+ completion:^(NSError *_Nullable error) {
1285
+ if (error != nil) {
1286
+ [self promiseRejectAuthException:reject error:error];
1287
+ return;
1288
+ }
1289
+
1290
+ resolve(nil);
1291
+ return;
1292
+ }];
1293
+ }
1294
+
1295
+ + (void)finalizeMultiFactorEnrollment:(NSString *)appName
1296
+ verificationId:(NSString *)verificationId
1297
+ verificationCode:(NSString *)verificationCode
1298
+ displayName:(NSString *_Nullable)displayName
1299
+ resolve:(RCTPromiseResolveBlock)resolve
1300
+ reject:(RCTPromiseRejectBlock)reject {
1301
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1302
+
1303
+ DLog(@"using instance finalizeMultifactorEnrollment: %@", firebaseApp.name);
1304
+
1305
+ FIRPhoneAuthCredential *credential =
1306
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1307
+ credentialWithVerificationID:verificationId
1308
+ verificationCode:verificationCode];
1309
+ FIRMultiFactorAssertion *assertion =
1310
+ [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
1311
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1312
+ [user.multiFactor enrollWithAssertion:assertion
1313
+ displayName:displayName
1314
+ completion:^(NSError *_Nullable error) {
1315
+ if (error != nil) {
1316
+ [self promiseRejectAuthException:reject error:error];
1317
+ return;
1318
+ }
1319
+
1320
+ resolve(nil);
1321
+ return;
1322
+ }];
1323
+ }
1324
+
1325
+ + (void)finalizeTotpEnrollment:(NSString *)appName
1326
+ totpSecret:(NSString *)totpSecret
1327
+ verificationCode:(NSString *)verificationCode
1328
+ displayName:(NSString *_Nullable)displayName
1329
+ resolve:(RCTPromiseResolveBlock)resolve
1330
+ reject:(RCTPromiseRejectBlock)reject {
1331
+ [self initializeSharedStateOnce];
1332
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1333
+
1334
+ DLog(@"using instance finalizeTotpEnrollment: %@", firebaseApp.name);
1335
+
1336
+ FIRTOTPSecret *cachedTotpSecret = cachedTotpSecrets[totpSecret];
1337
+ DLog(@"using totpSecretKey: %@", totpSecret);
1338
+ DLog(@"using cachedSecret: %@", cachedTotpSecret);
1339
+ FIRTOTPMultiFactorAssertion *assertion =
1340
+ [FIRTOTPMultiFactorGenerator assertionForEnrollmentWithSecret:cachedTotpSecret
1341
+ oneTimePassword:verificationCode];
1342
+
1343
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1344
+
1345
+ [user.multiFactor enrollWithAssertion:assertion
1346
+ displayName:displayName
1347
+ completion:^(NSError *_Nullable error) {
1348
+ if (error != nil) {
1349
+ [self promiseRejectAuthException:reject error:error];
1350
+ return;
1351
+ }
1352
+
1353
+ resolve(nil);
1354
+ return;
1355
+ }];
1356
+ }
1357
+
1358
+ + (void)verifyPhoneNumber:(NSString *)appName
1359
+ phoneNumber:(NSString *)phoneNumber
1360
+ requestKey:(NSString *)requestKey
1361
+ timeout:(double)timeout
1362
+ forceResend:(BOOL)forceResend {
1363
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1364
+
1365
+ DLog(@"using instance verifyPhoneNumber: %@", firebaseApp.name);
1366
+
1367
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1368
+ verifyPhoneNumber:phoneNumber
1369
+ UIDelegate:nil
1370
+ completion:^(NSString *_Nullable verificationID, NSError *_Nullable error) {
1371
+ if (error) {
1372
+ NSDictionary *jsError = [self getJSError:error];
1373
+ NSDictionary *body = @{
1374
+ @"type" : @"onVerificationFailed",
1375
+ @"requestKey" : requestKey,
1376
+ @"state" : @{@"error" : jsError},
1377
+ };
1378
+ [RNFBSharedUtils sendJSEventForApp:firebaseApp
1379
+ name:PHONE_AUTH_STATE_CHANGED_EVENT
1380
+ body:body];
1381
+ } else {
1382
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1383
+ [defaults setObject:verificationID forKey:@"authVerificationID"];
1384
+ NSDictionary *body = @{
1385
+ @"type" : @"onCodeSent",
1386
+ @"requestKey" : requestKey,
1387
+ @"state" : @{@"verificationId" : verificationID},
1388
+ };
1389
+ [RNFBSharedUtils sendJSEventForApp:firebaseApp
1390
+ name:PHONE_AUTH_STATE_CHANGED_EVENT
1391
+ body:body];
1392
+ }
1393
+ }];
1394
+ }
1395
+
1396
+ + (void)confirmationResultConfirm:(NSString *)appName
1397
+ verificationCode:(NSString *)verificationCode
1398
+ resolve:(RCTPromiseResolveBlock)resolve
1399
+ reject:(RCTPromiseRejectBlock)reject {
1400
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1401
+
1402
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1403
+ NSString *verificationId = [defaults stringForKey:@"authVerificationID"];
1404
+
1405
+ FIRAuthCredential *credential =
1406
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1407
+ credentialWithVerificationID:verificationId
1408
+ verificationCode:verificationCode];
1409
+
1410
+ [[FIRAuth authWithApp:firebaseApp]
1411
+ signInWithCredential:credential
1412
+ completion:^(FIRAuthDataResult *authResult, NSError *error) {
1413
+ DLog(@"auth error: %long", (long)error.code);
1414
+ if (error) {
1415
+ [self promiseRejectAuthException:reject error:error];
1416
+ } else {
1417
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
1418
+ }
1419
+ }];
1420
+ }
1421
+ #endif
1422
+
1423
+ + (void)linkWithCredential:(NSString *)appName
1424
+ provider:(NSString *)provider
1425
+ authToken:(NSString *)authToken
1426
+ authSecret:(NSString *)authSecret
1427
+ resolve:(RCTPromiseResolveBlock)resolve
1428
+ reject:(RCTPromiseRejectBlock)reject {
1429
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1430
+
1431
+ FIRAuthCredential *credential = [self getCredentialForProvider:provider
1432
+ token:authToken
1433
+ secret:authSecret
1434
+ firebaseApp:firebaseApp];
1435
+
1436
+ if (credential == nil) {
1437
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1438
+ userInfo:(NSMutableDictionary *)@{
1439
+ @"code" : @"invalid-credential",
1440
+ @"message" : @"The supplied auth credential is malformed, "
1441
+ @"has expired or is not currently supported.",
1442
+ }];
1443
+ }
1444
+
1445
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1446
+ if (user) {
1447
+ [user linkWithCredential:credential
1448
+ completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
1449
+ if (error) {
1450
+ [self promiseRejectAuthException:reject error:error];
1451
+ } else {
1452
+ [self promiseWithAuthResult:resolve rejecter:reject authResult:authResult];
1453
+ }
1454
+ }];
1455
+ } else {
1456
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1457
+ }
1458
+ }
1459
+
1460
+ + (void)linkWithProvider:(NSString *)appName
1461
+ provider:(NSDictionary *)provider
1462
+ resolve:(RCTPromiseResolveBlock)resolve
1463
+ reject:(RCTPromiseRejectBlock)reject {
1464
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1465
+
1466
+ NSString *providerId = provider[@"providerId"];
1467
+ if (providerId == nil) {
1468
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1469
+ userInfo:(NSMutableDictionary *)@{
1470
+ @"code" : @"invalid-credential",
1471
+ @"message" : @"The supplied auth credential is malformed, "
1472
+ @"has expired or is not currently supported.",
1473
+ }];
1474
+ }
1475
+
1476
+ __block FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1477
+ if (user == nil) {
1478
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1479
+ return;
1480
+ }
1481
+
1482
+ __block FIROAuthProvider *builder =
1483
+ [FIROAuthProvider providerWithProviderID:providerId auth:[FIRAuth authWithApp:firebaseApp]];
1484
+ // Add scopes if present
1485
+ if (provider[@"scopes"]) {
1486
+ [builder setScopes:provider[@"scopes"]];
1487
+ }
1488
+ // Add custom parameters if present
1489
+ if (provider[@"parameters"]) {
1490
+ [builder setCustomParameters:provider[@"parameters"]];
1491
+ }
1492
+
1493
+ #if TARGET_OS_IOS
1494
+ [builder getCredentialWithUIDelegate:nil
1495
+ completion:^(FIRAuthCredential *_Nullable credential,
1496
+ NSError *_Nullable error) {
1497
+ if (error) {
1498
+ [self promiseRejectAuthException:reject error:error];
1499
+ return;
1500
+ }
1501
+ if (credential) {
1502
+ [user linkWithCredential:credential
1503
+ completion:^(FIRAuthDataResult *_Nullable authResult,
1504
+ NSError *_Nullable error) {
1505
+ if (error) {
1506
+ [self promiseRejectAuthException:reject
1507
+ error:error];
1508
+ return;
1509
+ }
1510
+
1511
+ // NOTE: This variable has NO PURPOSE AT ALL, it is
1512
+ // only to keep a strong reference to the builder
1513
+ // variable so it is not deallocated prematurely by
1514
+ // ARC.
1515
+ NSString *providerID = builder.providerID;
1516
+
1517
+ [self promiseWithAuthResult:resolve
1518
+ rejecter:reject
1519
+ authResult:authResult];
1520
+ }];
1521
+ }
1522
+ }];
1523
+ #endif
1524
+ }
1525
+
1526
+ + (void)unlink:(NSString *)appName
1527
+ providerId:(NSString *)providerId
1528
+ resolve:(RCTPromiseResolveBlock)resolve
1529
+ reject:(RCTPromiseRejectBlock)reject {
1530
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1531
+
1532
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1533
+
1534
+ if (user) {
1535
+ [user unlinkFromProvider:providerId
1536
+ completion:^(FIRUser *_Nullable _user, NSError *_Nullable error) {
1537
+ if (error) {
1538
+ [self promiseRejectAuthException:reject error:error];
1539
+ } else {
1540
+ [self reloadAndReturnUser:user
1541
+ resolver:resolve
1542
+ rejecter:reject
1543
+ firebaseApp:firebaseApp];
1544
+ }
1545
+ }];
1546
+ } else {
1547
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1548
+ }
1549
+ }
1550
+
1551
+ + (void)reauthenticateWithCredential:(NSString *)appName
1552
+ provider:(NSString *)provider
1553
+ authToken:(NSString *)authToken
1554
+ authSecret:(NSString *)authSecret
1555
+ resolve:(RCTPromiseResolveBlock)resolve
1556
+ reject:(RCTPromiseRejectBlock)reject {
1557
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1558
+
1559
+ FIRAuthCredential *credential = [self getCredentialForProvider:provider
1560
+ token:authToken
1561
+ secret:authSecret
1562
+ firebaseApp:firebaseApp];
1563
+
1564
+ if (credential == nil) {
1565
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1566
+ userInfo:(NSMutableDictionary *)@{
1567
+ @"code" : @"invalid-credential",
1568
+ @"message" : @"The supplied auth credential is malformed, "
1569
+ @"has expired or is not currently supported.",
1570
+ }];
1571
+ }
1572
+
1573
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1574
+
1575
+ if (user) {
1576
+ [user reauthenticateWithCredential:credential
1577
+ completion:^(FIRAuthDataResult *_Nullable authResult,
1578
+ NSError *_Nullable error) {
1579
+ if (error) {
1580
+ [self promiseRejectAuthException:reject error:error];
1581
+ } else {
1582
+ [self promiseWithAuthResult:resolve
1583
+ rejecter:reject
1584
+ authResult:authResult];
1585
+ }
1586
+ }];
1587
+ } else {
1588
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1589
+ }
1590
+ }
1591
+
1592
+ + (void)reauthenticateWithProvider:(NSString *)appName
1593
+ provider:(NSDictionary *)provider
1594
+ resolve:(RCTPromiseResolveBlock)resolve
1595
+ reject:(RCTPromiseRejectBlock)reject {
1596
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1597
+
1598
+ NSString *providerId = provider[@"providerId"];
1599
+ if (providerId == nil) {
1600
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1601
+ userInfo:(NSMutableDictionary *)@{
1602
+ @"code" : @"invalid-credential",
1603
+ @"message" : @"The supplied auth credential is malformed, "
1604
+ @"has expired or is not currently supported.",
1605
+ }];
1606
+ }
1607
+
1608
+ __block FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1609
+ if (user == nil) {
1610
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1611
+ return;
1612
+ }
1613
+
1614
+ __block FIROAuthProvider *builder =
1615
+ [FIROAuthProvider providerWithProviderID:providerId auth:[FIRAuth authWithApp:firebaseApp]];
1616
+ // Add scopes if present
1617
+ if (provider[@"scopes"]) {
1618
+ [builder setScopes:provider[@"scopes"]];
1619
+ }
1620
+ // Add custom parameters if present
1621
+ if (provider[@"parameters"]) {
1622
+ [builder setCustomParameters:provider[@"parameters"]];
1623
+ }
1624
+ #if TARGET_OS_IOS
1625
+ [builder getCredentialWithUIDelegate:nil
1626
+ completion:^(FIRAuthCredential *_Nullable credential,
1627
+ NSError *_Nullable error) {
1628
+ if (error) {
1629
+ [self promiseRejectAuthException:reject error:error];
1630
+ return;
1631
+ }
1632
+ if (credential) {
1633
+ [user reauthenticateWithCredential:credential
1634
+ completion:^(
1635
+ FIRAuthDataResult *_Nullable authResult,
1636
+ NSError *_Nullable error) {
1637
+ if (error) {
1638
+ [self promiseRejectAuthException:reject
1639
+ error:error];
1640
+ return;
1641
+ }
1642
+
1643
+ // NOTE: This variable has NO PURPOSE AT
1644
+ // ALL, it is only to keep a strong
1645
+ // reference to the builder variable so it
1646
+ // is not deallocated prematurely by ARC.
1647
+ NSString *providerID = builder.providerID;
1648
+
1649
+ [self promiseWithAuthResult:resolve
1650
+ rejecter:reject
1651
+ authResult:authResult];
1652
+ }];
1653
+ }
1654
+ }];
1655
+ #endif
1656
+ }
1657
+
1658
+ + (void)fetchSignInMethodsForEmail:(NSString *)appName
1659
+ email:(NSString *)email
1660
+ resolve:(RCTPromiseResolveBlock)resolve
1661
+ reject:(RCTPromiseRejectBlock)reject {
1662
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1663
+
1664
+ [[FIRAuth authWithApp:firebaseApp]
1665
+ fetchSignInMethodsForEmail:email
1666
+ completion:^(NSArray<NSString *> *_Nullable providers,
1667
+ NSError *_Nullable error) {
1668
+ if (error) {
1669
+ [self promiseRejectAuthException:reject error:error];
1670
+ } else if (!providers) {
1671
+ NSMutableArray *emptyResponse = [[NSMutableArray alloc] init];
1672
+ resolve(emptyResponse);
1673
+ } else {
1674
+ resolve(providers);
1675
+ }
1676
+ }];
1677
+ }
1678
+
1679
+ + (void)setLanguageCode:(NSString *)appName code:(NSString *)code {
1680
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1681
+
1682
+ if (code) {
1683
+ [FIRAuth authWithApp:firebaseApp].languageCode = code;
1684
+ } else {
1685
+ [[FIRAuth authWithApp:firebaseApp] useAppLanguage];
1686
+ }
1687
+ }
1688
+
1689
+ + (void)setTenantId:(NSString *)appName
1690
+ tenantId:(NSString *)tenantId
1691
+ resolve:(RCTPromiseResolveBlock)resolve
1692
+ reject:(RCTPromiseRejectBlock)reject {
1693
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1694
+
1695
+ [FIRAuth authWithApp:firebaseApp].tenantID = tenantId;
1696
+ resolve([NSNull null]);
1697
+ }
1698
+
1699
+ + (void)useDeviceLanguage:(NSString *)appName {
1700
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1701
+
1702
+ [[FIRAuth authWithApp:firebaseApp] useAppLanguage];
1703
+ }
1704
+
1705
+ + (void)verifyPasswordResetCode:(NSString *)appName
1706
+ code:(NSString *)code
1707
+ resolve:(RCTPromiseResolveBlock)resolve
1708
+ reject:(RCTPromiseRejectBlock)reject {
1709
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1710
+
1711
+ [[FIRAuth authWithApp:firebaseApp]
1712
+ verifyPasswordResetCode:code
1713
+ completion:^(NSString *_Nullable email, NSError *_Nullable error) {
1714
+ if (error) {
1715
+ [self promiseRejectAuthException:reject error:error];
1716
+ } else {
1717
+ resolve(email);
1718
+ }
1719
+ }];
1720
+ }
1721
+
1722
+ + (void)useEmulator:(NSString *)appName host:(nonnull NSString *)host port:(double)port {
1723
+ [self initializeSharedStateOnce];
1724
+ FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
1725
+
1726
+ if (!emulatorConfigs[firebaseApp.name]) {
1727
+ [[FIRAuth authWithApp:firebaseApp] useEmulatorWithHost:host port:(NSInteger)port];
1728
+ emulatorConfigs[firebaseApp.name] = @YES;
1729
+ }
1730
+ }
1731
+
1732
+ + (NSString *)nonEmptyStringFromDictionary:(NSDictionary *)dictionary key:(NSString *)key {
1733
+ id value = dictionary[key];
1734
+ if (![value isKindOfClass:[NSString class]]) {
1735
+ return nil;
1736
+ }
1737
+
1738
+ NSString *stringValue = (NSString *)value;
1739
+ NSString *trimmed = [stringValue
1740
+ stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
1741
+ return trimmed.length > 0 ? stringValue : nil;
1742
+ }
1743
+
1744
+ + (NSPersonNameComponents *)personNameComponentsFromDictionary:(NSDictionary *)dictionary {
1745
+ if (dictionary == nil || (id)dictionary == [NSNull null]) {
1746
+ return nil;
1747
+ }
1748
+
1749
+ NSPersonNameComponents *components = [[NSPersonNameComponents alloc] init];
1750
+ BOOL hasAnyComponent = NO;
1751
+ NSString *namePrefix = [self nonEmptyStringFromDictionary:dictionary key:@"namePrefix"];
1752
+ if (namePrefix != nil) {
1753
+ components.namePrefix = namePrefix;
1754
+ hasAnyComponent = YES;
1755
+ }
1756
+ NSString *givenName = [self nonEmptyStringFromDictionary:dictionary key:@"givenName"];
1757
+ if (givenName != nil) {
1758
+ components.givenName = givenName;
1759
+ hasAnyComponent = YES;
1760
+ }
1761
+ NSString *middleName = [self nonEmptyStringFromDictionary:dictionary key:@"middleName"];
1762
+ if (middleName != nil) {
1763
+ components.middleName = middleName;
1764
+ hasAnyComponent = YES;
1765
+ }
1766
+ NSString *familyName = [self nonEmptyStringFromDictionary:dictionary key:@"familyName"];
1767
+ if (familyName != nil) {
1768
+ components.familyName = familyName;
1769
+ hasAnyComponent = YES;
1770
+ }
1771
+ NSString *nameSuffix = [self nonEmptyStringFromDictionary:dictionary key:@"nameSuffix"];
1772
+ if (nameSuffix != nil) {
1773
+ components.nameSuffix = nameSuffix;
1774
+ hasAnyComponent = YES;
1775
+ }
1776
+ NSString *nickname = [self nonEmptyStringFromDictionary:dictionary key:@"nickname"];
1777
+ if (nickname != nil) {
1778
+ components.nickname = nickname;
1779
+ hasAnyComponent = YES;
1780
+ }
1781
+ return hasAnyComponent ? components : nil;
1782
+ }
1783
+
1784
+ + (FIRAuthCredential *)getCredentialForProvider:(NSString *)provider
1785
+ token:(NSString *)authToken
1786
+ secret:(NSString *)authTokenSecret
1787
+ firebaseApp:(FIRApp *)firebaseApp {
1788
+ [self initializeSharedStateOnce];
1789
+ FIRAuthCredential *credential;
1790
+
1791
+ // First check if we cached an authToken
1792
+ if (credentials[authToken] != nil && ![credentials[authToken] isEqual:[NSNull null]]) {
1793
+ credential = credentials[authToken];
1794
+ } else if ([provider compare:@"twitter.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1795
+ credential = [FIRTwitterAuthProvider credentialWithToken:authToken secret:authTokenSecret];
1796
+ } else if ([provider compare:@"facebook.com" options:NSCaseInsensitiveSearch] == NSOrderedSame &&
1797
+ ![authTokenSecret isEqualToString:@""]) {
1798
+ credential = [FIROAuthProvider credentialWithProviderID:provider
1799
+ IDToken:authToken
1800
+ rawNonce:authTokenSecret];
1801
+ } else if ([provider compare:@"facebook.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1802
+ credential = [FIRFacebookAuthProvider credentialWithAccessToken:authToken];
1803
+ } else if ([provider compare:@"google.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1804
+ credential = [FIRGoogleAuthProvider credentialWithIDToken:authToken
1805
+ accessToken:authTokenSecret];
1806
+ } else if ([provider compare:@"apple.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1807
+ credential = [FIROAuthProvider credentialWithProviderID:provider
1808
+ IDToken:authToken
1809
+ rawNonce:authTokenSecret];
1810
+ } else if ([provider compare:@"password" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1811
+ credential = [FIREmailAuthProvider credentialWithEmail:authToken password:authTokenSecret];
1812
+ } else if ([provider compare:@"emailLink" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1813
+ credential = [FIREmailAuthProvider credentialWithEmail:authToken link:authTokenSecret];
1814
+ } else if ([provider compare:@"github.com" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1815
+ credential = [FIRGitHubAuthProvider credentialWithToken:authToken];
1816
+ } else if ([provider compare:@"phone" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1817
+ #if TARGET_OS_IOS
1818
+ DLog(@"using app credGen: %@", firebaseApp.name) credential =
1819
+ [[FIRPhoneAuthProvider providerWithAuth:[FIRAuth authWithApp:firebaseApp]]
1820
+ credentialWithVerificationID:authToken
1821
+ verificationCode:authTokenSecret];
1822
+ #endif
1823
+ } else if ([provider compare:@"oauth" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
1824
+ NSString *IDToken = authToken.length > 0 ? authToken : nil;
1825
+ NSString *accessToken = authTokenSecret.length > 0 ? authTokenSecret : nil;
1826
+ credential = [FIROAuthProvider credentialWithProviderID:@"oauth"
1827
+ IDToken:IDToken
1828
+ accessToken:accessToken];
1829
+ } else if ([provider hasPrefix:@"oidc."]) {
1830
+ credential = [FIROAuthProvider credentialWithProviderID:provider
1831
+ IDToken:authToken
1832
+ rawNonce:nil];
1833
+ } else {
1834
+ DLog(@"Provider not yet handled: %@", provider);
1835
+ }
1836
+
1837
+ return credential;
1838
+ }
1839
+
1840
+ // This is here to protect against bugs in the iOS SDK which don't
1841
+ // correctly refresh the user object when performing certain operations
1842
+ + (void)reloadAndReturnUser:(FIRUser *)user
1843
+ resolver:(RCTPromiseResolveBlock)resolve
1844
+ rejecter:(RCTPromiseRejectBlock)reject
1845
+ firebaseApp:(FIRApp *)firebaseApp {
1846
+ [user reloadWithCompletion:^(NSError *_Nullable error) {
1847
+ if (error) {
1848
+ [self promiseRejectAuthException:reject error:error];
1849
+ } else {
1850
+ [self promiseWithUser:resolve rejecter:reject user:user];
1851
+ }
1852
+ }];
1853
+ }
1854
+
1855
+ + (void)promiseNoUser:(RCTPromiseResolveBlock)resolve
1856
+ rejecter:(RCTPromiseRejectBlock)reject
1857
+ isError:(BOOL)isError {
1858
+ if (isError) {
1859
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1860
+ userInfo:(NSMutableDictionary *)@{
1861
+ @"code" : @"no-current-user",
1862
+ @"message" : @"No user currently signed in.",
1863
+ }];
1864
+ } else {
1865
+ resolve([NSNull null]);
1866
+ }
1867
+ }
1868
+
1869
+ #if TARGET_OS_IOS
1870
+ + (NSDictionary *)multiFactorResolverToDict:(FIRMultiFactorResolver *)resolver {
1871
+ // Temporarily store the non-serializable session for later
1872
+ NSString *sessionHash = [NSString stringWithFormat:@"%@", @([resolver.session hash])];
1873
+
1874
+ return @{
1875
+ @"hints" : [self convertMultiFactorData:resolver.hints],
1876
+ @"session" : sessionHash,
1877
+ @"auth" : resolver.auth
1878
+ };
1879
+ }
1880
+ #endif
1881
+
1882
+ + (void)promiseRejectAuthException:(RCTPromiseRejectBlock)reject error:(NSError *)error {
1883
+ NSDictionary *jsError = [self getJSError:error];
1884
+
1885
+ [RNFBSharedUtils
1886
+ rejectPromiseWithUserInfo:reject
1887
+ userInfo:(NSMutableDictionary *)@{
1888
+ @"code" : [jsError valueForKey:@"code"],
1889
+ @"message" : [jsError valueForKey:@"message"],
1890
+ @"nativeErrorMessage" : [jsError valueForKey:@"nativeErrorMessage"],
1891
+ @"authCredential" : [jsError valueForKey:@"authCredential"],
1892
+ @"resolver" : [jsError valueForKey:@"resolver"]
1893
+ }];
1894
+ }
1895
+
1896
+ + (NSDictionary *)getJSError:(NSError *)error {
1897
+ [self initializeSharedStateOnce];
1898
+ NSString *code = AuthErrorCode_toJSErrorCode[error.code];
1899
+ NSString *message = [error localizedDescription];
1900
+ NSString *nativeErrorMessage = [error localizedDescription];
1901
+
1902
+ if (code == nil) code = @"unknown";
1903
+
1904
+ // TODO(Salakar): replace these with a AuthErrorCode_toJSErrorMessage map (like codes now does)
1905
+ switch (error.code) {
1906
+ case FIRAuthErrorCodeInvalidCustomToken:
1907
+ message = @"The custom token format is incorrect. Please check the documentation.";
1908
+ break;
1909
+ case FIRAuthErrorCodeCustomTokenMismatch:
1910
+ message = @"The custom token corresponds to a different audience.";
1911
+ break;
1912
+ case FIRAuthErrorCodeInvalidCredential:
1913
+ message = @"The supplied auth credential is malformed or has expired.";
1914
+ break;
1915
+ case FIRAuthErrorCodeInvalidEmail:
1916
+ message = @"The email address is badly formatted.";
1917
+ break;
1918
+ case FIRAuthErrorCodeWrongPassword:
1919
+ message = @"The password is invalid or the user does not have a password.";
1920
+ break;
1921
+ case FIRAuthErrorCodeUserMismatch:
1922
+ message = @"The supplied credentials do not correspond to the previously signed in user.";
1923
+ break;
1924
+ case FIRAuthErrorCodeRequiresRecentLogin:
1925
+ message = @"This operation is sensitive and requires recent authentication. Log in again "
1926
+ @"before retrying this request.";
1927
+ break;
1928
+ case FIRAuthErrorCodeSecondFactorRequired:
1929
+ message = @"Please complete a second factor challenge to finish signing into this account.";
1930
+ break;
1931
+ case FIRAuthErrorCodeAccountExistsWithDifferentCredential:
1932
+ message = @"An account already exists with the same email address but different sign-in "
1933
+ @"credentials. Sign in using a provider associated with this email address.";
1934
+ break;
1935
+ case FIRAuthErrorCodeEmailAlreadyInUse:
1936
+ message = @"The email address is already in use by another account.";
1937
+ break;
1938
+ case FIRAuthErrorCodeCredentialAlreadyInUse:
1939
+ message = @"This credential is already associated with a different user account.";
1940
+ break;
1941
+ case FIRAuthErrorCodeUserDisabled:
1942
+ message = @"The user account has been disabled by an administrator.";
1943
+ break;
1944
+ case FIRAuthErrorCodeUserTokenExpired:
1945
+ message = @"The user's credential is no longer valid. The user must sign in again.";
1946
+ break;
1947
+ case FIRAuthErrorCodeUserNotFound:
1948
+ message = @"There is no user record corresponding to this identifier. The user may have been "
1949
+ @"deleted.";
1950
+ break;
1951
+ case FIRAuthErrorCodeInvalidUserToken:
1952
+ message = @"The user's credential is no longer valid. The user must sign in again.";
1953
+ break;
1954
+ case FIRAuthErrorCodeWeakPassword:
1955
+ message = @"The given password is invalid.";
1956
+ break;
1957
+ case FIRAuthErrorCodeOperationNotAllowed:
1958
+ message = @"This operation is not allowed. You must enable this service in the console.";
1959
+ break;
1960
+ case FIRAuthErrorCodeNetworkError:
1961
+ message = @"A network error has occurred, please try again.";
1962
+ break;
1963
+ case FIRAuthErrorCodeInternalError:
1964
+ message = @"An internal error has occurred, please try again.";
1965
+ break;
1966
+ case FIRAuthErrorCodeInvalidPhoneNumber:
1967
+ message = @"The format of the phone number provided is incorrect. "
1968
+ @"Please enter the phone number in a format that can be parsed into E.164 format. "
1969
+ @"E.164 phone numbers are written in the format [+][country code][subscriber "
1970
+ @"number including area code].";
1971
+ break;
1972
+ default:
1973
+ break;
1974
+ }
1975
+
1976
+ NSDictionary *authCredentialDict = nil;
1977
+ if ([error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey] != nil) {
1978
+ FIRAuthCredential *authCredential = [error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey];
1979
+ authCredentialDict = [self authCredentialToDict:authCredential];
1980
+ }
1981
+
1982
+ NSDictionary *resolverDict = nil;
1983
+ #if TARGET_OS_IOS
1984
+ if ([error userInfo][FIRAuthErrorUserInfoMultiFactorResolverKey] != nil) {
1985
+ FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
1986
+ resolverDict = [self multiFactorResolverToDict:resolver];
1987
+
1988
+ NSString *sessionKey = [NSString stringWithFormat:@"%@", @([resolver.session hash])];
1989
+ cachedResolver[sessionKey] = resolver;
1990
+ }
1991
+ #endif
1992
+
1993
+ return @{
1994
+ @"code" : code,
1995
+ @"message" : message,
1996
+ @"nativeErrorMessage" : nativeErrorMessage,
1997
+ @"authCredential" : authCredentialDict != nil ? (id)authCredentialDict : [NSNull null],
1998
+ @"resolver" : resolverDict != nil ? (id)resolverDict : [NSNull null]
1999
+ };
2000
+ }
2001
+
2002
+ + (void)promiseWithUser:(RCTPromiseResolveBlock)resolve
2003
+ rejecter:(RCTPromiseRejectBlock)reject
2004
+ user:(FIRUser *)user {
2005
+ if (user) {
2006
+ NSDictionary *userDict = [self firebaseUserToDict:user];
2007
+ resolve(userDict);
2008
+ } else {
2009
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
2010
+ }
2011
+ }
2012
+
2013
+ + (void)promiseWithAuthResult:(RCTPromiseResolveBlock)resolve
2014
+ rejecter:(RCTPromiseRejectBlock)reject
2015
+ authResult:(FIRAuthDataResult *)authResult {
2016
+ if (authResult && authResult.user) {
2017
+ NSMutableDictionary *authResultDict = [NSMutableDictionary dictionary];
2018
+
2019
+ if (authResult.additionalUserInfo) {
2020
+ NSMutableDictionary *additionalUserInfo = [NSMutableDictionary dictionary];
2021
+
2022
+ [additionalUserInfo setValue:@(authResult.additionalUserInfo.isNewUser) forKey:keyNewUser];
2023
+
2024
+ if (authResult.additionalUserInfo.profile) {
2025
+ [additionalUserInfo setValue:authResult.additionalUserInfo.profile forKey:keyProfile];
2026
+ } else {
2027
+ [additionalUserInfo setValue:[NSNull null] forKey:keyProfile];
2028
+ }
2029
+
2030
+ if (authResult.additionalUserInfo.providerID) {
2031
+ [additionalUserInfo setValue:authResult.additionalUserInfo.providerID forKey:keyProviderId];
2032
+ } else {
2033
+ [additionalUserInfo setValue:[NSNull null] forKey:keyProviderId];
2034
+ }
2035
+
2036
+ if (authResult.additionalUserInfo.username) {
2037
+ [additionalUserInfo setValue:authResult.additionalUserInfo.username forKey:keyUsername];
2038
+ } else {
2039
+ [additionalUserInfo setValue:[NSNull null] forKey:keyUsername];
2040
+ }
2041
+
2042
+ [authResultDict setValue:additionalUserInfo forKey:keyAdditionalUserInfo];
2043
+ } else {
2044
+ [authResultDict setValue:[NSNull null] forKey:keyAdditionalUserInfo];
2045
+ }
2046
+
2047
+ [authResultDict setValue:[self firebaseUserToDict:authResult.user] forKey:keyUser];
2048
+ resolve(authResultDict);
2049
+ } else {
2050
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
2051
+ }
2052
+ }
2053
+
2054
+ + (NSArray<NSObject *> *)convertProviderData:(NSArray<id<FIRUserInfo>> *)providerData {
2055
+ NSMutableArray *output = [NSMutableArray array];
2056
+
2057
+ for (id<FIRUserInfo> userInfo in providerData) {
2058
+ NSMutableDictionary *pData = [NSMutableDictionary dictionary];
2059
+
2060
+ if (userInfo.providerID != nil) {
2061
+ [pData setValue:userInfo.providerID forKey:keyProviderId];
2062
+ }
2063
+
2064
+ if (userInfo.uid != nil) {
2065
+ [pData setValue:userInfo.uid forKey:keyUid];
2066
+ }
2067
+
2068
+ if (userInfo.displayName != nil) {
2069
+ [pData setValue:userInfo.displayName forKey:keyDisplayName];
2070
+ }
2071
+
2072
+ if (userInfo.photoURL != nil) {
2073
+ [pData setValue:[userInfo.photoURL absoluteString] forKey:keyPhotoUrl];
2074
+ }
2075
+
2076
+ if (userInfo.email != nil) {
2077
+ [pData setValue:userInfo.email forKey:keyEmail];
2078
+ }
2079
+
2080
+ if (userInfo.phoneNumber != nil) {
2081
+ [pData setValue:userInfo.phoneNumber forKey:keyPhoneNumber];
2082
+ }
2083
+
2084
+ [output addObject:pData];
2085
+ }
2086
+
2087
+ return output;
2088
+ }
2089
+
2090
+ + (NSDictionary *)authConstantsDictionary {
2091
+ NSDictionary *firebaseApps = [FIRApp allApps];
2092
+ NSMutableDictionary *constants = [NSMutableDictionary new];
2093
+ NSMutableDictionary *appLanguage = [NSMutableDictionary new];
2094
+ NSMutableDictionary *appUser = [NSMutableDictionary new];
2095
+
2096
+ for (id key in firebaseApps) {
2097
+ FIRApp *firebaseApp = firebaseApps[key];
2098
+ NSString *appName = firebaseApp.name;
2099
+ FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
2100
+
2101
+ if ([appName isEqualToString:@"__FIRAPP_DEFAULT"]) {
2102
+ appName = @"[DEFAULT]";
2103
+ }
2104
+
2105
+ appLanguage[appName] = [FIRAuth authWithApp:firebaseApp].languageCode;
2106
+
2107
+ if (user != nil) {
2108
+ appUser[appName] = [self firebaseUserToDict:user];
2109
+ }
2110
+ }
2111
+
2112
+ constants[constAppLanguage] = appLanguage;
2113
+ constants[constAppUser] = appUser;
2114
+ return constants;
2115
+ }
2116
+
2117
+ + (NSDictionary *)firebaseUserToDict:(FIRUser *)user {
2118
+ return @{
2119
+ keyDisplayName : user.displayName ? (id)user.displayName : [NSNull null],
2120
+ keyEmail : user.email ? (id)user.email : [NSNull null],
2121
+ @"emailVerified" : @(user.emailVerified),
2122
+ @"isAnonymous" : @(user.anonymous),
2123
+ @"metadata" : @{
2124
+ @"creationTime" : user.metadata.creationDate
2125
+ ? (id) @(round([user.metadata.creationDate timeIntervalSince1970] * 1000.0))
2126
+ : [NSNull null],
2127
+ @"lastSignInTime" : user.metadata.lastSignInDate
2128
+ ? (id) @(round([user.metadata.lastSignInDate timeIntervalSince1970] * 1000.0))
2129
+ : [NSNull null],
2130
+ },
2131
+ keyPhoneNumber : user.phoneNumber ? (id)user.phoneNumber : [NSNull null],
2132
+ keyPhotoUrl : user.photoURL ? (id)[user.photoURL absoluteString] : [NSNull null],
2133
+ @"providerData" : [self convertProviderData:user.providerData],
2134
+ keyProviderId : [user.providerID lowercaseString],
2135
+ @"refreshToken" : user.refreshToken,
2136
+ @"tenantId" : user.tenantID ? (id)user.tenantID : [NSNull null],
2137
+ keyUid : user.uid,
2138
+ #if TARGET_OS_IOS
2139
+ @"multiFactor" :
2140
+ @{@"enrolledFactors" : [self convertMultiFactorData:user.multiFactor.enrolledFactors]}
2141
+ #endif
2142
+ };
2143
+ }
2144
+
2145
+ #if TARGET_OS_IOS
2146
+ + (NSArray<NSMutableDictionary *> *)convertMultiFactorData:(NSArray<FIRMultiFactorInfo *> *)hints {
2147
+ NSMutableArray *enrolledFactors = [NSMutableArray array];
2148
+
2149
+ for (FIRMultiFactorInfo *hint in hints) {
2150
+ NSString *enrollmentTime =
2151
+ [[[NSISO8601DateFormatter alloc] init] stringFromDate:hint.enrollmentDate];
2152
+
2153
+ NSMutableDictionary *factorDict = [@{
2154
+ @"uid" : hint.UID,
2155
+ @"factorId" : hint.factorID,
2156
+ @"displayName" : hint.displayName == nil ? [NSNull null] : hint.displayName,
2157
+ @"enrollmentTime" : enrollmentTime,
2158
+ // @deprecated enrollmentDate kept for backwards compatibility, please use enrollmentTime
2159
+ @"enrollmentDate" : enrollmentTime,
2160
+ } mutableCopy];
2161
+
2162
+ if ([hint isKindOfClass:[FIRPhoneMultiFactorInfo class]]) {
2163
+ FIRPhoneMultiFactorInfo *phoneHint = (FIRPhoneMultiFactorInfo *)hint;
2164
+ factorDict[@"phoneNumber"] = phoneHint.phoneNumber;
2165
+ }
2166
+
2167
+ [enrolledFactors addObject:factorDict];
2168
+ }
2169
+ return enrolledFactors;
2170
+ }
2171
+ #endif
2172
+
2173
+ + (NSDictionary *)authCredentialToDict:(FIRAuthCredential *)authCredential {
2174
+ [self initializeSharedStateOnce];
2175
+ NSString *authCredentialHash = [NSString stringWithFormat:@"%@", @([authCredential hash])];
2176
+
2177
+ // Temporarily store the non-serializable credential for later
2178
+ credentials[authCredentialHash] = authCredential;
2179
+
2180
+ return @{
2181
+ keyProviderId : authCredential.provider,
2182
+ @"token" : authCredentialHash,
2183
+ @"secret" : [NSNull null],
2184
+ };
2185
+ }
2186
+
2187
+ + (FIRActionCodeSettings *)buildActionCodeSettings:(NSDictionary *)actionCodeSettings {
2188
+ FIRActionCodeSettings *settings = [[FIRActionCodeSettings alloc] init];
2189
+
2190
+ NSString *url = actionCodeSettings[keyUrl];
2191
+ [settings setURL:[NSURL URLWithString:url]];
2192
+
2193
+ if (actionCodeSettings[keyLinkDomain]) {
2194
+ NSString *linkDomain = actionCodeSettings[keyLinkDomain];
2195
+ [settings setLinkDomain:linkDomain];
2196
+ }
2197
+
2198
+ if (actionCodeSettings[keyHandleCodeInApp]) {
2199
+ BOOL handleCodeInApp = [actionCodeSettings[keyHandleCodeInApp] boolValue];
2200
+ [settings setHandleCodeInApp:handleCodeInApp];
2201
+ }
2202
+
2203
+ if (actionCodeSettings[keyAndroid]) {
2204
+ NSDictionary *android = actionCodeSettings[keyAndroid];
2205
+ NSString *packageName = android[keyPackageName];
2206
+ NSString *minimumVersion = android[keyMinVersion];
2207
+ BOOL installApp = [android[keyInstallApp] boolValue];
2208
+ [settings setAndroidPackageName:packageName
2209
+ installIfNotAvailable:installApp
2210
+ minimumVersion:minimumVersion];
2211
+ }
2212
+
2213
+ if (actionCodeSettings[keyIOS]) {
2214
+ NSDictionary *ios = actionCodeSettings[keyIOS];
2215
+ [settings setIOSBundleID:ios[keyBundleId]];
2216
+ }
2217
+
2218
+ return settings;
2219
+ }
2220
+
2221
+ @end