@react-native-firebase/auth 23.1.2 → 23.2.1
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.
- package/CHANGELOG.md +17 -0
- package/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java +150 -0
- package/ios/RNFBAuth/RNFBAuthModule.m +137 -2
- package/lib/MultiFactorResolver.js +7 -2
- package/lib/TotpMultiFactorGenerator.js +56 -0
- package/lib/TotpSecret.js +67 -0
- package/lib/getMultiFactorResolver.js +4 -0
- package/lib/index.d.ts +79 -0
- package/lib/index.js +9 -0
- package/lib/multiFactor.js +15 -4
- package/lib/version.js +1 -1
- package/lib/web/RNFBAuthModule.js +134 -5
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
@@ -3,6 +3,23 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
5
5
|
|
6
|
+
## [23.2.1](https://github.com/invertase/react-native-firebase/compare/v23.2.0...v23.2.1) (2025-09-01)
|
7
|
+
|
8
|
+
**Note:** Version bump only for package @react-native-firebase/auth
|
9
|
+
|
10
|
+
## [23.2.0](https://github.com/invertase/react-native-firebase/compare/v23.1.2...v23.2.0) (2025-08-29)
|
11
|
+
|
12
|
+
### Features
|
13
|
+
|
14
|
+
- **auth:** QR code generation from TOTP secrets ([dd8e14b](https://github.com/invertase/react-native-firebase/commit/dd8e14b3387a8d6a0a48e3379d6379d7a3dae14d))
|
15
|
+
- **auth:** support native TOTP app open ([213ee45](https://github.com/invertase/react-native-firebase/commit/213ee456894d21666ccdd6f179232aefba19658a))
|
16
|
+
- **auth:** support TOTP enroll and unenroll ([0ad0658](https://github.com/invertase/react-native-firebase/commit/0ad0658ecb6d586c4428bf34b034add03fb90e3e))
|
17
|
+
- **other:** implement TOTP auth for Other platform ([3fbc43a](https://github.com/invertase/react-native-firebase/commit/3fbc43a1f1ccf768c5f76a962a59d1850f73ba5a))
|
18
|
+
|
19
|
+
### Bug Fixes
|
20
|
+
|
21
|
+
- **auth:** add TotpSecret type definition ([be01081](https://github.com/invertase/react-native-firebase/commit/be0108134c93c57fcdac1069ac28b7aab9fc62be))
|
22
|
+
|
6
23
|
## [23.1.2](https://github.com/invertase/react-native-firebase/compare/v23.1.1...v23.1.2) (2025-08-25)
|
7
24
|
|
8
25
|
**Note:** Version bump only for package @react-native-firebase/auth
|
@@ -66,6 +66,9 @@ import com.google.firebase.auth.PhoneAuthProvider;
|
|
66
66
|
import com.google.firebase.auth.PhoneMultiFactorAssertion;
|
67
67
|
import com.google.firebase.auth.PhoneMultiFactorGenerator;
|
68
68
|
import com.google.firebase.auth.PhoneMultiFactorInfo;
|
69
|
+
import com.google.firebase.auth.TotpMultiFactorAssertion;
|
70
|
+
import com.google.firebase.auth.TotpMultiFactorGenerator;
|
71
|
+
import com.google.firebase.auth.TotpSecret;
|
69
72
|
import com.google.firebase.auth.TwitterAuthProvider;
|
70
73
|
import com.google.firebase.auth.UserInfo;
|
71
74
|
import com.google.firebase.auth.UserProfileChangeRequest;
|
@@ -107,6 +110,7 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
|
|
107
110
|
|
108
111
|
private final HashMap<String, MultiFactorResolver> mCachedResolvers = new HashMap<>();
|
109
112
|
private final HashMap<String, MultiFactorSession> mMultiFactorSessions = new HashMap<>();
|
113
|
+
private final HashMap<String, TotpSecret> mTotpSecrets = new HashMap<>();
|
110
114
|
|
111
115
|
// storage for anonymous phone auth credentials, used for linkWithCredentials
|
112
116
|
// https://github.com/invertase/react-native-firebase/issues/4911
|
@@ -154,6 +158,7 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
|
|
154
158
|
|
155
159
|
mCachedResolvers.clear();
|
156
160
|
mMultiFactorSessions.clear();
|
161
|
+
mTotpSecrets.clear();
|
157
162
|
}
|
158
163
|
|
159
164
|
@ReactMethod
|
@@ -1130,6 +1135,26 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
|
|
1130
1135
|
});
|
1131
1136
|
}
|
1132
1137
|
|
1138
|
+
@ReactMethod
|
1139
|
+
public void unenrollMultiFactor(
|
1140
|
+
final String appName, final String factorUID, final Promise promise) {
|
1141
|
+
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
1142
|
+
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
1143
|
+
firebaseAuth
|
1144
|
+
.getCurrentUser()
|
1145
|
+
.getMultiFactor()
|
1146
|
+
.unenroll(factorUID)
|
1147
|
+
.addOnCompleteListener(
|
1148
|
+
task -> {
|
1149
|
+
if (!task.isSuccessful()) {
|
1150
|
+
rejectPromiseWithExceptionMap(promise, task.getException());
|
1151
|
+
return;
|
1152
|
+
}
|
1153
|
+
|
1154
|
+
promise.resolve(null);
|
1155
|
+
});
|
1156
|
+
}
|
1157
|
+
|
1133
1158
|
@ReactMethod
|
1134
1159
|
public void verifyPhoneNumberWithMultiFactorInfo(
|
1135
1160
|
final String appName, final String hintUid, final String sessionKey, final Promise promise) {
|
@@ -1280,6 +1305,67 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
|
|
1280
1305
|
});
|
1281
1306
|
}
|
1282
1307
|
|
1308
|
+
@ReactMethod
|
1309
|
+
public void generateQrCodeUrl(
|
1310
|
+
final String appName,
|
1311
|
+
final String secretKey,
|
1312
|
+
final String account,
|
1313
|
+
final String issuer,
|
1314
|
+
final Promise promise) {
|
1315
|
+
|
1316
|
+
TotpSecret secret = mTotpSecrets.get(secretKey);
|
1317
|
+
if (secret == null) {
|
1318
|
+
rejectPromiseWithCodeAndMessage(
|
1319
|
+
promise, "invalid-multi-factor-secret", "can't find secret for provided key");
|
1320
|
+
return;
|
1321
|
+
}
|
1322
|
+
promise.resolve(secret.generateQrCodeUrl(account, issuer));
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
@ReactMethod
|
1326
|
+
public void openInOtpApp(final String appName, final String secretKey, final String qrCodeUri) {
|
1327
|
+
TotpSecret secret = mTotpSecrets.get(secretKey);
|
1328
|
+
if (secret != null) {
|
1329
|
+
secret.openInOtpApp(qrCodeUri);
|
1330
|
+
}
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
@ReactMethod
|
1334
|
+
public void finalizeTotpEnrollment(
|
1335
|
+
final String appName,
|
1336
|
+
final String totpSecret,
|
1337
|
+
final String verificationCode,
|
1338
|
+
@Nullable final String displayName,
|
1339
|
+
final Promise promise) {
|
1340
|
+
|
1341
|
+
TotpSecret secret = mTotpSecrets.get(totpSecret);
|
1342
|
+
if (secret == null) {
|
1343
|
+
rejectPromiseWithCodeAndMessage(
|
1344
|
+
promise, "invalid-multi-factor-secret", "can't find secret for provided key");
|
1345
|
+
return;
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
TotpMultiFactorAssertion assertion =
|
1349
|
+
TotpMultiFactorGenerator.getAssertionForEnrollment(secret, verificationCode);
|
1350
|
+
|
1351
|
+
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
|
1352
|
+
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
1353
|
+
|
1354
|
+
firebaseAuth
|
1355
|
+
.getCurrentUser()
|
1356
|
+
.getMultiFactor()
|
1357
|
+
.enroll(assertion, displayName)
|
1358
|
+
.addOnCompleteListener(
|
1359
|
+
task -> {
|
1360
|
+
if (!task.isSuccessful()) {
|
1361
|
+
rejectPromiseWithExceptionMap(promise, task.getException());
|
1362
|
+
return;
|
1363
|
+
}
|
1364
|
+
|
1365
|
+
promise.resolve(null);
|
1366
|
+
});
|
1367
|
+
}
|
1368
|
+
|
1283
1369
|
/**
|
1284
1370
|
* This method is intended to resolve a {@link PhoneAuthCredential} obtained through a
|
1285
1371
|
* multi-factor authentication flow. A credential can either be obtained using:
|
@@ -1335,6 +1421,70 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
|
|
1335
1421
|
resolveMultiFactorCredential(credential, session, promise);
|
1336
1422
|
}
|
1337
1423
|
|
1424
|
+
@ReactMethod
|
1425
|
+
public void resolveTotpSignIn(
|
1426
|
+
final String appName,
|
1427
|
+
final String sessionKey,
|
1428
|
+
final String uid,
|
1429
|
+
final String oneTimePassword,
|
1430
|
+
final Promise promise) {
|
1431
|
+
|
1432
|
+
final MultiFactorAssertion assertion =
|
1433
|
+
TotpMultiFactorGenerator.getAssertionForSignIn(uid, oneTimePassword);
|
1434
|
+
|
1435
|
+
final MultiFactorResolver resolver = mCachedResolvers.get(sessionKey);
|
1436
|
+
if (resolver == null) {
|
1437
|
+
// See https://firebase.google.com/docs/reference/node/firebase.auth.multifactorresolver for
|
1438
|
+
// the error code
|
1439
|
+
rejectPromiseWithCodeAndMessage(
|
1440
|
+
promise,
|
1441
|
+
"invalid-multi-factor-session",
|
1442
|
+
"No resolver for session found. Is the session id correct?");
|
1443
|
+
return;
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
resolver
|
1447
|
+
.resolveSignIn(assertion)
|
1448
|
+
.addOnCompleteListener(
|
1449
|
+
task -> {
|
1450
|
+
if (task.isSuccessful()) {
|
1451
|
+
AuthResult authResult = task.getResult();
|
1452
|
+
promiseWithAuthResult(authResult, promise);
|
1453
|
+
} else {
|
1454
|
+
promiseRejectAuthException(promise, task.getException());
|
1455
|
+
}
|
1456
|
+
});
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
@ReactMethod
|
1460
|
+
public void generateTotpSecret(
|
1461
|
+
final String appName, final String sessionKey, final Promise promise) {
|
1462
|
+
|
1463
|
+
final MultiFactorSession session = mMultiFactorSessions.get(sessionKey);
|
1464
|
+
if (session == null) {
|
1465
|
+
rejectPromiseWithCodeAndMessage(
|
1466
|
+
promise,
|
1467
|
+
"invalid-multi-factor-session",
|
1468
|
+
"No resolver for session found. Is the session id correct?");
|
1469
|
+
return;
|
1470
|
+
}
|
1471
|
+
|
1472
|
+
TotpMultiFactorGenerator.generateSecret(session)
|
1473
|
+
.addOnCompleteListener(
|
1474
|
+
task -> {
|
1475
|
+
if (task.isSuccessful()) {
|
1476
|
+
TotpSecret totpSecret = task.getResult();
|
1477
|
+
String totpSecretKey = totpSecret.getSharedSecretKey();
|
1478
|
+
mTotpSecrets.put(totpSecretKey, totpSecret);
|
1479
|
+
WritableMap result = Arguments.createMap();
|
1480
|
+
result.putString("secretKey", totpSecretKey);
|
1481
|
+
promise.resolve(result);
|
1482
|
+
} else {
|
1483
|
+
promiseRejectAuthException(promise, task.getException());
|
1484
|
+
}
|
1485
|
+
});
|
1486
|
+
}
|
1487
|
+
|
1338
1488
|
@ReactMethod
|
1339
1489
|
public void confirmationResultConfirm(
|
1340
1490
|
String appName, final String verificationCode, final Promise promise) {
|
@@ -58,6 +58,7 @@ static __strong NSMutableDictionary<NSString *, FIRAuthCredential *> *credential
|
|
58
58
|
#if TARGET_OS_IOS
|
59
59
|
static __strong NSMutableDictionary<NSString *, FIRMultiFactorResolver *> *cachedResolver;
|
60
60
|
static __strong NSMutableDictionary<NSString *, FIRMultiFactorSession *> *cachedSessions;
|
61
|
+
static __strong NSMutableDictionary<NSString *, FIRTOTPSecret *> *cachedTotpSecrets;
|
61
62
|
#endif
|
62
63
|
|
63
64
|
@implementation RNFBAuthModule
|
@@ -81,6 +82,7 @@ RCT_EXPORT_MODULE();
|
|
81
82
|
#if TARGET_OS_IOS
|
82
83
|
cachedResolver = [[NSMutableDictionary alloc] init];
|
83
84
|
cachedSessions = [[NSMutableDictionary alloc] init];
|
85
|
+
cachedTotpSecrets = [[NSMutableDictionary alloc] init];
|
84
86
|
#endif
|
85
87
|
});
|
86
88
|
return self;
|
@@ -110,6 +112,7 @@ RCT_EXPORT_MODULE();
|
|
110
112
|
#if TARGET_OS_IOS
|
111
113
|
[cachedResolver removeAllObjects];
|
112
114
|
[cachedSessions removeAllObjects];
|
115
|
+
[cachedTotpSecrets removeAllObjects];
|
113
116
|
#endif
|
114
117
|
}
|
115
118
|
|
@@ -967,6 +970,87 @@ RCT_EXPORT_METHOD(resolveMultiFactorSignIn
|
|
967
970
|
}];
|
968
971
|
}
|
969
972
|
|
973
|
+
RCT_EXPORT_METHOD(resolveTotpSignIn
|
974
|
+
: (FIRApp *)firebaseApp
|
975
|
+
: (NSString *)sessionKey
|
976
|
+
: (NSString *)uid
|
977
|
+
: (NSString *)oneTimePassword
|
978
|
+
: (RCTPromiseResolveBlock)resolve
|
979
|
+
: (RCTPromiseRejectBlock)reject) {
|
980
|
+
DLog(@"using instance resolve TotpSignIn: %@", firebaseApp.name);
|
981
|
+
|
982
|
+
FIRMultiFactorAssertion *assertion =
|
983
|
+
[FIRTOTPMultiFactorGenerator assertionForSignInWithEnrollmentID:uid
|
984
|
+
oneTimePassword:oneTimePassword];
|
985
|
+
[cachedResolver[sessionKey] resolveSignInWithAssertion:assertion
|
986
|
+
completion:^(FIRAuthDataResult *_Nullable authResult,
|
987
|
+
NSError *_Nullable error) {
|
988
|
+
DLog(@"authError: %@", error) if (error) {
|
989
|
+
[self promiseRejectAuthException:reject
|
990
|
+
error:error];
|
991
|
+
}
|
992
|
+
else {
|
993
|
+
[self promiseWithAuthResult:resolve
|
994
|
+
rejecter:reject
|
995
|
+
authResult:authResult];
|
996
|
+
}
|
997
|
+
}];
|
998
|
+
}
|
999
|
+
|
1000
|
+
RCT_EXPORT_METHOD(generateTotpSecret
|
1001
|
+
: (FIRApp *)firebaseApp
|
1002
|
+
: (NSString *)sessionKey
|
1003
|
+
: (RCTPromiseResolveBlock)resolve
|
1004
|
+
: (RCTPromiseRejectBlock)reject) {
|
1005
|
+
DLog(@"using instance resolve generateTotpSecret: %@", firebaseApp.name);
|
1006
|
+
|
1007
|
+
FIRMultiFactorSession *session = cachedSessions[sessionKey];
|
1008
|
+
DLog(@"using sessionKey: %@", sessionKey);
|
1009
|
+
DLog(@"using session: %@", session);
|
1010
|
+
[FIRTOTPMultiFactorGenerator
|
1011
|
+
generateSecretWithMultiFactorSession:session
|
1012
|
+
completion:^(FIRTOTPSecret *_Nullable totpSecret,
|
1013
|
+
NSError *_Nullable error) {
|
1014
|
+
DLog(@"authError: %@", error) if (error) {
|
1015
|
+
[self promiseRejectAuthException:reject error:error];
|
1016
|
+
}
|
1017
|
+
else {
|
1018
|
+
NSString *secretKey = totpSecret.sharedSecretKey;
|
1019
|
+
DLog(@"secretKey generated: %@", secretKey);
|
1020
|
+
cachedTotpSecrets[secretKey] = totpSecret;
|
1021
|
+
DLog(@"cachedSecret: %@", cachedTotpSecrets[secretKey]);
|
1022
|
+
resolve(@{
|
1023
|
+
@"secretKey" : secretKey,
|
1024
|
+
});
|
1025
|
+
}
|
1026
|
+
}];
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
RCT_EXPORT_METHOD(generateQrCodeUrl
|
1030
|
+
: (FIRApp *)firebaseApp
|
1031
|
+
: (NSString *)secretKey
|
1032
|
+
: (NSString *)accountName
|
1033
|
+
: (NSString *)issuer
|
1034
|
+
: (RCTPromiseResolveBlock)resolve
|
1035
|
+
: (RCTPromiseRejectBlock)reject) {
|
1036
|
+
DLog(@"generateQrCodeUrl using instance resolve generateQrCodeUrl: %@", firebaseApp.name);
|
1037
|
+
DLog(@"generateQrCodeUrl using secretKey: %@", secretKey);
|
1038
|
+
FIRTOTPSecret *totpSecret = cachedTotpSecrets[secretKey];
|
1039
|
+
NSString *url = [totpSecret generateQRCodeURLWithAccountName:accountName issuer:issuer];
|
1040
|
+
DLog(@"generateQrCodeUrl got QR Code URL %@", url);
|
1041
|
+
resolve(url);
|
1042
|
+
}
|
1043
|
+
|
1044
|
+
RCT_EXPORT_METHOD(openInOtpApp
|
1045
|
+
: (FIRApp *)firebaseApp
|
1046
|
+
: (NSString *)secretKey
|
1047
|
+
: (NSString *)qrCodeUri) {
|
1048
|
+
DLog(@"generateQrCodeUrl using secretKey: %@", secretKey);
|
1049
|
+
FIRTOTPSecret *totpSecret = cachedTotpSecrets[secretKey];
|
1050
|
+
DLog(@"openInOtpApp using qrCodeUri: %@", qrCodeUri);
|
1051
|
+
[totpSecret openInOTPAppWithQRCodeURL:qrCodeUri];
|
1052
|
+
}
|
1053
|
+
|
970
1054
|
RCT_EXPORT_METHOD(getSession
|
971
1055
|
: (FIRApp *)firebaseApp
|
972
1056
|
: (RCTPromiseResolveBlock)resolve
|
@@ -985,6 +1069,26 @@ RCT_EXPORT_METHOD(getSession
|
|
985
1069
|
}];
|
986
1070
|
}
|
987
1071
|
|
1072
|
+
RCT_EXPORT_METHOD(unenrollMultiFactor
|
1073
|
+
: (FIRApp *)firebaseApp
|
1074
|
+
: (NSString *)factorUID
|
1075
|
+
: (RCTPromiseResolveBlock)resolve
|
1076
|
+
: (RCTPromiseRejectBlock)reject) {
|
1077
|
+
DLog(@"using instance unenrollMultiFactor: %@", firebaseApp.name);
|
1078
|
+
|
1079
|
+
FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
|
1080
|
+
[user.multiFactor unenrollWithFactorUID:factorUID
|
1081
|
+
completion:^(NSError *_Nullable error) {
|
1082
|
+
if (error != nil) {
|
1083
|
+
[self promiseRejectAuthException:reject error:error];
|
1084
|
+
return;
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
resolve(nil);
|
1088
|
+
return;
|
1089
|
+
}];
|
1090
|
+
}
|
1091
|
+
|
988
1092
|
RCT_EXPORT_METHOD(finalizeMultiFactorEnrollment
|
989
1093
|
: (FIRApp *)firebaseApp
|
990
1094
|
: (NSString *)verificationId
|
@@ -1014,6 +1118,37 @@ RCT_EXPORT_METHOD(finalizeMultiFactorEnrollment
|
|
1014
1118
|
}];
|
1015
1119
|
}
|
1016
1120
|
|
1121
|
+
RCT_EXPORT_METHOD(finalizeTotpEnrollment
|
1122
|
+
: (FIRApp *)firebaseApp
|
1123
|
+
: (NSString *)totpSecret
|
1124
|
+
: (NSString *)verificationCode
|
1125
|
+
: (NSString *_Nullable)displayName
|
1126
|
+
: (RCTPromiseResolveBlock)resolve
|
1127
|
+
: (RCTPromiseRejectBlock)reject) {
|
1128
|
+
DLog(@"using instance finalizeTotpEnrollment: %@", firebaseApp.name);
|
1129
|
+
|
1130
|
+
FIRTOTPSecret *cachedTotpSecret = cachedTotpSecrets[totpSecret];
|
1131
|
+
DLog(@"using totpSecretKey: %@", totpSecret);
|
1132
|
+
DLog(@"using cachedSecret: %@", cachedTotpSecret);
|
1133
|
+
FIRTOTPMultiFactorAssertion *assertion =
|
1134
|
+
[FIRTOTPMultiFactorGenerator assertionForEnrollmentWithSecret:cachedTotpSecret
|
1135
|
+
oneTimePassword:verificationCode];
|
1136
|
+
|
1137
|
+
FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
|
1138
|
+
|
1139
|
+
[user.multiFactor enrollWithAssertion:assertion
|
1140
|
+
displayName:displayName
|
1141
|
+
completion:^(NSError *_Nullable error) {
|
1142
|
+
if (error != nil) {
|
1143
|
+
[self promiseRejectAuthException:reject error:error];
|
1144
|
+
return;
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
resolve(nil);
|
1148
|
+
return;
|
1149
|
+
}];
|
1150
|
+
}
|
1151
|
+
|
1017
1152
|
RCT_EXPORT_METHOD(verifyPhoneNumber
|
1018
1153
|
: (FIRApp *)firebaseApp
|
1019
1154
|
: (NSString *)phoneNumber
|
@@ -1741,12 +1876,12 @@ RCT_EXPORT_METHOD(useEmulator
|
|
1741
1876
|
@"enrollmentDate" : enrollmentTime,
|
1742
1877
|
} mutableCopy];
|
1743
1878
|
|
1744
|
-
// only support phone mutli factor
|
1745
1879
|
if ([hint isKindOfClass:[FIRPhoneMultiFactorInfo class]]) {
|
1746
1880
|
FIRPhoneMultiFactorInfo *phoneHint = (FIRPhoneMultiFactorInfo *)hint;
|
1747
1881
|
factorDict[@"phoneNumber"] = phoneHint.phoneNumber;
|
1748
|
-
[enrolledFactors addObject:factorDict];
|
1749
1882
|
}
|
1883
|
+
|
1884
|
+
[enrolledFactors addObject:factorDict];
|
1750
1885
|
}
|
1751
1886
|
return enrolledFactors;
|
1752
1887
|
}
|
@@ -9,7 +9,12 @@ export default class MultiFactorResolver {
|
|
9
9
|
}
|
10
10
|
|
11
11
|
resolveSignIn(assertion) {
|
12
|
-
const { token, secret } = assertion;
|
13
|
-
|
12
|
+
const { token, secret, uid, verificationCode } = assertion;
|
13
|
+
|
14
|
+
if (token && secret) {
|
15
|
+
return this._auth.resolveMultiFactorSignIn(this.session, token, secret);
|
16
|
+
}
|
17
|
+
|
18
|
+
return this._auth.resolveTotpSignIn(this.session, uid, verificationCode);
|
14
19
|
}
|
15
20
|
}
|
@@ -0,0 +1,56 @@
|
|
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
|
+
import { isOther } from '@react-native-firebase/app/lib/common';
|
19
|
+
import { TotpSecret } from './TotpSecret';
|
20
|
+
import { getAuth } from './modular';
|
21
|
+
|
22
|
+
export default class TotpMultiFactorGenerator {
|
23
|
+
static FACTOR_ID = 'totp';
|
24
|
+
|
25
|
+
constructor() {
|
26
|
+
throw new Error(
|
27
|
+
'`new TotpMultiFactorGenerator()` is not supported on the native Firebase SDKs.',
|
28
|
+
);
|
29
|
+
}
|
30
|
+
|
31
|
+
static assertionForSignIn(uid, verificationCode) {
|
32
|
+
if (isOther) {
|
33
|
+
// we require the web native assertion when using firebase-js-sdk
|
34
|
+
// as it has functions used by the SDK, a shim won't do
|
35
|
+
return getAuth().native.assertionForSignIn(uid, verificationCode);
|
36
|
+
}
|
37
|
+
return { uid, verificationCode };
|
38
|
+
}
|
39
|
+
|
40
|
+
static assertionForEnrollment(totpSecret, verificationCode) {
|
41
|
+
return { totpSecret: totpSecret.secretKey, verificationCode };
|
42
|
+
}
|
43
|
+
|
44
|
+
static async generateSecret(session, auth) {
|
45
|
+
if (!session) {
|
46
|
+
throw new Error('Session is required to generate a TOTP secret.');
|
47
|
+
}
|
48
|
+
const {
|
49
|
+
secretKey,
|
50
|
+
// Other properties are not publicly exposed in native APIs
|
51
|
+
// hashingAlgorithm, codeLength, codeIntervalSeconds, enrollmentCompletionDeadline
|
52
|
+
} = await auth.native.generateTotpSecret(session);
|
53
|
+
|
54
|
+
return new TotpSecret(secretKey, auth);
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,67 @@
|
|
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
|
+
import { isString } from '@react-native-firebase/app/lib/common';
|
18
|
+
|
19
|
+
export class TotpSecret {
|
20
|
+
constructor(secretKey, auth) {
|
21
|
+
// The native TotpSecret has many more properties, but they are
|
22
|
+
// internal to the native SDKs, we only maintain the secret in JS layer
|
23
|
+
this.secretKey = secretKey;
|
24
|
+
|
25
|
+
// we do need a handle to the correct auth instance to generate QR codes etc
|
26
|
+
this.auth = auth;
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs.
|
31
|
+
*/
|
32
|
+
secretKey = null;
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Returns a QR code URL as described in
|
36
|
+
* https://github.com/google/google-authenticator/wiki/Key-Uri-Format
|
37
|
+
* This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator.
|
38
|
+
* If the optional parameters are unspecified, an accountName of <userEmail> and issuer of <firebaseAppName> are used.
|
39
|
+
*
|
40
|
+
* @param accountName the name of the account/app along with a user identifier.
|
41
|
+
* @param issuer issuer of the TOTP (likely the app name).
|
42
|
+
* @returns A Promise that resolves to a QR code URL string.
|
43
|
+
*/
|
44
|
+
async generateQrCodeUrl(accountName, issuer) {
|
45
|
+
// accountName and issure are nullable in the API specification but are
|
46
|
+
// required by tha native SDK. The JS SDK returns '' if they are missing/empty.
|
47
|
+
if (!isString(accountName) || !isString(issuer) || accountName === '' || issuer === '') {
|
48
|
+
return '';
|
49
|
+
}
|
50
|
+
return this.auth.native.generateQrCodeUrl(this.secretKey, accountName, issuer);
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Opens the specified QR Code URL in an OTP authenticator app on the device.
|
55
|
+
* The shared secret key and account name will be populated in the OTP authenticator app.
|
56
|
+
* The URL uses the otpauth:// scheme and will be opened on an app that handles this scheme,
|
57
|
+
* if it exists on the device, possibly opening the ecocystem-specific app store with a generic
|
58
|
+
* query for compatible apps if no app exists on the device.
|
59
|
+
*
|
60
|
+
* @param qrCodeUrl the URL to open in the app, from generateQrCodeUrl
|
61
|
+
*/
|
62
|
+
openInOtpApp(qrCodeUrl) {
|
63
|
+
if (isString(qrCodeUrl) && !qrCodeUrl !== '') {
|
64
|
+
return this.auth.native.openInOtpApp(this.secretKey, qrCodeUrl);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { isOther } from '@react-native-firebase/app/lib/common';
|
1
2
|
import MultiFactorResolver from './MultiFactorResolver.js';
|
2
3
|
|
3
4
|
/**
|
@@ -7,6 +8,9 @@ import MultiFactorResolver from './MultiFactorResolver.js';
|
|
7
8
|
* Returns null if no resolver object can be found on the error.
|
8
9
|
*/
|
9
10
|
export function getMultiFactorResolver(auth, error) {
|
11
|
+
if (isOther) {
|
12
|
+
return auth.native.getMultiFactorResolver(error);
|
13
|
+
}
|
10
14
|
if (
|
11
15
|
error.hasOwnProperty('userInfo') &&
|
12
16
|
error.userInfo.hasOwnProperty('resolver') &&
|
package/lib/index.d.ts
CHANGED
@@ -275,6 +275,78 @@ export namespace FirebaseAuthTypes {
|
|
275
275
|
assertion(credential: AuthCredential): MultiFactorAssertion;
|
276
276
|
}
|
277
277
|
|
278
|
+
/**
|
279
|
+
* Represents a TOTP secret that is used for enrolling a TOTP second factor.
|
280
|
+
* Contains the shared secret key and other parameters to generate time-based
|
281
|
+
* one-time passwords. Implements methods to retrieve the shared secret key,
|
282
|
+
* generate a QR code URL, and open the QR code URL in an OTP authenticator app.
|
283
|
+
*
|
284
|
+
* Differs from standard firebase JS implementation in three ways:
|
285
|
+
* 1- there is no visibility into ony properties other than the secretKey
|
286
|
+
* 2- there is an added `openInOtpApp` method supported by native SDKs
|
287
|
+
* 3- the return value of generateQrCodeUrl is a Promise because react-native bridge is async
|
288
|
+
* @public
|
289
|
+
*/
|
290
|
+
export declare class TotpSecret {
|
291
|
+
/** used internally to support non-default auth instances */
|
292
|
+
private readonly auth;
|
293
|
+
/**
|
294
|
+
* Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs.
|
295
|
+
*/
|
296
|
+
readonly secretKey: string;
|
297
|
+
|
298
|
+
private constructor();
|
299
|
+
|
300
|
+
/**
|
301
|
+
* Returns a QR code URL as described in
|
302
|
+
* https://github.com/google/google-authenticator/wiki/Key-Uri-Format
|
303
|
+
* This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator.
|
304
|
+
* If the optional parameters are unspecified, an accountName of userEmail and issuer of firebaseAppName are used.
|
305
|
+
*
|
306
|
+
* @param accountName the name of the account/app along with a user identifier.
|
307
|
+
* @param issuer issuer of the TOTP (likely the app name).
|
308
|
+
* @returns A Promise that resolves to a QR code URL string.
|
309
|
+
*/
|
310
|
+
async generateQrCodeUrl(accountName?: string, issuer?: string): Promise<string>;
|
311
|
+
|
312
|
+
/**
|
313
|
+
* Opens the specified QR Code URL in an OTP authenticator app on the device.
|
314
|
+
* The shared secret key and account name will be populated in the OTP authenticator app.
|
315
|
+
* The URL uses the otpauth:// scheme and will be opened on an app that handles this scheme,
|
316
|
+
* if it exists on the device, possibly opening the ecocystem-specific app store with a generic
|
317
|
+
* query for compatible apps if no app exists on the device.
|
318
|
+
*
|
319
|
+
* @param qrCodeUrl the URL to open in the app, from generateQrCodeUrl
|
320
|
+
*/
|
321
|
+
openInOtpApp(qrCodeUrl: string): string;
|
322
|
+
}
|
323
|
+
|
324
|
+
export interface TotpMultiFactorGenerator {
|
325
|
+
FACTOR_ID: FactorId.TOTP;
|
326
|
+
|
327
|
+
assertionForSignIn(uid: string, totpSecret: string): MultiFactorAssertion;
|
328
|
+
|
329
|
+
assertionForEnrollment(secret: TotpSecret, code: string): MultiFactorAssertion;
|
330
|
+
|
331
|
+
/**
|
332
|
+
* @param auth - The Auth instance. Only used for native platforms, should be ignored on web.
|
333
|
+
*/
|
334
|
+
generateSecret(
|
335
|
+
session: FirebaseAuthTypes.MultiFactorSession,
|
336
|
+
auth: FirebaseAuthTypes.Auth,
|
337
|
+
): Promise<TotpSecret>;
|
338
|
+
}
|
339
|
+
|
340
|
+
export declare interface MultiFactorError extends AuthError {
|
341
|
+
/** Details about the MultiFactorError. */
|
342
|
+
readonly customData: AuthError['customData'] & {
|
343
|
+
/**
|
344
|
+
* The type of operation (sign-in, linking, or re-authentication) that raised the error.
|
345
|
+
*/
|
346
|
+
readonly operationType: (typeof OperationType)[keyof typeof OperationType];
|
347
|
+
};
|
348
|
+
}
|
349
|
+
|
278
350
|
/**
|
279
351
|
* firebase.auth.X
|
280
352
|
*/
|
@@ -476,6 +548,7 @@ export namespace FirebaseAuthTypes {
|
|
476
548
|
*/
|
477
549
|
export enum FactorId {
|
478
550
|
PHONE = 'phone',
|
551
|
+
TOTP = 'totp',
|
479
552
|
}
|
480
553
|
|
481
554
|
/**
|
@@ -596,6 +669,12 @@ export namespace FirebaseAuthTypes {
|
|
596
669
|
* The method will ensure the user state is reloaded after successfully enrolling a factor.
|
597
670
|
*/
|
598
671
|
enroll(assertion: MultiFactorAssertion, displayName?: string): Promise<void>;
|
672
|
+
|
673
|
+
/**
|
674
|
+
* Unenroll a previously enrolled multi-factor authentication factor.
|
675
|
+
* @param option The multi-factor option to unenroll.
|
676
|
+
*/
|
677
|
+
unenroll(option: MultiFactorInfo | string): Promise<void>;
|
599
678
|
}
|
600
679
|
|
601
680
|
/**
|
package/lib/index.js
CHANGED
@@ -34,6 +34,7 @@ import {
|
|
34
34
|
import ConfirmationResult from './ConfirmationResult';
|
35
35
|
import PhoneAuthListener from './PhoneAuthListener';
|
36
36
|
import PhoneMultiFactorGenerator from './PhoneMultiFactorGenerator';
|
37
|
+
import TotpMultiFactorGenerator from './TotpMultiFactorGenerator';
|
37
38
|
import Settings from './Settings';
|
38
39
|
import User from './User';
|
39
40
|
import { getMultiFactorResolver } from './getMultiFactorResolver';
|
@@ -66,6 +67,7 @@ export {
|
|
66
67
|
TwitterAuthProvider,
|
67
68
|
FacebookAuthProvider,
|
68
69
|
PhoneMultiFactorGenerator,
|
70
|
+
TotpMultiFactorGenerator,
|
69
71
|
OAuthProvider,
|
70
72
|
OIDCAuthProvider,
|
71
73
|
PhoneAuthState,
|
@@ -80,6 +82,7 @@ const statics = {
|
|
80
82
|
TwitterAuthProvider,
|
81
83
|
FacebookAuthProvider,
|
82
84
|
PhoneMultiFactorGenerator,
|
85
|
+
TotpMultiFactorGenerator,
|
83
86
|
OAuthProvider,
|
84
87
|
OIDCAuthProvider,
|
85
88
|
PhoneAuthState,
|
@@ -324,6 +327,12 @@ class FirebaseAuthModule extends FirebaseModule {
|
|
324
327
|
});
|
325
328
|
}
|
326
329
|
|
330
|
+
resolveTotpSignIn(session, uid, totpSecret) {
|
331
|
+
return this.native.resolveTotpSignIn(session, uid, totpSecret).then(userCredential => {
|
332
|
+
return this._setUserCredential(userCredential);
|
333
|
+
});
|
334
|
+
}
|
335
|
+
|
327
336
|
createUserWithEmailAndPassword(email, password) {
|
328
337
|
return this.native
|
329
338
|
.createUserWithEmailAndPassword(email, password)
|
package/lib/multiFactor.js
CHANGED
@@ -26,14 +26,25 @@ export class MultiFactorUser {
|
|
26
26
|
* profile, which is necessary to see the multi-factor changes.
|
27
27
|
*/
|
28
28
|
async enroll(multiFactorAssertion, displayName) {
|
29
|
-
const { token, secret } = multiFactorAssertion;
|
30
|
-
|
29
|
+
const { token, secret, totpSecret, verificationCode } = multiFactorAssertion;
|
30
|
+
if (token && secret) {
|
31
|
+
await this._auth.native.finalizeMultiFactorEnrollment(token, secret, displayName);
|
32
|
+
} else if (totpSecret && verificationCode) {
|
33
|
+
await this._auth.native.finalizeTotpEnrollment(totpSecret, verificationCode, displayName);
|
34
|
+
} else {
|
35
|
+
throw new Error('Invalid multi-factor assertion provided for enrollment.');
|
36
|
+
}
|
31
37
|
|
32
38
|
// We need to reload the user otherwise the changes are not visible
|
39
|
+
// TODO reload not working on Other platform
|
33
40
|
return reload(this._auth.currentUser);
|
34
41
|
}
|
35
42
|
|
36
|
-
unenroll() {
|
37
|
-
|
43
|
+
async unenroll(enrollmentId) {
|
44
|
+
await this._auth.native.unenrollMultiFactor(enrollmentId);
|
45
|
+
|
46
|
+
if (this._auth.currentUser) {
|
47
|
+
return reload(this._auth.currentUser);
|
48
|
+
}
|
38
49
|
}
|
39
50
|
}
|
package/lib/version.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
// Generated by genversion.
|
2
|
-
module.exports = '23.1
|
2
|
+
module.exports = '23.2.1';
|
@@ -8,6 +8,8 @@ import {
|
|
8
8
|
sendSignInLinkToEmail,
|
9
9
|
getAdditionalUserInfo,
|
10
10
|
multiFactor,
|
11
|
+
getMultiFactorResolver,
|
12
|
+
TotpMultiFactorGenerator,
|
11
13
|
createUserWithEmailAndPassword,
|
12
14
|
signInWithEmailAndPassword,
|
13
15
|
isSignInWithEmailLink,
|
@@ -70,6 +72,15 @@ function rejectPromiseWithCodeAndMessage(code, message) {
|
|
70
72
|
return rejectPromise(getWebError({ code: `auth/${code}`, message }));
|
71
73
|
}
|
72
74
|
|
75
|
+
function rejectWithCodeAndMessage(code, message) {
|
76
|
+
return Promise.reject(
|
77
|
+
getWebError({
|
78
|
+
code,
|
79
|
+
message,
|
80
|
+
}),
|
81
|
+
);
|
82
|
+
}
|
83
|
+
|
73
84
|
/**
|
74
85
|
* Returns a structured error object.
|
75
86
|
* @param {error} error The error object.
|
@@ -102,7 +113,9 @@ function userToObject(user) {
|
|
102
113
|
tenantId: user.tenantId !== null && user.tenantId !== '' ? user.tenantId : null,
|
103
114
|
providerData: user.providerData.map(userInfoToObject),
|
104
115
|
metadata: userMetadataToObject(user.metadata),
|
105
|
-
multiFactor:
|
116
|
+
multiFactor: {
|
117
|
+
enrolledFactors: multiFactor(user).enrolledFactors.map(multiFactorInfoToObject),
|
118
|
+
},
|
106
119
|
};
|
107
120
|
}
|
108
121
|
|
@@ -222,6 +235,7 @@ const instances = {};
|
|
222
235
|
const authStateListeners = {};
|
223
236
|
const idTokenListeners = {};
|
224
237
|
const sessionMap = new Map();
|
238
|
+
const totpSecretMap = new Map();
|
225
239
|
let sessionId = 0;
|
226
240
|
|
227
241
|
// Returns a cached Firestore instance.
|
@@ -441,11 +455,28 @@ export default {
|
|
441
455
|
* @returns {Promise<object>} - The result of the sign in.
|
442
456
|
*/
|
443
457
|
async signInWithEmailAndPassword(appName, email, password) {
|
444
|
-
|
445
|
-
|
446
|
-
|
458
|
+
// The default guard / getWebError process doesn't work well here,
|
459
|
+
// since it creates a new error object that is then passed through
|
460
|
+
// a native module proxy and gets processed again.
|
461
|
+
// We need lots of information from the error so that MFA will work
|
462
|
+
// later if needed. So we handle the error custom here.
|
463
|
+
// return guard(async () => {
|
464
|
+
try {
|
465
|
+
const credential = await signInWithEmailAndPassword(
|
466
|
+
getCachedAuthInstance(appName),
|
467
|
+
email,
|
468
|
+
password,
|
469
|
+
);
|
447
470
|
return authResultToObject(credential);
|
448
|
-
})
|
471
|
+
} catch (e) {
|
472
|
+
e.userInfo = {
|
473
|
+
code: e.code.split('/')[1],
|
474
|
+
message: e.message,
|
475
|
+
customData: e.customData,
|
476
|
+
};
|
477
|
+
throw e;
|
478
|
+
}
|
479
|
+
// });
|
449
480
|
},
|
450
481
|
|
451
482
|
/**
|
@@ -991,6 +1022,104 @@ export default {
|
|
991
1022
|
});
|
992
1023
|
},
|
993
1024
|
|
1025
|
+
/**
|
1026
|
+
* Get a MultiFactorResolver from the underlying SDK
|
1027
|
+
* @param {*} _appName the name of the app to get the auth instance for
|
1028
|
+
* @param {*} uid the uid of the TOTP MFA attempt
|
1029
|
+
* @param {*} code the code from the user TOTP app
|
1030
|
+
* @return TotpMultiFactorAssertion to use for resolving
|
1031
|
+
*/
|
1032
|
+
assertionForSignIn(_appName, uid, code) {
|
1033
|
+
return TotpMultiFactorGenerator.assertionForSignIn(uid, code);
|
1034
|
+
},
|
1035
|
+
|
1036
|
+
/**
|
1037
|
+
* Get a MultiFactorResolver from the underlying SDK
|
1038
|
+
* @param {*} appName the name of the app to get the auth instance for
|
1039
|
+
* @param {*} error the MFA error returned from initial factor login attempt
|
1040
|
+
* @return MultiFactorResolver to use for verifying the second factor
|
1041
|
+
*/
|
1042
|
+
getMultiFactorResolver(appName, error) {
|
1043
|
+
return getMultiFactorResolver(getCachedAuthInstance(appName), error);
|
1044
|
+
},
|
1045
|
+
|
1046
|
+
/**
|
1047
|
+
* generate a TOTP secret
|
1048
|
+
* @param {*} _appName - The name of the app to get the auth instance for.
|
1049
|
+
* @param {*} session - The MultiFactorSession to associate with the secret
|
1050
|
+
* @returns object with secretKey to associate with TotpSecret
|
1051
|
+
*/
|
1052
|
+
async generateTotpSecret(_appName, session) {
|
1053
|
+
return guard(async () => {
|
1054
|
+
const totpSecret = await TotpMultiFactorGenerator.generateSecret(sessionMap.get(session));
|
1055
|
+
totpSecretMap.set(totpSecret.secretKey, totpSecret);
|
1056
|
+
return { secretKey: totpSecret.secretKey };
|
1057
|
+
});
|
1058
|
+
},
|
1059
|
+
|
1060
|
+
/**
|
1061
|
+
* unenroll from TOTP
|
1062
|
+
* @param {*} appName - The name of the app to get the auth instance for.
|
1063
|
+
* @param {*} enrollmentId - The ID to associate with the enrollment
|
1064
|
+
* @returns
|
1065
|
+
*/
|
1066
|
+
async unenrollMultiFactor(appName, enrollmentId) {
|
1067
|
+
return guard(async () => {
|
1068
|
+
const auth = getCachedAuthInstance(appName);
|
1069
|
+
if (auth.currentUser === null) {
|
1070
|
+
return promiseNoUser(true);
|
1071
|
+
}
|
1072
|
+
await multiFactor(auth.currentUser).unenroll(enrollmentId);
|
1073
|
+
});
|
1074
|
+
},
|
1075
|
+
|
1076
|
+
/**
|
1077
|
+
* finalize a TOTP enrollment
|
1078
|
+
* @param {*} appName - The name of the app to get the auth instance for.
|
1079
|
+
* @param {*} secretKey - The secretKey to associate native TotpSecret
|
1080
|
+
* @param {*} verificationCode - The TOTP to verify
|
1081
|
+
* @param {*} displayName - The name to associate as a hint
|
1082
|
+
* @returns
|
1083
|
+
*/
|
1084
|
+
async finalizeTotpEnrollment(appName, secretKey, verificationCode, displayName) {
|
1085
|
+
return guard(async () => {
|
1086
|
+
const auth = getCachedAuthInstance(appName);
|
1087
|
+
if (auth.currentUser === null) {
|
1088
|
+
return promiseNoUser(true);
|
1089
|
+
}
|
1090
|
+
const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
|
1091
|
+
totpSecretMap.get(secretKey),
|
1092
|
+
verificationCode,
|
1093
|
+
);
|
1094
|
+
await multiFactor(auth.currentUser).enroll(multiFactorAssertion, displayName);
|
1095
|
+
});
|
1096
|
+
},
|
1097
|
+
|
1098
|
+
/**
|
1099
|
+
* generate a TOTP QR Code URL
|
1100
|
+
* @param {*} _appName - The name of the app to get the auth instance for.
|
1101
|
+
* @param {*} secretKey - The secretKey to associate with the TotpSecret
|
1102
|
+
* @param {*} accountName - The account name to use in auth app
|
1103
|
+
* @param {*} issuer - The issuer to use in auth app
|
1104
|
+
* @returns QR Code URL
|
1105
|
+
*/
|
1106
|
+
generateQrCodeUrl(_appName, secretKey, accountName, issuer) {
|
1107
|
+
return totpSecretMap.get(secretKey).generateQrCodeUrl(accountName, issuer);
|
1108
|
+
},
|
1109
|
+
|
1110
|
+
/**
|
1111
|
+
* open a QR Code URL in an app directly
|
1112
|
+
* @param {*} appName - The name of the app to get the auth instance for.
|
1113
|
+
* @param {*} qrCodeUrl the URL to open in the app, from generateQrCodeUrl
|
1114
|
+
* @throws Error not supported in this environment
|
1115
|
+
*/
|
1116
|
+
openInOtpApp() {
|
1117
|
+
return rejectWithCodeAndMessage(
|
1118
|
+
'unsupported',
|
1119
|
+
'This operation is not supported in this environment.',
|
1120
|
+
);
|
1121
|
+
},
|
1122
|
+
|
994
1123
|
/* ----------------------
|
995
1124
|
* other methods
|
996
1125
|
* ---------------------- */
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@react-native-firebase/auth",
|
3
|
-
"version": "23.1
|
3
|
+
"version": "23.2.1",
|
4
4
|
"author": "Invertase <oss@invertase.io> (http://invertase.io)",
|
5
5
|
"description": "React Native Firebase - The authentication module provides an easy-to-use API to integrate an authentication workflow into new and existing applications. React Native Firebase provides access to all Firebase authentication methods and identity providers.",
|
6
6
|
"main": "lib/index.js",
|
@@ -27,7 +27,7 @@
|
|
27
27
|
"plist": "^3.1.0"
|
28
28
|
},
|
29
29
|
"peerDependencies": {
|
30
|
-
"@react-native-firebase/app": "23.1
|
30
|
+
"@react-native-firebase/app": "23.2.1",
|
31
31
|
"expo": ">=47.0.0"
|
32
32
|
},
|
33
33
|
"devDependencies": {
|
@@ -43,5 +43,5 @@
|
|
43
43
|
"access": "public",
|
44
44
|
"provenance": true
|
45
45
|
},
|
46
|
-
"gitHead": "
|
46
|
+
"gitHead": "79455d150fd162c23a1fd57af5d1a497303a5407"
|
47
47
|
}
|