|
49 | 49 | import com.google.firebase.auth.FirebaseAuthMultiFactorException;
|
50 | 50 | import com.google.firebase.auth.FirebaseAuthProvider;
|
51 | 51 | import com.google.firebase.auth.FirebaseAuthSettings;
|
| 52 | +import com.google.firebase.auth.FirebaseAuthUserCollisionException; |
52 | 53 | import com.google.firebase.auth.FirebaseUser;
|
53 | 54 | import com.google.firebase.auth.FirebaseUserMetadata;
|
54 | 55 | import com.google.firebase.auth.GetTokenResult;
|
@@ -107,6 +108,10 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
|
107 | 108 | private final HashMap<String, MultiFactorResolver> mCachedResolvers = new HashMap<>();
|
108 | 109 | private final HashMap<String, MultiFactorSession> mMultiFactorSessions = new HashMap<>();
|
109 | 110 |
|
| 111 | + // storage for anonymous phone auth credentials, used for linkWithCredentials |
| 112 | + // https://github.com/invertase/react-native-firebase/issues/4911 |
| 113 | + private HashMap<String, AuthCredential> credentials = new HashMap<>(); |
| 114 | + |
110 | 115 | ReactNativeFirebaseAuthModule(ReactApplicationContext reactContext) {
|
111 | 116 | super(reactContext, TAG);
|
112 | 117 | }
|
@@ -914,9 +919,8 @@ private void signInWithProvider(String appName, ReadableMap provider, final Prom
|
914 | 919 | return;
|
915 | 920 | }
|
916 | 921 |
|
917 |
| - OAuthProvider.Builder builder = OAuthProvider.newBuilder( |
918 |
| - provider.getString("providerId"), |
919 |
| - firebaseAuth); |
| 922 | + OAuthProvider.Builder builder = |
| 923 | + OAuthProvider.newBuilder(provider.getString("providerId"), firebaseAuth); |
920 | 924 | // Add scopes if present
|
921 | 925 | if (provider.hasKey("scopes")) {
|
922 | 926 | ReadableArray scopes = provider.getArray("scopes");
|
@@ -1613,6 +1617,17 @@ private void linkWithCredential(
|
1613 | 1617 | promiseWithAuthResult(task.getResult(), promise);
|
1614 | 1618 | } else {
|
1615 | 1619 | Exception exception = task.getException();
|
| 1620 | + if (exception instanceof FirebaseAuthUserCollisionException collEx) { |
| 1621 | + AuthCredential updatedCredential = collEx.getUpdatedCredential(); |
| 1622 | + Log.d(TAG, "link:onComplete:collisionFailure", collEx); |
| 1623 | + // If we have a credential in the error, we can return it, otherwise fall |
| 1624 | + // through |
| 1625 | + if (updatedCredential != null) { |
| 1626 | + Log.d(TAG, "link:onComplete:collisionFailure had credential", collEx); |
| 1627 | + promiseRejectLinkAuthException(promise, collEx, updatedCredential); |
| 1628 | + return; |
| 1629 | + } |
| 1630 | + } |
1616 | 1631 | Log.e(TAG, "link:onComplete:failure", exception);
|
1617 | 1632 | promiseRejectAuthException(promise, exception);
|
1618 | 1633 | }
|
@@ -1650,9 +1665,8 @@ private void linkWithProvider(String appName, ReadableMap provider, final Promis
|
1650 | 1665 | return;
|
1651 | 1666 | }
|
1652 | 1667 |
|
1653 |
| - OAuthProvider.Builder builder = OAuthProvider.newBuilder( |
1654 |
| - provider.getString("providerId"), |
1655 |
| - firebaseAuth); |
| 1668 | + OAuthProvider.Builder builder = |
| 1669 | + OAuthProvider.newBuilder(provider.getString("providerId"), firebaseAuth); |
1656 | 1670 | // Add scopes if present
|
1657 | 1671 | if (provider.hasKey("scopes")) {
|
1658 | 1672 | ReadableArray scopes = provider.getArray("scopes");
|
@@ -1795,9 +1809,8 @@ private void reauthenticateWithProvider(
|
1795 | 1809 | return;
|
1796 | 1810 | }
|
1797 | 1811 |
|
1798 |
| - OAuthProvider.Builder builder = OAuthProvider.newBuilder( |
1799 |
| - provider.getString("providerId"), |
1800 |
| - firebaseAuth); |
| 1812 | + OAuthProvider.Builder builder = |
| 1813 | + OAuthProvider.newBuilder(provider.getString("providerId"), firebaseAuth); |
1801 | 1814 | // Add scopes if present
|
1802 | 1815 | if (provider.hasKey("scopes")) {
|
1803 | 1816 | ReadableArray scopes = provider.getArray("scopes");
|
@@ -1855,6 +1868,9 @@ private AuthCredential getCredentialForProvider(
|
1855 | 1868 | if (provider.startsWith("oidc.")) {
|
1856 | 1869 | return OAuthProvider.newCredentialBuilder(provider).setIdToken(authToken).build();
|
1857 | 1870 | }
|
| 1871 | + if (credentials.containsKey(authToken) && credentials.get(authToken) != null) { |
| 1872 | + return credentials.get(authToken); |
| 1873 | + } |
1858 | 1874 |
|
1859 | 1875 | switch (provider) {
|
1860 | 1876 | case "facebook.com":
|
@@ -2217,6 +2233,36 @@ private void promiseRejectAuthException(Promise promise, Exception exception) {
|
2217 | 2233 | promise, error.getString("code"), error.getString("message"), resolverAsMap);
|
2218 | 2234 | }
|
2219 | 2235 |
|
| 2236 | + /** |
| 2237 | + * promiseRejectLinkAuthException |
| 2238 | + * |
| 2239 | + * @param promise |
| 2240 | + * @param exception |
| 2241 | + * @param authCredential |
| 2242 | + */ |
| 2243 | + private void promiseRejectLinkAuthException( |
| 2244 | + @NonNull Promise promise, |
| 2245 | + @NonNull Exception exception, |
| 2246 | + @NonNull AuthCredential authCredential) { |
| 2247 | + WritableMap error = getJSError(exception); |
| 2248 | + String authHashCode = String.valueOf(authCredential.hashCode()); |
| 2249 | + |
| 2250 | + WritableMap authCredentialsMap = Arguments.createMap(); |
| 2251 | + authCredentialsMap.putString("providerId", authCredential.getProvider()); |
| 2252 | + authCredentialsMap.putString("token", authHashCode); |
| 2253 | + authCredentialsMap.putString("secret", null); |
| 2254 | + |
| 2255 | + // Temporarily store the non-serializable credential for later |
| 2256 | + credentials.put(authHashCode, authCredential); |
| 2257 | + |
| 2258 | + WritableMap userInfoMap = Arguments.createMap(); |
| 2259 | + userInfoMap.putString("code", error.getString("code")); |
| 2260 | + userInfoMap.putString("message", error.getString("message")); |
| 2261 | + userInfoMap.putMap("authCredential", authCredentialsMap); |
| 2262 | + |
| 2263 | + promise.reject(error.getString("code"), error.getString("message"), userInfoMap); |
| 2264 | + } |
| 2265 | + |
2220 | 2266 | /**
|
2221 | 2267 | * getJSError
|
2222 | 2268 | *
|
|
0 commit comments