I'm using Firebase Authentication in my app (email and password auth).
In the onStart() method of my Login activity I retrieve the current user using:
FirebaseUser currentUser = mAuth.getCurrentUser();
The problem comes when the user is deleted from the database, the mAuth.getCurrentUser() method still retrieves the user and allows authentication.
How can I check if the user still exists?
Thx!
Try using something like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").child("email").addListenerForSingleValueEvent(new
ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
// used "email" already exists and is not deleted
} else {
// User does not exist. Add here your logic if the user doesn't exist
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Or check some of the following SO questions and answers:
Firebase authentication for checking if the user exists in the database or not
Firebase Auth - with Email and Password - Check user already registered
You can use getInstance. This worked for me fine. You don't get an instance with it.
private boolean isSignedIn() {
return FirebaseAuth.getInstance().getCurrentUser() != null;
}
Delete the userdata and make the currentuser null:
Follow the below code.
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User account deleted.");
//Remove the information f the user from database.
}
}
});
The code below works great on android to confirm if the Firebase Auth user still exists (has not been deleted or disabled) and has valid credentials.
Deleting the Auth user from the firebase console does not revoke auth tokens on devices the user is currently logged in as the token is cached locally. Using reload() forces a check with the firebase auth server.
currentUser.reload().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
//User still exists and credentials are valid
}else {
//User has been disabled, deleted or login credentials are no longer valid,
//so send them to Login screen
}
}
});
I am trying to sign in with facebook in the reinstallation of an android app. Initially I signed up using Google and successfully linked it with firebase.
But when I try to do with facebook it gives a
FirebaseAuthUserCollisionException
I read in the Firebase Documentation that you can do so by
FirebaseUser prevUser = currentUser;
currentUser = auth.signInWithCredential(credential).await().getUser();
// Merge prevUser and currentUser accounts and data
// ...
but here await() method no longer exists. Also after searching a bit I found out this solution
Tasks.await(mAuth.signInWithCredential(credential)).getUser();
But this also gives an error when getting the current user which is already linked. What can I do to solve this?
There is no need in .await() method to get firebase user.
Use FirebaseAuth.AuthStateListenerinstead.
So you implement firebase sign in with something like this:
FirebaseAuth.getInstance()signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "login success");
} else {
Log.d(TAG, "login error");
}
}
});
And implement AuthStateListener which is trigerred every time user state is changed:
private FirebaseAuth.AuthStateListener authStateListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initAuthStateListener();
}
private void initAuthStateListener() {
authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user == null) {
//user is not logged in
} else {
//user is logged in
//logic to finish the activity and proceed to the app can be put here
}
}
};
}
#Override
protected void onStart() {
super.onStart();
FirebaseAuth.getInstance().addAuthStateListener(authStateListener);
}
#Override
protected void onStop() {
super.onStop();
FirebaseAuth.getInstance().removeAuthStateListener(authStateListener);
}
Note: onAuthStateChanged is trigerred once when authStateListener is added to firebase auth instance.
Also make sure Prevent creation of multiple accounts with the same email address parameter is set on firebase console (Authentication >> SIGN-IN METHOD >> Advanced >> One account per email address (Change) ).
When I am trying to sign up a user using Firebase authentication method in my Android application, this is happening:
It's not registering a user
This is the Registration code
final String _name = txtName.getText().toString().trim();
String _email = txtEmail.getText().toString().trim();
String _pass = txtPass.getText().toString().trim();
if(!TextUtils.isEmpty(_name) && !TextUtils.isEmpty(_email) && !TextUtils.isEmpty(_pass) ) {
mProgress.setMessage("Registrando ...");
mProgress.show();
firAuth.createUserWithEmailAndPassword(_email, _pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()) {
//the user has been registered
}
}
});
You are registring the user but not hiding the progress bar after user successfully registered in the firebase. Try applying this code and check the firebase dashboard for authentication. And also Implement onFailureListener to know the reason why user is not being registered.
firAuth.createUserWithEmailAndPassword(_email, _pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
mProgress.dismis();
if(task.isSuccessful()) {
//the user has been registered
Log.d("onSuccess","USER REGISTERED");
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
mProgress.dismis();
Log.e("onFailure",e.getMessage());
}
}
);
EDIT: If you are still facing the same issue go and check these settings in your firebase console authentication tab ,
Select SIGN-IN METHOD and Check the status of Email/Password if it is Disable then switch it to the Enable.
And it looks like you are using Genymotion, so have you installed the Google Libraries into your virtual device ?
If not follow this thread or test your app on a physical device
I referenced the documentation in Firebase page. My problem is in this paragraph:
The call to linkWithCredential will fail if the credentials are already linked to another user account. In this situation, you must handle merging the accounts and associated data as appropriate for your app:
FirebaseUser prevUser = currentUser; currentUser = auth.signInWithCredential(credential).await().getUser(); // Merge
prevUser and currentUser accounts and data // ...
I can't figure out how to add this code into my project. When and where do I put this code
auth.signInWithCredential(credential).await().getUser();
into my java file? Android Studio announced me that it can't resolve await() method.
What should I do to resolve that problem. Thank you in advance!
You should handle this part of code when the linkWithCredentials call fails.
Here is a small example :
mAuth.getCurrentUser().linkWithCredential(credentials).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
FirebaseUser prevUser = currentUser;
try {
currentUser = Tasks.await(auth.signInWithCredential(credential)).getUser();
} catch (Exception e) {
e.printStackStrace();
}
// Merge prevUser and currentUser accounts and data
// ...
} else {
}
}
});
NB: Task.await() doesn't exist anymore you should use Tasks.await(...) static method instead.
Suppose that:
One account per email address setting is enabled on firebase authentication
User are logging in with anonymous authentication
The linkWithCredential usually fails with FirebaseAuthUserCollisionException, it could happen either because this credential is used to login before (you can check by searching this email on firebase console) or this email account is used to login before but with different providers ( such as a user logged in with abc#gmail.com by using google sign in before, now he/she uses abc#gmail.com but with Facebook login ) To handle it, you need 2 steps:
Step 1: link with anonymous account
private void linkWithAnonymousAccount(final AuthCredential credential) {
mFirebaseAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
getFirebaseToken();
} else {
Exception exception = task.getException();
if (exception instanceof FirebaseAuthUserCollisionException) {
signInWithFirebase(credential);
} else {
Utils.showDialogMessage(mContext, task.getException().getLocalizedMessage());
}
}
}
});
}
Step 2: sign with firebase
private void signInWithFirebase(AuthCredential credential) {
mFirebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
getFirebaseToken();
} else {
Utils.showDialogMessage(mContext, task.getException().getLocalizedMessage());
}
}
});
}
Google says the step 2 is merging because after signed in, you need to get information of the previous user and put into the new user.
I hope it helpful.
I'm trying to code a Delete User method in my Android App, but I have some issues each time I execute it. This method will be executed when a user pushes the Delete account button on an Activity. My apps works with FirebaseUI Auth.
Here is the method:
private void deleteAccount() {
Log.d(TAG, "ingreso a deleteAccount");
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
final FirebaseUser currentUser = firebaseAuth.getCurrentUser();
currentUser.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG,"OK! Works fine!");
startActivity(new Intent(Main3WelcomeActivity.this, Main3Activity.class));
finish();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG,"Ocurrio un error durante la eliminaciĆ³n del usuario", e);
}
});
}
1) When I execute that function a Smart Lock message appears on the screen and the user is signed in again. Here is a screenshot of this message.
2) On other occasions, when the user is logged in for a long time, the function throws an Exception like this:
06-30 00:01:26.672 11152-11152/com.devpicon.android.firebasesamples E/Main3WelcomeActivity: Ocurrio un error durante la eliminaciĆ³n del usuario
com.google.firebase.FirebaseException: An internal error has occured. [ CREDENTIAL_TOO_OLD_LOGIN_AGAIN ]
at com.google.android.gms.internal.zzacq.zzbN(Unknown Source)
at com.google.android.gms.internal.zzacn$zzg.zza(Unknown Source)
at com.google.android.gms.internal.zzacy.zzbO(Unknown Source)
at com.google.android.gms.internal.zzacy$zza.onFailure(Unknown Source)
at com.google.android.gms.internal.zzact$zza.onTransact(Unknown Source)
at android.os.Binder.execTransact(Binder.java:453)
I've read that I have to re-authenticate the user but I'm not sure how to do this when I'm working with Google Sign In.
As per the Firebase documentation can user delete() method to remove user from the Firebase
Before remove the user please reAuthenticate the user.
Sample code
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
// Get auth credentials from the user for re-authentication. The example below shows
// email and password credentials but there are multiple possible providers,
// such as GoogleAuthProvider or FacebookAuthProvider.
AuthCredential credential = EmailAuthProvider
.getCredential("user#example.com", "password1234");
// Prompt the user to re-provide their sign-in credentials
user.reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User account deleted.");
}
}
});
}
});
For more details : https://firebase.google.com/docs/auth/android/manage-users#re-authenticate_a_user
If you want to user re Authentication with other singin provider only need to change the Provider for GoogleAuthProvider below is the sample code
GoogleAuthProvider.getCredential(googleIdToken,null);
The answer provided by Ansuita Jr. is very beautifully explained and is correct with just a small problem.
The user gets deleted even without having successful re-authentication.
This is because we use
user.delete()
in the onComplete() method which is always executed.
Therefore, we need to add an if check to check whether the task is successful or not which is mentioned below
user.reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.e("TAG", "onComplete: authentication complete");
user.delete()
.addOnCompleteListener (new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.e("TAG", "User account deleted.");
} else {
Log.e("TAG", "User account deletion unsucessful.");
}
}
});
} else {
Toast.makeText(UserProfileActivity.this, "Authentication failed",
Toast.LENGTH_SHORT).show();
}
}
});
Your delete callback already handles the case of a failure, why do you add addOnFailureListener later?
Try to delete it, this way:
private void deleteAccount() {
Log.d(TAG, "ingreso a deleteAccount");
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
final FirebaseUser currentUser = firebaseAuth.getCurrentUser();
currentUser.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG,"OK! Works fine!");
startActivity(new Intent(Main3WelcomeActivity.this, Main3Activity.class));
finish();
} else {
Log.w(TAG,"Something is wrong!");
}
}
});
}
First of all, you need to store the auth token or the password at the moment your user is logging in. If your app doesn't provide such as Google Sign-in, Facebook Sign-in or others, you just need to store the password.
//If there's any, delete all stored content from this user on Real Time Database.
yourDatabaseReferenceNode.removeValue();
//Getting the user instance.
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
//You need to get here the token you saved at logging-in time.
String token = "userSavedToken";
//You need to get here the password you saved at logging-in time.
String password = "userSavedPassword";
AuthCredential credential;
//This means you didn't have the token because user used like Facebook Sign-in method.
if (token == null) {
credential = EmailAuthProvider.getCredential(user.getEmail(), password);
} else {
//Doesn't matter if it was Facebook Sign-in or others. It will always work using GoogleAuthProvider for whatever the provider.
credential = GoogleAuthProvider.getCredential(token, null);
}
//We have to reauthenticate user because we don't know how long
//it was the sign-in. Calling reauthenticate, will update the
//user login and prevent FirebaseException (CREDENTIAL_TOO_OLD_LOGIN_AGAIN) on user.delete()
user.reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
//Calling delete to remove the user and wait for a result.
user.delete().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
//Ok, user remove
} else {
//Handle the exception
task.getException();
}
}
});
}
});
}
#Android developers:
I faced an issue where the Firebase Auth information was persisting in the device's disk AFTER uninstalling the app. After experimenting and reading about it, I found that setting android:allowBackup="false" and android:fullBackupContent="false" in the Manifest's <application> tag will ensure the identity information is not persisted after the app is uninstalled.
Please note, this kind of persistence was not happening on all Android devices. In fact, it started happening on one of my devices that never had this issue.
If the sign-in method is "Anonymous", you can just call
FirebaseAuth.getInstance().getCurrentUser().delete().addOnCompleteListener(task -> {
if (task.isSuccessful()){
Log.d(TAG, "Deletion Success");
}
});
But if it's a different method, you will need a re-authentication.
How to re-authenticate
Use this methods :-
remove()
is equivalent to calling set(null).
or
removeUser()
removeUser(credentials, [onComplete])
Only get current user and delete it by using following method it'll work fine
user.delete();
and you can add on Oncompletelistner also
by addinduser.delete().addOnCompleteListner(new OnCompleteListner)and more on
If you are using AuthUI or FirebaseAuth you can just do the following
AuthUI.getInstance().delete(context).addOnSuccessListener {
}.addOnFailureListener{
}
OR
FirebaseAuth.getInstance().currentUser.delete().addOnSuccessListener...
If you are using FirebaseUI Auth you can just do the following
private void delete() {
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser user=firebaseAuth.getCurrentUser();
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
startActivity(new Intent(Main3WelcomeActivity.this, Main3Activity.class));
finish();
Toast.makeText(Main3WelcomeActivity.this,"Account deleted",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(Home.this,"failed",Toast.LENGTH_LONG).show();
}
}
});}