I am using Firebase Anonymous Authentication.
In case a user has been deleted from the Firebase console, the client still believes the user exists, as it still holds the token.
Each time I start the app, I would like to verify if the user still exists. I found out I can use the FirebaseUser.reload() function.
The documentation says that in case the user's account has been disabled or deleted, the FirebaseAuthInvalidUserException will be thrown:
https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseUser.html#reload()
However this is an asyncronous function, and I am struggling finding out how to catch this exception. Can anyone show me a code sample on how to catch this exception?
I have looked all documentation, but I haven't found a sample about this.
Try this:
mFirebaseUser.reload().addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof FirebaseAuthInvalidUserException) {
Log.d(TheApp.LOG_TAG, "user doesn't exist anymore");
createUser();
}
}
});
Related
I have used anonymous sign in in my app. So, whenever the user opens the app, the user gets signed in by a new anonymous account. As a result, in spite of having a very few users (around 4 to 5), there are more than 400 signed in accounts in my Firebase Authentication section. That's why I thought to delete the user (the anonymous account) when the user closes the app. For this reason, I have used
user.delete().addOnCompleteListener( new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText( Activity.this, "Deleted Successfully" , Toast.LENGTH_LONG).show();
}
else {
Toast.makeText( Activity.this, "Failed" , Toast.LENGTH_LONG).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText( Activity.this, "Failed to delete" , Toast.LENGTH_LONG).show();
}
});
But, the problem is NO TOAST IS DISPLAYED. So, what can be causing this problem? I don't know whether the user is being deleted or not. Also, suggest some better way to tackle this problem, if possible.
This isn't the way that anonymous accounts are meant to be used. They are expected to persist across app launches so that any per-user data you're storing will continue to be associated with the user as they come and go. Deleting the account whenever the app is backgrounded is certainly going to cause confusion for both you and the user.
If you want to do something to purge unused accounts, you should have some backend code that uses the Firebase Admin SDK that periodically deletes old user accounts by whatever criteria you decide that makes that account "old".
I'm trying to log in in Firebase from these type of services in Android.
I'm able to successfully login anonymously from my main activity this way:
private FirebaseAuth mAuth;
(more code)
mAuth.signInAnonymously().addOnSuccessListener(this, new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(#NonNull AuthResult authResult) {
(more code to execute when the user has logged)
But if I try to use the same thing from a Service or JobIntentService it's impossible to do, as the first parameter for addOnSuccessListener needs to refer to an activity.
I tried to do a cast in the service to Activity to that "this", but, as expected, it didn't work.
I also tried with:
mAuth.signInAnonymously().addOnCompleteListener(
But the same happens with the first parameter, it needs to be an activity.
Under some circumstances, the mentioned services might run when the main activity is active, but not as a general rule, so I'd need something to allow a service to log in regardless of another circumstance.
Unless this was a restriction for firebase and cannot be done, which I would find pretty strange.
I finally realized a solution:
This code:
while (true){
try {
if (mAuth.getCurrentUser().getUid() == null) {
} else {
break;
}
}
catch (Exception e)
{
}
}
Allows to wait until the user has successfully logged in into firebase.
It can be improved by limiting the number of times the loop executes, but it serves as a general idea.
Note I posted the issue/question to google sample github repo, https://github.com/googlesamples/android-play-safetynet/issues/12. However, I don't get any response yet.
library version used: com.google.android.gms:play-services-safetynet:11.4.2
I am using safety net captcha API. everything working as expected meaning, both are detected:
- on success (when test with real device and no harms detected)
- one failure listener (when test with Android emulator and verified the steps)
However, Here steps produce issue where on success and on failure are not detected:
- Run app in Android emulator
- Hit the SafetyNet verify with captcha
- As android emulator mark as possible harm, it will shows image for the verification
- Click on listen icon to listen the word
- Click on the screen outside the dialog area, the verification dialog will close
Expected: addOnFailureListener should be triggered because user didn't response to the verification steps when detected as robot
Actual: both OnSuccessListener and addOnFailureListener are not detected
Sample code
SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
.addOnSuccessListener((Executor) this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Executor) this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
Log.d(TAG, "Error: " + CommonStatusCodes
.getStatusCodeString(statusCode));
} else {
// A different, unknown type of error occurred.
Log.d(TAG, "Error: " + e.getMessage());
}
}
});
Questions:
Is it expected design in which if user dismiss the verification dialog then SafetyNet doesn't notify the listener?
Are there any other listener for SafetyNet to handle the scenario above of the issue? or other solutions to handling this scenario from SafetyNet SDK?
Thanks
Github issue solution is to handle action onResume()
When safety net captcha is Cancelled:
In my case requirement were to end animation on button when safety net captcha was dismissed. So user would be able to click on it once again.
When safety net captcha fails:
They suggested to close all dialog onResume()
In Kotlin answer for that should be:
supportFragmentManager.fragments.takeIf { it.isNotEmpty() }?.map { (it as? DialogFragment)?.dismiss() }
For java you can find answer here:
Android - How to Dismiss All Dialogs in onPause
I am building an app where I use AWS Cognito to make user accounts. I can get it to work just fine most of the time, I have successfully made all the necessary classes and handlers to create and authenticate users and just abut everything else. However, I seem to run into this strange problem ONLY when trying to sign a user in right after their account has been created.
com.amazonaws.mobileconnectors.cognitoidentityprovider.exceptions.CognitoInternalErrorException: Authentication failed due to an internal error
If I restart the app, I can sign in just fine, so it is an issue with signing in right after an account has been created. It is very unspecific and the documentation just says "An internal error has occurred. Retry your request, but if the problem persists, contact us with details by posting a message on the AWS forums." How do you get around this?
Basically after you create an account and authenticate it, there is something cached in one of the AWS API related classes which still points towards the account not being authenticated. This error is only occurring if trying to immediately sign in after the account was created. In my case and in most cases, all of the AWS Cognito API code is contained in a manager/helper class, mine is an AWSHelper Class. To get around this issue, in my Handler after the user is confirmed, I simply recreated the AWSHelper in my activity, and I am able to sign in just fine.
GenericHandler confirmationCallback = new GenericHandler() {
#Override
public void onSuccess() {
Log.w("DMJ", "user has been confirmed!");
if (!mainActivity.updateAWS()) {
Toast.makeText(activity, "Account created! Please sign into your account", Toast.LENGTH_LONG).show();
activity.changeFragment(new SignInFragment(), "SignInFragment");
} else {
Toast.makeText(activity, "Account created!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Exception exception) {
Log.w("DMJ", "confirmation got rekt m8");
exception.printStackTrace();
}
};
In my MainActivity, I have the following method
public boolean updateAWS() {
awsHelper = new AWSHelper(this);
if (awsHelper.isSignedIn) {
changeFragment(new HomeScreenFragment(), "HomeScreenFragment");
return true;
}
return false;
}
ALSO, I have not checked but I suspect if you try to sign in the user after the the onSuccess() method entirely, the CognitoUser will be updated and able to sign in without the CognitoInternalErrorException
I'm looking to catch the errors of the new methods to change email and password for Android, but I can't seem to find anything. Can somebody point me in the right direction?
The official documentation is not clear about this.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String newPassword = "SOME-SECURE-PASSWORD";
user.updatePassword(newPassword)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User password updated.");
}
}
});
https://firebase.google.com/docs/auth/android/manage-users#set_a_users_password
The callbacks use the new Task class in Google Play services. There are two ways of catching errors with this:
Use addOnCompleteListener, check for isSuccessful and inspect the return of getException if it failed.
Use addOnSuccessListener and addOnFailureListener. The latter callback will include an Exception with the error.
The actual exceptions returned are documented in the reference documentation for each method. For example, updatePassword could fail with:
FirebaseAuthWeakPasswordException thrown if the password is not strong enough
FirebaseAuthInvalidUserException thrown if the current user's account has been disabled, deleted, or its credentials are no longer valid
FirebaseAuthRecentLoginRequiredException thrown if the user's last sign-in time does not meet the security threshold. Use reauthenticate(AuthCredential) to resolve. This does not apply if the user is anonymous.