Skip to content

Commit c950da6

Browse files
authored
Cancel sign in when user is disabled (#1760)
1 parent 85340ba commit c950da6

File tree

7 files changed

+106
-19
lines changed

7 files changed

+106
-19
lines changed

auth/src/main/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPrompt.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@
2828

2929
import com.firebase.ui.auth.ErrorCodes;
3030
import com.firebase.ui.auth.FirebaseAuthAnonymousUpgradeException;
31+
import com.firebase.ui.auth.FirebaseUiException;
3132
import com.firebase.ui.auth.IdpResponse;
3233
import com.firebase.ui.auth.R;
3334
import com.firebase.ui.auth.data.model.FlowParameters;
3435
import com.firebase.ui.auth.ui.AppCompatBase;
3536
import com.firebase.ui.auth.util.ExtraConstants;
37+
import com.firebase.ui.auth.util.FirebaseAuthError;
3638
import com.firebase.ui.auth.util.data.PrivacyDisclosureUtils;
3739
import com.firebase.ui.auth.util.data.ProviderUtils;
3840
import com.firebase.ui.auth.util.ui.ImeHelper;
@@ -41,7 +43,10 @@
4143
import com.firebase.ui.auth.viewmodel.email.WelcomeBackPasswordHandler;
4244
import com.google.android.material.textfield.TextInputLayout;
4345
import com.google.firebase.auth.AuthCredential;
46+
import com.google.firebase.auth.FirebaseAuth;
47+
import com.google.firebase.auth.FirebaseAuthException;
4448
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
49+
import com.google.firebase.auth.FirebaseAuthInvalidUserException;
4550

4651
import androidx.annotation.NonNull;
4752
import androidx.annotation.Nullable;
@@ -120,9 +125,21 @@ protected void onFailure(@NonNull Exception e) {
120125
if (e instanceof FirebaseAuthAnonymousUpgradeException) {
121126
IdpResponse response = ((FirebaseAuthAnonymousUpgradeException) e).getResponse();
122127
finish(ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT, response.toIntent());
123-
} else {
124-
mPasswordLayout.setError(getString(getErrorMessage(e)));
128+
return;
125129
}
130+
131+
if (e instanceof FirebaseAuthException) {
132+
FirebaseAuthException authEx = (FirebaseAuthException) e;
133+
FirebaseAuthError error = FirebaseAuthError.fromException(authEx);
134+
if (error == FirebaseAuthError.ERROR_USER_DISABLED) {
135+
IdpResponse resp = IdpResponse.from(
136+
new FirebaseUiException(ErrorCodes.ERROR_USER_DISABLED));
137+
finish(RESULT_CANCELED, resp.toIntent());
138+
return;
139+
}
140+
}
141+
142+
mPasswordLayout.setError(getString(getErrorMessage(e)));
126143
}
127144
});
128145

auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,19 @@ protected void onSuccess(@NonNull IdpResponse response) {
163163

164164
@Override
165165
protected void onFailure(@NonNull Exception e) {
166+
if (e instanceof UserCancellationException) {
167+
// User pressed back, there is no error.
168+
return;
169+
}
170+
166171
if (e instanceof FirebaseAuthAnonymousUpgradeException) {
167172
finish(ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT,
168173
((FirebaseAuthAnonymousUpgradeException) e).getResponse().toIntent());
169-
} else if ((!(e instanceof UserCancellationException))) {
170-
String text = e instanceof FirebaseUiException ? e.getMessage() :
171-
getString(R.string.fui_error_unknown);
174+
} else if (e instanceof FirebaseUiException) {
175+
FirebaseUiException fue = (FirebaseUiException) e;
176+
finish(RESULT_CANCELED, IdpResponse.from(fue).toIntent());
177+
} else {
178+
String text = getString(R.string.fui_error_unknown);
172179
Toast.makeText(AuthMethodPickerActivity.this,
173180
text,
174181
Toast.LENGTH_SHORT).show();

auth/src/main/java/com/firebase/ui/auth/ui/phone/PhoneActivity.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.firebase.ui.auth.ErrorCodes;
2323
import com.firebase.ui.auth.FirebaseAuthAnonymousUpgradeException;
24+
import com.firebase.ui.auth.FirebaseUiException;
2425
import com.firebase.ui.auth.IdpResponse;
2526
import com.firebase.ui.auth.R;
2627
import com.firebase.ui.auth.data.model.FlowParameters;
@@ -33,6 +34,7 @@
3334
import com.firebase.ui.auth.viewmodel.ResourceObserver;
3435
import com.firebase.ui.auth.viewmodel.phone.PhoneProviderResponseHandler;
3536
import com.google.android.material.textfield.TextInputLayout;
37+
import com.google.firebase.auth.FirebaseAuth;
3638
import com.google.firebase.auth.FirebaseAuthException;
3739
import com.google.firebase.auth.PhoneAuthProvider;
3840

@@ -159,8 +161,14 @@ private void handleError(@Nullable Exception e) {
159161
IdpResponse response = ((FirebaseAuthAnonymousUpgradeException) e).getResponse();
160162
finish(ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT, response.toIntent());
161163
} else if (e instanceof FirebaseAuthException) {
162-
errorView.setError(getErrorMessage(
163-
FirebaseAuthError.fromException((FirebaseAuthException) e)));
164+
FirebaseAuthError error = FirebaseAuthError.fromException((FirebaseAuthException) e);
165+
if (error == FirebaseAuthError.ERROR_USER_DISABLED) {
166+
IdpResponse response = IdpResponse.from(
167+
new FirebaseUiException(ErrorCodes.ERROR_USER_DISABLED));
168+
finish(RESULT_CANCELED, response.toIntent());
169+
return;
170+
}
171+
errorView.setError(getErrorMessage(error));
164172
} else if (e != null) {
165173
errorView.setError(e.getLocalizedMessage());
166174
} else {

auth/src/main/java/com/firebase/ui/auth/viewmodel/email/WelcomeBackPasswordHandler.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.firebase.ui.auth.data.model.Resource;
88
import com.firebase.ui.auth.data.model.User;
99
import com.firebase.ui.auth.data.remote.ProfileMerger;
10+
import com.firebase.ui.auth.util.FirebaseAuthError;
1011
import com.firebase.ui.auth.util.data.AuthOperationManager;
1112
import com.firebase.ui.auth.util.data.TaskFailureLogger;
1213
import com.firebase.ui.auth.viewmodel.SignInViewModelBase;
@@ -19,6 +20,8 @@
1920
import com.google.firebase.auth.AuthCredential;
2021
import com.google.firebase.auth.AuthResult;
2122
import com.google.firebase.auth.EmailAuthProvider;
23+
import com.google.firebase.auth.FirebaseAuth;
24+
import com.google.firebase.auth.FirebaseAuthException;
2225

2326
import androidx.annotation.NonNull;
2427
import androidx.annotation.Nullable;

auth/src/main/java/com/firebase/ui/auth/viewmodel/idp/SocialProviderResponseHandler.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.firebase.ui.auth.ui.email.WelcomeBackEmailLinkPrompt;
1616
import com.firebase.ui.auth.ui.email.WelcomeBackPasswordPrompt;
1717
import com.firebase.ui.auth.ui.idp.WelcomeBackIdpPrompt;
18+
import com.firebase.ui.auth.util.FirebaseAuthError;
1819
import com.firebase.ui.auth.util.data.AuthOperationManager;
1920
import com.firebase.ui.auth.util.data.ProviderUtils;
2021
import com.firebase.ui.auth.viewmodel.RequestCodes;
@@ -24,6 +25,8 @@
2425
import com.google.firebase.auth.AuthCredential;
2526
import com.google.firebase.auth.AuthResult;
2627
import com.google.firebase.auth.EmailAuthProvider;
28+
import com.google.firebase.auth.FirebaseAuth;
29+
import com.google.firebase.auth.FirebaseAuthException;
2730
import com.google.firebase.auth.FirebaseAuthInvalidUserException;
2831
import com.google.firebase.auth.FirebaseAuthUserCollisionException;
2932
import com.google.firebase.auth.PhoneAuthProvider;
@@ -78,12 +81,28 @@ public void onSuccess(AuthResult result) {
7881
.addOnFailureListener(new OnFailureListener() {
7982
@Override
8083
public void onFailure(@NonNull Exception e) {
81-
if (e instanceof FirebaseAuthUserCollisionException) {
84+
// For some reason disabled users can hit FirebaseAuthUserCollisionException
85+
// so we have to handle this special case.
86+
boolean isDisabledUser = (e instanceof FirebaseAuthInvalidUserException);
87+
if (e instanceof FirebaseAuthException) {
88+
FirebaseAuthException authEx = (FirebaseAuthException) e;
89+
FirebaseAuthError fae = FirebaseAuthError.fromException(authEx);
90+
if (fae == FirebaseAuthError.ERROR_USER_DISABLED) {
91+
isDisabledUser = true;
92+
}
93+
}
94+
95+
if (isDisabledUser) {
96+
setResult(Resource.<IdpResponse>forFailure(
97+
new FirebaseUiException(ErrorCodes.ERROR_USER_DISABLED)
98+
));
99+
} else if (e instanceof FirebaseAuthUserCollisionException) {
82100
final String email = response.getEmail();
83101
if (email == null) {
84102
setResult(Resource.<IdpResponse>forFailure(e));
85103
return;
86104
}
105+
87106
// There can be a collision due to:
88107
// CASE 1: Anon user signing in with a credential that belongs to an
89108
// existing user.
@@ -119,15 +138,6 @@ public void onFailure(@NonNull Exception e) {
119138
e));
120139
}
121140
});
122-
} else if (e instanceof FirebaseAuthInvalidUserException) {
123-
setResult(Resource.<IdpResponse>forFailure(
124-
new FirebaseUiException(
125-
ErrorCodes.ERROR_USER_DISABLED,
126-
ErrorCodes.toFriendlyMessage(
127-
ErrorCodes.ERROR_USER_DISABLED
128-
)
129-
)
130-
));
131141
}
132142
}
133143
});

auth/src/test/java/com/firebase/ui/auth/testhelpers/ResourceMatchers.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.firebase.ui.auth.testhelpers;
22

3+
import com.firebase.ui.auth.FirebaseUiException;
4+
import com.firebase.ui.auth.IdpResponse;
35
import com.firebase.ui.auth.data.model.Resource;
46
import com.firebase.ui.auth.data.model.State;
57

@@ -22,6 +24,28 @@ public static <T> ArgumentMatcher<Resource<T>> isFailure() {
2224
return isState(State.FAILURE);
2325
}
2426

27+
public static <T> ArgumentMatcher<Resource<T>> isFailureWithCode(final int code) {
28+
return new ArgumentMatcher<Resource<T>>() {
29+
@Override
30+
public boolean matches(Resource<T> argument) {
31+
if (argument.getState() != State.FAILURE) {
32+
return false;
33+
}
34+
35+
if (argument.getException() == null) {
36+
return false;
37+
}
38+
39+
if (!(argument.getException() instanceof FirebaseUiException)) {
40+
return false;
41+
}
42+
43+
FirebaseUiException fue = (FirebaseUiException) argument.getException();
44+
return fue.getErrorCode() == code;
45+
}
46+
};
47+
}
48+
2549
public static <T> ArgumentMatcher<Resource<T>> isSuccessWith(final T result) {
2650
return new ArgumentMatcher<Resource<T>>() {
2751
@Override

auth/src/test/java/com/firebase/ui/auth/viewmodel/SocialProviderResponseHandlerTest.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.app.Application;
55

66
import com.firebase.ui.auth.AuthUI;
7+
import com.firebase.ui.auth.ErrorCodes;
78
import com.firebase.ui.auth.FirebaseAuthAnonymousUpgradeException;
89
import com.firebase.ui.auth.IdpResponse;
910
import com.firebase.ui.auth.data.model.FlowParameters;
@@ -25,9 +26,9 @@
2526
import com.google.firebase.auth.EmailAuthProvider;
2627
import com.google.firebase.auth.FacebookAuthProvider;
2728
import com.google.firebase.auth.FirebaseAuth;
29+
import com.google.firebase.auth.FirebaseAuthException;
2830
import com.google.firebase.auth.FirebaseAuthUserCollisionException;
2931
import com.google.firebase.auth.FirebaseUser;
30-
import com.google.firebase.auth.GithubAuthProvider;
3132
import com.google.firebase.auth.GoogleAuthProvider;
3233
import com.google.firebase.auth.SignInMethodQueryResult;
3334

@@ -40,7 +41,6 @@
4041
import org.mockito.MockitoAnnotations;
4142
import org.robolectric.RobolectricTestRunner;
4243

43-
import java.util.ArrayList;
4444
import java.util.Arrays;
4545
import java.util.Collections;
4646

@@ -121,6 +121,24 @@ public void testSignInResponse_failure() {
121121
verify(mResultObserver).onChanged(argThat(ResourceMatchers.<IdpResponse>isFailure()));
122122
}
123123

124+
@Test
125+
public void testSignInIdp_disabled() {
126+
mHandler.getOperation().observeForever(mResultObserver);
127+
128+
when(mMockAuth.signInWithCredential(any(AuthCredential.class)))
129+
.thenReturn(AutoCompleteTask.<AuthResult>forFailure(
130+
new FirebaseAuthException("ERROR_USER_DISABLED", "disabled")));
131+
132+
IdpResponse response = new IdpResponse.Builder(new User.Builder(
133+
GoogleAuthProvider.PROVIDER_ID, TestConstants.EMAIL).build())
134+
.setToken(TestConstants.TOKEN)
135+
.build();
136+
mHandler.startSignIn(response);
137+
138+
verify(mResultObserver).onChanged(
139+
argThat(ResourceMatchers.<IdpResponse>isFailureWithCode(ErrorCodes.ERROR_USER_DISABLED)));
140+
}
141+
124142
@Test
125143
public void testSignInIdp_resolution() {
126144
mHandler.getOperation().observeForever(mResultObserver);

0 commit comments

Comments
 (0)