@react-native-firebase/auth 18.6.2 → 18.7.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 CHANGED
@@ -3,6 +3,16 @@
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
+ ## [18.7.1](https://github.com/invertase/react-native-firebase/compare/v18.7.0...v18.7.1) (2023-11-29)
7
+
8
+ **Note:** Version bump only for package @react-native-firebase/auth
9
+
10
+ ## [18.7.0](https://github.com/invertase/react-native-firebase/compare/v18.6.2...v18.7.0) (2023-11-28)
11
+
12
+ ### Features
13
+
14
+ - **auth, oauth:** support native oauth providers ([#7443](https://github.com/invertase/react-native-firebase/issues/7443)) ([8461691](https://github.com/invertase/react-native-firebase/commit/8461691914386e3711bc52fa4198f7bb7b62baff))
15
+
6
16
  ## [18.6.2](https://github.com/invertase/react-native-firebase/compare/v18.6.1...v18.6.2) (2023-11-23)
7
17
 
8
18
  ### Bug Fixes
@@ -26,10 +26,13 @@ import com.facebook.react.bridge.Arguments;
26
26
  import com.facebook.react.bridge.Promise;
27
27
  import com.facebook.react.bridge.ReactApplicationContext;
28
28
  import com.facebook.react.bridge.ReactMethod;
29
+ import com.facebook.react.bridge.ReadableArray;
29
30
  import com.facebook.react.bridge.ReadableMap;
31
+ import com.facebook.react.bridge.ReadableMapKeySetIterator;
30
32
  import com.facebook.react.bridge.WritableArray;
31
33
  import com.facebook.react.bridge.WritableMap;
32
34
  import com.google.android.gms.tasks.OnCompleteListener;
35
+ import com.google.android.gms.tasks.Task;
33
36
  import com.google.firebase.FirebaseApp;
34
37
  import com.google.firebase.FirebaseException;
35
38
  import com.google.firebase.FirebaseNetworkException;
@@ -877,6 +880,72 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
877
880
  }
878
881
  }
879
882
 
883
+ @ReactMethod
884
+ private void signInWithProvider(String appName, ReadableMap provider, final Promise promise) {
885
+ FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
886
+ FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
887
+
888
+ if (provider.getString("providerId") == null) {
889
+ rejectPromiseWithCodeAndMessage(
890
+ promise,
891
+ "invalid-credential",
892
+ "The supplied auth credential is malformed, has expired or is not currently supported.");
893
+ return;
894
+ }
895
+
896
+ OAuthProvider.Builder builder = OAuthProvider.newBuilder(provider.getString("providerId"));
897
+ // Add scopes if present
898
+ if (provider.hasKey("scopes")) {
899
+ ReadableArray scopes = provider.getArray("scopes");
900
+ if (scopes != null) {
901
+ List<String> scopeList = new ArrayList<>();
902
+ for (int i = 0; i < scopes.size(); i++) {
903
+ String scope = scopes.getString(i);
904
+ scopeList.add(scope);
905
+ }
906
+ builder.setScopes(scopeList);
907
+ }
908
+ }
909
+ // Add custom parameters if present
910
+ if (provider.hasKey("customParameters")) {
911
+ ReadableMap customParameters = provider.getMap("customParameters");
912
+ if (customParameters != null) {
913
+ ReadableMapKeySetIterator iterator = customParameters.keySetIterator();
914
+ while (iterator.hasNextKey()) {
915
+ String key = iterator.nextKey();
916
+ builder.addCustomParameter(key, customParameters.getString(key));
917
+ }
918
+ }
919
+ }
920
+ Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
921
+ if (pendingResultTask != null) {
922
+ pendingResultTask
923
+ .addOnSuccessListener(
924
+ authResult -> {
925
+ Log.d(TAG, "signInWithProvider:success");
926
+ promiseWithAuthResult(authResult, promise);
927
+ })
928
+ .addOnFailureListener(
929
+ e -> {
930
+ Log.d(TAG, "signInWithProvider:failure", e);
931
+ promiseRejectAuthException(promise, e);
932
+ });
933
+ } else {
934
+ firebaseAuth
935
+ .startActivityForSignInWithProvider(getCurrentActivity(), builder.build())
936
+ .addOnSuccessListener(
937
+ authResult -> {
938
+ Log.d(TAG, "signInWithProvider:success");
939
+ promiseWithAuthResult(authResult, promise);
940
+ })
941
+ .addOnFailureListener(
942
+ e -> {
943
+ Log.d(TAG, "signInWithProvider:failure", e);
944
+ promiseRejectAuthException(promise, e);
945
+ });
946
+ }
947
+ }
948
+
880
949
  /**
881
950
  * signInWithPhoneNumber
882
951
  *
@@ -1527,6 +1596,85 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
1527
1596
  }
1528
1597
  }
1529
1598
 
1599
+ /**
1600
+ * linkWithProvider
1601
+ *
1602
+ * @param provider
1603
+ * @param promise
1604
+ */
1605
+ @ReactMethod
1606
+ private void linkWithProvider(String appName, ReadableMap provider, final Promise promise) {
1607
+ FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
1608
+ FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
1609
+
1610
+ if (provider.getString("providerId") == null) {
1611
+ rejectPromiseWithCodeAndMessage(
1612
+ promise,
1613
+ "invalid-credential",
1614
+ "The supplied auth credential is malformed, has expired or is not currently supported.");
1615
+ return;
1616
+ }
1617
+
1618
+ FirebaseUser user = firebaseAuth.getCurrentUser();
1619
+ Log.d(TAG, "linkWithProvider");
1620
+
1621
+ if (user == null) {
1622
+ promiseNoUser(promise, true);
1623
+ return;
1624
+ }
1625
+
1626
+ OAuthProvider.Builder builder = OAuthProvider.newBuilder(provider.getString("providerId"));
1627
+ // Add scopes if present
1628
+ if (provider.hasKey("scopes")) {
1629
+ ReadableArray scopes = provider.getArray("scopes");
1630
+ if (scopes != null) {
1631
+ List<String> scopeList = new ArrayList<>();
1632
+ for (int i = 0; i < scopes.size(); i++) {
1633
+ String scope = scopes.getString(i);
1634
+ scopeList.add(scope);
1635
+ }
1636
+ builder.setScopes(scopeList);
1637
+ }
1638
+ }
1639
+ // Add custom parameters if present
1640
+ if (provider.hasKey("customParameters")) {
1641
+ ReadableMap customParameters = provider.getMap("customParameters");
1642
+ if (customParameters != null) {
1643
+ ReadableMapKeySetIterator iterator = customParameters.keySetIterator();
1644
+ while (iterator.hasNextKey()) {
1645
+ String key = iterator.nextKey();
1646
+ builder.addCustomParameter(key, customParameters.getString(key));
1647
+ }
1648
+ }
1649
+ }
1650
+ Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
1651
+ if (pendingResultTask != null) {
1652
+ pendingResultTask
1653
+ .addOnSuccessListener(
1654
+ authResult -> {
1655
+ Log.d(TAG, "linkWithProvider:success");
1656
+ promiseWithAuthResult(authResult, promise);
1657
+ })
1658
+ .addOnFailureListener(
1659
+ e -> {
1660
+ Log.d(TAG, "linkWithProvider:failure", e);
1661
+ promiseRejectAuthException(promise, e);
1662
+ });
1663
+ } else {
1664
+ user.startActivityForLinkWithProvider(getCurrentActivity(), builder.build())
1665
+ .addOnSuccessListener(
1666
+ authResult -> {
1667
+ Log.d(TAG, "linkWithProvider:success");
1668
+ promiseWithAuthResult(authResult, promise);
1669
+ })
1670
+ .addOnFailureListener(
1671
+ e -> {
1672
+ Log.d(TAG, "linkWithProvider:failure", e);
1673
+ promiseRejectAuthException(promise, e);
1674
+ });
1675
+ }
1676
+ }
1677
+
1530
1678
  @ReactMethod
1531
1679
  public void unlink(final String appName, final String providerId, final Promise promise) {
1532
1680
  FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
@@ -1590,6 +1738,86 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
1590
1738
  }
1591
1739
  }
1592
1740
 
1741
+ /**
1742
+ * reauthenticateWithProvider
1743
+ *
1744
+ * @param provider
1745
+ * @param promise
1746
+ */
1747
+ @ReactMethod
1748
+ private void reauthenticateWithProvider(
1749
+ String appName, ReadableMap provider, final Promise promise) {
1750
+ FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
1751
+ FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
1752
+
1753
+ if (provider.getString("providerId") == null) {
1754
+ rejectPromiseWithCodeAndMessage(
1755
+ promise,
1756
+ "invalid-credential",
1757
+ "The supplied auth credential is malformed, has expired or is not currently supported.");
1758
+ return;
1759
+ }
1760
+
1761
+ FirebaseUser user = firebaseAuth.getCurrentUser();
1762
+ Log.d(TAG, "reauthenticateWithProvider");
1763
+
1764
+ if (user == null) {
1765
+ promiseNoUser(promise, true);
1766
+ return;
1767
+ }
1768
+
1769
+ OAuthProvider.Builder builder = OAuthProvider.newBuilder(provider.getString("providerId"));
1770
+ // Add scopes if present
1771
+ if (provider.hasKey("scopes")) {
1772
+ ReadableArray scopes = provider.getArray("scopes");
1773
+ if (scopes != null) {
1774
+ List<String> scopeList = new ArrayList<>();
1775
+ for (int i = 0; i < scopes.size(); i++) {
1776
+ String scope = scopes.getString(i);
1777
+ scopeList.add(scope);
1778
+ }
1779
+ builder.setScopes(scopeList);
1780
+ }
1781
+ }
1782
+ // Add custom parameters if present
1783
+ if (provider.hasKey("customParameters")) {
1784
+ ReadableMap customParameters = provider.getMap("customParameters");
1785
+ if (customParameters != null) {
1786
+ ReadableMapKeySetIterator iterator = customParameters.keySetIterator();
1787
+ while (iterator.hasNextKey()) {
1788
+ String key = iterator.nextKey();
1789
+ builder.addCustomParameter(key, customParameters.getString(key));
1790
+ }
1791
+ }
1792
+ }
1793
+ Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
1794
+ if (pendingResultTask != null) {
1795
+ pendingResultTask
1796
+ .addOnSuccessListener(
1797
+ authResult -> {
1798
+ Log.d(TAG, "reauthenticateWithProvider:success");
1799
+ promiseWithAuthResult(authResult, promise);
1800
+ })
1801
+ .addOnFailureListener(
1802
+ e -> {
1803
+ Log.d(TAG, "reauthenticateWithProvider:failure", e);
1804
+ promiseRejectAuthException(promise, e);
1805
+ });
1806
+ } else {
1807
+ user.startActivityForReauthenticateWithProvider(getCurrentActivity(), builder.build())
1808
+ .addOnSuccessListener(
1809
+ authResult -> {
1810
+ Log.d(TAG, "reauthenticateWithProvider:success");
1811
+ promiseWithAuthResult(authResult, promise);
1812
+ })
1813
+ .addOnFailureListener(
1814
+ e -> {
1815
+ Log.d(TAG, "reauthenticateWithProvider:failure", e);
1816
+ promiseRejectAuthException(promise, e);
1817
+ });
1818
+ }
1819
+ }
1820
+
1593
1821
  /** Returns an instance of AuthCredential for the specified provider */
1594
1822
  private AuthCredential getCredentialForProvider(
1595
1823
  String provider, String authToken, String authSecret) {
@@ -571,6 +571,63 @@ RCT_EXPORT_METHOD(signInWithCredential
571
571
  }];
572
572
  }
573
573
 
574
+ RCT_EXPORT_METHOD(signInWithProvider
575
+ : (FIRApp *)firebaseApp
576
+ : (NSDictionary *)provider
577
+ : (RCTPromiseResolveBlock)resolve
578
+ : (RCTPromiseRejectBlock)reject) {
579
+ NSString *providerId = provider[@"providerId"];
580
+ if (providerId == nil) {
581
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
582
+ userInfo:(NSMutableDictionary *)@{
583
+ @"code" : @"invalid-credential",
584
+ @"message" : @"The supplied auth credential is malformed, "
585
+ @"has expired or is not currently supported.",
586
+ }];
587
+ }
588
+
589
+ __block FIROAuthProvider *builder = [FIROAuthProvider providerWithProviderID:providerId];
590
+ // Add scopes if present
591
+ if (provider[@"scopes"]) {
592
+ [builder setScopes:provider[@"scopes"]];
593
+ }
594
+ // Add custom parameters if present
595
+ if (provider[@"customParameters"]) {
596
+ [builder setCustomParameters:provider[@"customParameters"]];
597
+ }
598
+
599
+ [builder getCredentialWithUIDelegate:nil
600
+ completion:^(FIRAuthCredential *_Nullable credential,
601
+ NSError *_Nullable error) {
602
+ if (error) {
603
+ [self promiseRejectAuthException:reject error:error];
604
+ return;
605
+ }
606
+ if (credential) {
607
+ [[FIRAuth auth]
608
+ signInWithCredential:credential
609
+ completion:^(FIRAuthDataResult *_Nullable authResult,
610
+ NSError *_Nullable error) {
611
+ if (error) {
612
+ [self promiseRejectAuthException:reject
613
+ error:error];
614
+ return;
615
+ }
616
+
617
+ // NOTE: This variable has NO PURPOSE AT ALL, it is
618
+ // only to keep a strong reference to the builder
619
+ // variable so it is not deallocated prematurely by
620
+ // ARC.
621
+ NSString *providerID = builder.providerID;
622
+
623
+ [self promiseWithAuthResult:resolve
624
+ rejecter:reject
625
+ authResult:authResult];
626
+ }];
627
+ }
628
+ }];
629
+ }
630
+
574
631
  RCT_EXPORT_METHOD(confirmPasswordReset
575
632
  : (FIRApp *)firebaseApp
576
633
  : (NSString *)code
@@ -983,6 +1040,68 @@ RCT_EXPORT_METHOD(linkWithCredential
983
1040
  }
984
1041
  }
985
1042
 
1043
+ RCT_EXPORT_METHOD(linkWithProvider
1044
+ : (FIRApp *)firebaseApp
1045
+ : (NSDictionary *)provider
1046
+ : (RCTPromiseResolveBlock)resolve
1047
+ : (RCTPromiseRejectBlock)reject) {
1048
+ NSString *providerId = provider[@"providerId"];
1049
+ if (providerId == nil) {
1050
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1051
+ userInfo:(NSMutableDictionary *)@{
1052
+ @"code" : @"invalid-credential",
1053
+ @"message" : @"The supplied auth credential is malformed, "
1054
+ @"has expired or is not currently supported.",
1055
+ }];
1056
+ }
1057
+
1058
+ __block FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1059
+ if (user == nil) {
1060
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1061
+ return;
1062
+ }
1063
+
1064
+ __block FIROAuthProvider *builder = [FIROAuthProvider providerWithProviderID:providerId];
1065
+ // Add scopes if present
1066
+ if (provider[@"scopes"]) {
1067
+ [builder setScopes:provider[@"scopes"]];
1068
+ }
1069
+ // Add custom parameters if present
1070
+ if (provider[@"parameters"]) {
1071
+ [builder setCustomParameters:provider[@"parameters"]];
1072
+ }
1073
+
1074
+ [builder getCredentialWithUIDelegate:nil
1075
+ completion:^(FIRAuthCredential *_Nullable credential,
1076
+ NSError *_Nullable error) {
1077
+ if (error) {
1078
+ [self promiseRejectAuthException:reject error:error];
1079
+ return;
1080
+ }
1081
+ if (credential) {
1082
+ [user linkWithCredential:credential
1083
+ completion:^(FIRAuthDataResult *_Nullable authResult,
1084
+ NSError *_Nullable error) {
1085
+ if (error) {
1086
+ [self promiseRejectAuthException:reject
1087
+ error:error];
1088
+ return;
1089
+ }
1090
+
1091
+ // NOTE: This variable has NO PURPOSE AT ALL, it is
1092
+ // only to keep a strong reference to the builder
1093
+ // variable so it is not deallocated prematurely by
1094
+ // ARC.
1095
+ NSString *providerID = builder.providerID;
1096
+
1097
+ [self promiseWithAuthResult:resolve
1098
+ rejecter:reject
1099
+ authResult:authResult];
1100
+ }];
1101
+ }
1102
+ }];
1103
+ }
1104
+
986
1105
  RCT_EXPORT_METHOD(unlink
987
1106
  : (FIRApp *)firebaseApp
988
1107
  : (NSString *)providerId
@@ -1043,6 +1162,69 @@ RCT_EXPORT_METHOD(reauthenticateWithCredential
1043
1162
  }
1044
1163
  }
1045
1164
 
1165
+ RCT_EXPORT_METHOD(reauthenticateWithProvider
1166
+ : (FIRApp *)firebaseApp
1167
+ : (NSDictionary *)provider
1168
+ : (RCTPromiseResolveBlock)resolve
1169
+ : (RCTPromiseRejectBlock)reject) {
1170
+ NSString *providerId = provider[@"providerId"];
1171
+ if (providerId == nil) {
1172
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
1173
+ userInfo:(NSMutableDictionary *)@{
1174
+ @"code" : @"invalid-credential",
1175
+ @"message" : @"The supplied auth credential is malformed, "
1176
+ @"has expired or is not currently supported.",
1177
+ }];
1178
+ }
1179
+
1180
+ __block FIRUser *user = [FIRAuth authWithApp:firebaseApp].currentUser;
1181
+ if (user == nil) {
1182
+ [self promiseNoUser:resolve rejecter:reject isError:YES];
1183
+ return;
1184
+ }
1185
+
1186
+ __block FIROAuthProvider *builder = [FIROAuthProvider providerWithProviderID:providerId];
1187
+ // Add scopes if present
1188
+ if (provider[@"scopes"]) {
1189
+ [builder setScopes:provider[@"scopes"]];
1190
+ }
1191
+ // Add custom parameters if present
1192
+ if (provider[@"parameters"]) {
1193
+ [builder setCustomParameters:provider[@"parameters"]];
1194
+ }
1195
+
1196
+ [builder getCredentialWithUIDelegate:nil
1197
+ completion:^(FIRAuthCredential *_Nullable credential,
1198
+ NSError *_Nullable error) {
1199
+ if (error) {
1200
+ [self promiseRejectAuthException:reject error:error];
1201
+ return;
1202
+ }
1203
+ if (credential) {
1204
+ [user reauthenticateWithCredential:credential
1205
+ completion:^(
1206
+ FIRAuthDataResult *_Nullable authResult,
1207
+ NSError *_Nullable error) {
1208
+ if (error) {
1209
+ [self promiseRejectAuthException:reject
1210
+ error:error];
1211
+ return;
1212
+ }
1213
+
1214
+ // NOTE: This variable has NO PURPOSE AT
1215
+ // ALL, it is only to keep a strong
1216
+ // reference to the builder variable so it
1217
+ // is not deallocated prematurely by ARC.
1218
+ NSString *providerID = builder.providerID;
1219
+
1220
+ [self promiseWithAuthResult:resolve
1221
+ rejecter:reject
1222
+ authResult:authResult];
1223
+ }];
1224
+ }
1225
+ }];
1226
+ }
1227
+
1046
1228
  RCT_EXPORT_METHOD(fetchSignInMethodsForEmail
1047
1229
  : (FIRApp *)firebaseApp
1048
1230
  : (NSString *)email
package/lib/User.js CHANGED
@@ -96,12 +96,34 @@ export default class User {
96
96
  .then(userCredential => this._auth._setUserCredential(userCredential));
97
97
  }
98
98
 
99
+ linkWithPopup(provider) {
100
+ // call through to linkWithRedirect for shared implementation
101
+ return this.linkWithRedirect(provider);
102
+ }
103
+
104
+ linkWithRedirect(provider) {
105
+ return this._auth.native
106
+ .linkWithProvider(provider.toObject())
107
+ .then(userCredential => this._auth._setUserCredential(userCredential));
108
+ }
109
+
99
110
  reauthenticateWithCredential(credential) {
100
111
  return this._auth.native
101
112
  .reauthenticateWithCredential(credential.providerId, credential.token, credential.secret)
102
113
  .then(userCredential => this._auth._setUserCredential(userCredential));
103
114
  }
104
115
 
116
+ reauthenticateWithPopup(provider) {
117
+ // call through to reauthenticateWithRedirect for shared implementation
118
+ return this.reauthenticateWithRedirect(provider);
119
+ }
120
+
121
+ reauthenticateWithRedirect(provider) {
122
+ return this._auth.native
123
+ .reauthenticateWithProvider(provider.toObject())
124
+ .then(userCredential => this._auth._setUserCredential(userCredential));
125
+ }
126
+
105
127
  reload() {
106
128
  return this._auth.native.reload().then(user => {
107
129
  this._auth._setUser(user);
@@ -310,36 +332,12 @@ export default class User {
310
332
  );
311
333
  }
312
334
 
313
- linkWithPopup() {
314
- throw new Error(
315
- 'firebase.auth.User.linkWithPopup() is unsupported by the native Firebase SDKs.',
316
- );
317
- }
318
-
319
- linkWithRedirect() {
320
- throw new Error(
321
- 'firebase.auth.User.linkWithRedirect() is unsupported by the native Firebase SDKs.',
322
- );
323
- }
324
-
325
335
  reauthenticateWithPhoneNumber() {
326
336
  throw new Error(
327
337
  'firebase.auth.User.reauthenticateWithPhoneNumber() is unsupported by the native Firebase SDKs.',
328
338
  );
329
339
  }
330
340
 
331
- reauthenticateWithPopup() {
332
- throw new Error(
333
- 'firebase.auth.User.reauthenticateWithPopup() is unsupported by the native Firebase SDKs.',
334
- );
335
- }
336
-
337
- reauthenticateWithRedirect() {
338
- throw new Error(
339
- 'firebase.auth.User.reauthenticateWithRedirect() is unsupported by the native Firebase SDKs.',
340
- );
341
- }
342
-
343
341
  get refreshToken() {
344
342
  throw new Error('firebase.auth.User.refreshToken is unsupported by the native Firebase SDKs.');
345
343
  }
package/lib/index.d.ts CHANGED
@@ -109,6 +109,52 @@ export namespace FirebaseAuthTypes {
109
109
  credential: (token: string | null, secret?: string) => AuthCredential;
110
110
  }
111
111
 
112
+ /**
113
+ * Interface that represents an OAuth provider. Implemented by other providers.
114
+ */
115
+ export interface OAuthProvider {
116
+ /**
117
+ * The provider ID of the provider.
118
+ * @param providerId
119
+ */
120
+ // eslint-disable-next-line @typescript-eslint/no-misused-new
121
+ new (providerId: string): AuthProvider;
122
+ /**
123
+ * Creates a new `AuthCredential`.
124
+ *
125
+ * @returns {@link auth.AuthCredential}.
126
+ * @param token A provider token.
127
+ * @param secret A provider secret.
128
+ */
129
+ credential: (token: string | null, secret?: string) => AuthCredential;
130
+ /**
131
+ * Sets the OAuth custom parameters to pass in an OAuth request for sign-in
132
+ * operations.
133
+ *
134
+ * @remarks
135
+ * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`,
136
+ * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored.
137
+ *
138
+ * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request.
139
+ */
140
+ setCustomParameters: (customOAuthParameters: Record<string, string>) => AuthProvider;
141
+ /**
142
+ * Retrieve the current list of custom parameters.
143
+ * @returns The current map of OAuth custom parameters.
144
+ */
145
+ getCustomParameters: () => Record<string, string>;
146
+ /**
147
+ * Add an OAuth scope to the credential.
148
+ *
149
+ * @param scope - Provider OAuth scope to add.
150
+ */
151
+ addScope: (scope: string) => AuthProvider;
152
+ /**
153
+ * Retrieve the current list of OAuth scopes.
154
+ */
155
+ getScopes: () => string[];
156
+ }
157
+
112
158
  /**
113
159
  * Interface that represents an Open ID Connect auth provider. Implemented by other providers.
114
160
  */
@@ -315,7 +361,7 @@ export namespace FirebaseAuthTypes {
315
361
  * firebase.auth.OAuthProvider;
316
362
  * ```
317
363
  */
318
- OAuthProvider: AuthProvider;
364
+ OAuthProvider: OAuthProvider;
319
365
  /**
320
366
  * Custom Open ID connect auth provider implementation.
321
367
  *
@@ -1212,6 +1258,58 @@ export namespace FirebaseAuthTypes {
1212
1258
  */
1213
1259
  linkWithCredential(credential: AuthCredential): Promise<UserCredential>;
1214
1260
 
1261
+ /**
1262
+ * Link the user with a federated 3rd party credential provider (Microsoft, Yahoo).
1263
+ * The APIs here are the web-compatible linkWithPopup and linkWithRedirect but both
1264
+ * share the same underlying native SDK behavior and may be used interchangably.
1265
+ *
1266
+ * #### Example
1267
+ *
1268
+ * ```js
1269
+ * const provider = new firebase.auth.OAuthProvider('microsoft.com');
1270
+ * const userCredential = await firebase.auth().currentUser.linkWithPopup(provider);
1271
+ * ```
1272
+ *
1273
+ * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user.
1274
+ * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method.
1275
+ * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User.
1276
+ * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users.
1277
+ * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider.
1278
+ * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid.
1279
+ * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password.
1280
+ * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid.
1281
+ * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid.
1282
+ * @throws on iOS {@link auth.NativeFirebaseAuthError}, on Android {@link auth.NativeFirebaseError}
1283
+ * @param provider A created {@link auth.AuthProvider}.
1284
+ */
1285
+ linkWithPopup(provider: AuthProvider): Promise<UserCredential>;
1286
+
1287
+ /**
1288
+ * Link the user with a federated 3rd party credential provider (Microsoft, Yahoo).
1289
+ * The APIs here are the web-compatible linkWithPopup and linkWithRedirect but both
1290
+ * share the same underlying native SDK behavior and may be used interchangably.
1291
+ *
1292
+ * #### Example
1293
+ *
1294
+ * ```js
1295
+ * const provider = new firebase.auth.OAuthProvider('microsoft.com');
1296
+ * const userCredential = await firebase.auth().currentUser.linkWithRedirect(provider);
1297
+ * ```
1298
+ *
1299
+ * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user.
1300
+ * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method.
1301
+ * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User.
1302
+ * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users.
1303
+ * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider.
1304
+ * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid.
1305
+ * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password.
1306
+ * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid.
1307
+ * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid.
1308
+ * @throws on iOS {@link auth.NativeFirebaseAuthError}, on Android {@link auth.NativeFirebaseError}
1309
+ * @param provider A created {@link auth.AuthProvider}.
1310
+ */
1311
+ linkWithRedirect(provider: AuthProvider): Promise<UserCredential>;
1312
+
1215
1313
  /**
1216
1314
  * Re-authenticate a user with a third-party authentication provider.
1217
1315
  *
@@ -1233,6 +1331,27 @@ export namespace FirebaseAuthTypes {
1233
1331
  */
1234
1332
  reauthenticateWithCredential(credential: AuthCredential): Promise<UserCredential>;
1235
1333
 
1334
+ /**
1335
+ * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo)
1336
+ *
1337
+ * #### Example
1338
+ *
1339
+ * ```js
1340
+ * const provider = new firebase.auth.OAuthProvider('microsoft.com');
1341
+ * const userCredential = await firebase.auth().currentUser.reauthenticateWithProvider(provider);
1342
+ * ```
1343
+ *
1344
+ * @error auth/user-mismatch Thrown if the credential given does not correspond to the user.
1345
+ * @error auth/user-not-found Thrown if the credential given does not correspond to any existing user.
1346
+ * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method.
1347
+ * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid.
1348
+ * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password.
1349
+ * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid.
1350
+ * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid.
1351
+ * @param provider A created {@link auth.AuthProvider}.
1352
+ */
1353
+ reauthenticateWithProvider(provider: AuthProvider): Promise<UserCredential>;
1354
+
1236
1355
  /**
1237
1356
  * Refreshes the current user.
1238
1357
  *
@@ -1722,6 +1841,56 @@ export namespace FirebaseAuthTypes {
1722
1841
  */
1723
1842
  signInWithCredential(credential: AuthCredential): Promise<UserCredential>;
1724
1843
 
1844
+ /**
1845
+ * Signs the user in with a specified provider. This is a web-compatible API along with signInWithRedirect.
1846
+ * They both share the same call to the underlying native SDK signInWithProvider method.
1847
+ *
1848
+ * #### Example
1849
+ *
1850
+ * ```js
1851
+ * // create a new OAuthProvider
1852
+ * const provider = firebase.auth.OAuthProvider('microsoft.com');
1853
+ * // Sign the user in with the provider
1854
+ * const userCredential = await firebase.auth().signInWithPopup(provider);
1855
+ * ```
1856
+ *
1857
+ * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential.
1858
+ * @error auth/invalid-credential Thrown if the credential is malformed or has expired.
1859
+ * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab.
1860
+ * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled.
1861
+ * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email.
1862
+ * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set.
1863
+ * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid.
1864
+ * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid.
1865
+ * @param provider An `AuthProvider` configured for your desired provider, e.g. "microsoft.com"
1866
+ */
1867
+ signInWithPopup(provider: AuthProvider): Promise<UserCredential>;
1868
+
1869
+ /**
1870
+ * Signs the user in with a specified provider. This is a web-compatible API along with signInWithPopup.
1871
+ * They both share the same call to the underlying native SDK signInWithProvider method.
1872
+ *
1873
+ * #### Example
1874
+ *
1875
+ * ```js
1876
+ * // create a new OAuthProvider
1877
+ * const provider = firebase.auth.OAuthProvider('microsoft.com');
1878
+ * // Sign the user in with the provider
1879
+ * const userCredential = await firebase.auth().signInWithRedirect(provider);
1880
+ * ```
1881
+ *
1882
+ * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential.
1883
+ * @error auth/invalid-credential Thrown if the credential is malformed or has expired.
1884
+ * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab.
1885
+ * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled.
1886
+ * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email.
1887
+ * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set.
1888
+ * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid.
1889
+ * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid.
1890
+ * @param provider An `AuthProvider` configured for your desired provider, e.g. "microsoft.com"
1891
+ */
1892
+ signInWithRedirect(provider: AuthProvider): Promise<UserCredential>;
1893
+
1725
1894
  /**
1726
1895
  * Revokes a user's Sign in with Apple token.
1727
1896
  *
@@ -1738,6 +1907,41 @@ export namespace FirebaseAuthTypes {
1738
1907
  */
1739
1908
  revokeToken(authorizationCode: string): Promise<void>;
1740
1909
 
1910
+ /**
1911
+ * Signs the user in with a federated OAuth provider supported by Firebase (Microsoft, Yahoo).
1912
+ *
1913
+ * From Firebase Docs:
1914
+ * Unlike other OAuth providers supported by Firebase such as Google, Facebook, and Twitter, where
1915
+ * sign-in can directly be achieved with OAuth access token based credentials, Firebase Auth does not
1916
+ * support the same capability for providers such as Microsoft due to the inability of the Firebase Auth
1917
+ * server to verify the audience of Microsoft OAuth access tokens.
1918
+ *
1919
+ * #### Example
1920
+ * ```js
1921
+ * // Generate an OAuth instance
1922
+ * const provider = new firebase.auth.OAuthProvider('microsoft.com');
1923
+ * // Optionally add scopes to the OAuth instance
1924
+ * provider.addScope('mail.read');
1925
+ * // Optionally add custom parameters to the OAuth instance
1926
+ * provider.setCustomParameters({
1927
+ * prompt: 'consent',
1928
+ * });
1929
+ * // Sign in using the OAuth provider
1930
+ * const userCredential = await firebase.auth().signInWithProvider(provider);
1931
+ * ```
1932
+ *
1933
+ * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential.
1934
+ * @error auth/invalid-credential Thrown if the credential is malformed or has expired.
1935
+ * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab.
1936
+ * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled.
1937
+ * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email.
1938
+ * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set.
1939
+ * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid.
1940
+ * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid.
1941
+ * @param provider A generated `AuthProvider`, for example from social auth.
1942
+ */
1943
+ signInWithProvider(provider: AuthProvider): Promise<UserCredential>;
1944
+
1741
1945
  /**
1742
1946
  * Sends a password reset email to the given email address.
1743
1947
  * Unlike the web SDK, the email will contain a password reset link rather than a code.
package/lib/index.js CHANGED
@@ -433,16 +433,16 @@ class FirebaseAuthModule extends FirebaseModule {
433
433
  throw new Error('firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.');
434
434
  }
435
435
 
436
- signInWithPopup() {
437
- throw new Error(
438
- 'firebase.auth().signInWithPopup() is unsupported by the native Firebase SDKs.',
439
- );
436
+ signInWithPopup(provider) {
437
+ return this.native
438
+ .signInWithProvider(provider.toObject())
439
+ .then(userCredential => this._setUserCredential(userCredential));
440
440
  }
441
441
 
442
- signInWithRedirect() {
443
- throw new Error(
444
- 'firebase.auth().signInWithRedirect() is unsupported by the native Firebase SDKs.',
445
- );
442
+ signInWithRedirect(provider) {
443
+ return this.native
444
+ .signInWithProvider(provider.toObject())
445
+ .then(userCredential => this._setUserCredential(userCredential));
446
446
  }
447
447
 
448
448
  // firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680
@@ -264,14 +264,16 @@ export function verifyPhoneNumber(auth, phoneNumber, autoVerifyTimeoutOrForceRes
264
264
  Authenticates a Firebase client using a popup-based OAuth authentication flow.
265
265
  */
266
266
  export async function signInWithPopup(auth, provider, resolver) {
267
- throw new Error('signInWithPopup is unsupported by the native Firebase SDKs');
267
+ const _auth = _getUnderlyingAuth(auth);
268
+ return _auth.signInWithPopup(provider, resolver);
268
269
  }
269
270
 
270
271
  /*
271
272
  Authenticates a Firebase client using a full-page redirect flow.
272
273
  */
273
274
  export async function signInWithRedirect(auth, provider, resolver) {
274
- throw new Error('signInWithRedirect is unsupported by the native Firebase SDKs');
275
+ const _auth = _getUnderlyingAuth(auth);
276
+ return _auth.signInWithRedirect(provider, resolver);
275
277
  }
276
278
 
277
279
  /*
@@ -358,14 +360,14 @@ export async function linkWithPhoneNumber(user, phoneNumber, appVerifier) {
358
360
  * Links the authenticated provider to the user account using a pop-up based OAuth flow.
359
361
  */
360
362
  export async function linkWithPopup(user, provider, resolver) {
361
- throw new Error('linkWithPopup is unsupported by the native Firebase SDKs');
363
+ return user.linkWithPopup(provider, resolver);
362
364
  }
363
365
 
364
366
  /*
365
367
  * Links the OAuthProvider to the user account using a full-page redirect flow.
366
368
  */
367
369
  export async function linkWithRedirect(user, provider, resolver) {
368
- throw new Error('linkWithRedirect is unsupported by the native Firebase SDKs');
370
+ return user.linkWithRedirect(provider, resolver);
369
371
  }
370
372
 
371
373
  /*
@@ -393,14 +395,14 @@ export async function reauthenticateWithPhoneNumber(user, phoneNumber, appVerifi
393
395
  * Reauthenticates the current user with the specified OAuthProvider using a pop-up based OAuth flow.
394
396
  */
395
397
  export async function reauthenticateWithPopup(user, provider, resolver) {
396
- throw new Error('reauthenticateWithPopup is unsupported by the native Firebase SDKs');
398
+ return user.reauthenticateWithPopup(provider, resolver);
397
399
  }
398
400
 
399
401
  /*
400
402
  * Reauthenticates the current user with the specified OAuthProvider using a full-page redirect flow.
401
403
  */
402
404
  export async function reauthenticateWithRedirect(user, provider, resolver) {
403
- throw new Error('reauthenticateWithRedirect is unsupported by the native Firebase SDKs');
405
+ return user.reauthenticateWithRedirect(provider, resolver);
404
406
  }
405
407
 
406
408
  /*
@@ -15,22 +15,56 @@
15
15
  *
16
16
  */
17
17
 
18
- const providerId = 'oauth';
19
-
20
18
  export default class OAuthProvider {
21
- constructor() {
22
- throw new Error('`new OAuthProvider()` is not supported on the native Firebase SDKs.');
23
- }
19
+ /** @internal */
20
+ #providerId = null;
21
+ /** @internal */
22
+ #customParameters = {};
23
+ /** @internal */
24
+ #scopes = [];
24
25
 
25
- static get PROVIDER_ID() {
26
- return providerId;
26
+ constructor(providerId) {
27
+ this.#providerId = providerId;
27
28
  }
28
29
 
29
30
  static credential(idToken, accessToken) {
30
31
  return {
31
32
  token: idToken,
32
33
  secret: accessToken,
33
- providerId,
34
+ providerId: 'oauth',
35
+ };
36
+ }
37
+
38
+ get PROVIDER_ID() {
39
+ return this.#providerId;
40
+ }
41
+
42
+ setCustomParameters(customOAuthParameters) {
43
+ this.#customParameters = customOAuthParameters;
44
+ return this;
45
+ }
46
+
47
+ getCustomParameters() {
48
+ return this.#customParameters;
49
+ }
50
+
51
+ addScope(scope) {
52
+ if (!this.#scopes.includes(scope)) {
53
+ this.#scopes.push(scope);
54
+ }
55
+ return this;
56
+ }
57
+
58
+ getScopes() {
59
+ return [...this.#scopes];
60
+ }
61
+
62
+ /** @internal */
63
+ toObject() {
64
+ return {
65
+ providerId: this.#providerId,
66
+ scopes: this.#scopes,
67
+ customParameters: this.#customParameters,
34
68
  };
35
69
  }
36
70
  }
package/lib/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- module.exports = '18.6.2';
2
+ module.exports = '18.7.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-firebase/auth",
3
- "version": "18.6.2",
3
+ "version": "18.7.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": "18.6.2",
30
+ "@react-native-firebase/app": "18.7.1",
31
31
  "expo": ">=47.0.0"
32
32
  },
33
33
  "devDependencies": {
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "8673f3162667f5fd9f942ccac24cecbd18a79aa3"
45
+ "gitHead": "f8b7794db23185c8a934a3e3623e996ce282c1f7"
46
46
  }