Skip to content

Commit f8916e2

Browse files
joaqomikehardy
andauthored
fix(auth, android): return credential for signin if phone auth has link collision (#7793)
* Fix Android phone sign in not returning authCredential You can now upgrade anonymous users using phone auth on Android. Credit to @Shaninnik. * Apply suggestions from code review * style(lint): `yarn lint:android` cleaning things up after merging in suggestions * fix(auth, android): if no credential in collision exception, avoid accessing it --------- Co-authored-by: Mike Hardy <[email protected]>
1 parent cfd6f19 commit f8916e2

File tree

1 file changed

+55
-9
lines changed

1 file changed

+55
-9
lines changed

packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.google.firebase.auth.FirebaseAuthMultiFactorException;
5050
import com.google.firebase.auth.FirebaseAuthProvider;
5151
import com.google.firebase.auth.FirebaseAuthSettings;
52+
import com.google.firebase.auth.FirebaseAuthUserCollisionException;
5253
import com.google.firebase.auth.FirebaseUser;
5354
import com.google.firebase.auth.FirebaseUserMetadata;
5455
import com.google.firebase.auth.GetTokenResult;
@@ -107,6 +108,10 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule {
107108
private final HashMap<String, MultiFactorResolver> mCachedResolvers = new HashMap<>();
108109
private final HashMap<String, MultiFactorSession> mMultiFactorSessions = new HashMap<>();
109110

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+
110115
ReactNativeFirebaseAuthModule(ReactApplicationContext reactContext) {
111116
super(reactContext, TAG);
112117
}
@@ -914,9 +919,8 @@ private void signInWithProvider(String appName, ReadableMap provider, final Prom
914919
return;
915920
}
916921

917-
OAuthProvider.Builder builder = OAuthProvider.newBuilder(
918-
provider.getString("providerId"),
919-
firebaseAuth);
922+
OAuthProvider.Builder builder =
923+
OAuthProvider.newBuilder(provider.getString("providerId"), firebaseAuth);
920924
// Add scopes if present
921925
if (provider.hasKey("scopes")) {
922926
ReadableArray scopes = provider.getArray("scopes");
@@ -1613,6 +1617,17 @@ private void linkWithCredential(
16131617
promiseWithAuthResult(task.getResult(), promise);
16141618
} else {
16151619
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+
}
16161631
Log.e(TAG, "link:onComplete:failure", exception);
16171632
promiseRejectAuthException(promise, exception);
16181633
}
@@ -1650,9 +1665,8 @@ private void linkWithProvider(String appName, ReadableMap provider, final Promis
16501665
return;
16511666
}
16521667

1653-
OAuthProvider.Builder builder = OAuthProvider.newBuilder(
1654-
provider.getString("providerId"),
1655-
firebaseAuth);
1668+
OAuthProvider.Builder builder =
1669+
OAuthProvider.newBuilder(provider.getString("providerId"), firebaseAuth);
16561670
// Add scopes if present
16571671
if (provider.hasKey("scopes")) {
16581672
ReadableArray scopes = provider.getArray("scopes");
@@ -1795,9 +1809,8 @@ private void reauthenticateWithProvider(
17951809
return;
17961810
}
17971811

1798-
OAuthProvider.Builder builder = OAuthProvider.newBuilder(
1799-
provider.getString("providerId"),
1800-
firebaseAuth);
1812+
OAuthProvider.Builder builder =
1813+
OAuthProvider.newBuilder(provider.getString("providerId"), firebaseAuth);
18011814
// Add scopes if present
18021815
if (provider.hasKey("scopes")) {
18031816
ReadableArray scopes = provider.getArray("scopes");
@@ -1855,6 +1868,9 @@ private AuthCredential getCredentialForProvider(
18551868
if (provider.startsWith("oidc.")) {
18561869
return OAuthProvider.newCredentialBuilder(provider).setIdToken(authToken).build();
18571870
}
1871+
if (credentials.containsKey(authToken) && credentials.get(authToken) != null) {
1872+
return credentials.get(authToken);
1873+
}
18581874

18591875
switch (provider) {
18601876
case "facebook.com":
@@ -2217,6 +2233,36 @@ private void promiseRejectAuthException(Promise promise, Exception exception) {
22172233
promise, error.getString("code"), error.getString("message"), resolverAsMap);
22182234
}
22192235

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+
22202266
/**
22212267
* getJSError
22222268
*

0 commit comments

Comments
 (0)