Firebase: onAuthStateChanged comes with old user Uid - android

I get old (previously registered) user Uid in onAuthStateChanged after delete firebase account and then immediately creating a new one. But it is happen not every time, and I don't know what it is depends of. Any suggestions?
Also FirebaseAuth.getInstance().getCurrentUser() is null into this callback, which is strange too.
Might deletion process depends of completion of functions.auth.user().onDelete in Firebase Functions, but I'm not sure.
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
// re-auth need for delete account flow
if (reAuthFirebase){
Log.d(TAG, "onAuthStateChanged reAuthFirebase");
reAuthFirebase = false;
return;
}
// ignore 1st callback http://stackoverflow.com/a/40436769/1621111
if (isFirstAuthCallback){
Log.d(TAG, "onAuthStateChanged subscribe 1st callback");
isFirstAuthCallback = false;
return;
}
String firebaseUserUid = firebaseAuth.getUid(); // getting old Uid
}

Related

Is it a good idea to call Firebase reload() inside OnAuthStateChanged?

Is it a good idea to call Firebase reload() inside OnAuthStateChanged? Initially I would call reload() during app initialization, but it's not guaranteed the FirebaseUser object has been loaded yet. Seems a clean way to do it is call inside OnAuthStateChanged() if the user is not null. The logic being that the returned user profile would match what's cached and no subsequent calls to OnAuthStateChanged will be issued. It works - but I'm a bit worried about a run-away loop for reasons that may not be obvious to me.
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth)
{
final FirebaseUser user = mAuth.getCurrentUser();
//call reload here???
if (user != null)
{
user.reload().addOnFailureListener(new OnFailureListener()
{
#Override
public void onFailure(#NonNull Exception e)
{
if (e instanceof FirebaseAuthInvalidUserException)
{
Log.e(TAG, "INVALID USER EXCEPTION: " + e);
Disconnect();
SignOut();
}
}
});
}
}
I would not expect reload() to do anything significant at all on a newly signed in user. Since onAuthStateChanged indicates that the user has just signed in, the profile information should have just been loaded from the backend service. Reloading at that point isn't likely to be helpful.
Reloading is intended for times when a user has been signed in for a while, and your code is trying to check if something changed with its profile since it was last signed in.

Real-time database onDisconnect not executing after logging out

I have implemented the Firebase Real-Time Database presence system as shown in the official Firebase documentation. I would like to make the database secure so that logged-in users can only write to their own presence entries in the DB. So, on login, the user writes to the reference path /auth/{authId}/connections and at the same time sets up the onDisconnect to remove the value.
Here is the code from the Android app that is setting presence in rtdb:
getFirebaseDatabase().goOnline();
DatabaseReference.goOnline();
// Since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
final FirebaseDatabase database = getFirebaseDatabase();
final DatabaseReference myConnectionsRef = database.getReference("/auth/" + getFirebaseAuth().getUid() + "/connections");
// Stores the timestamp of my last disconnect (the last time I was seen online)
final DatabaseReference lastOnlineRef = database.getReference("/auth/" + getFirebaseAuth().getUid() + "/lastOnline");
connectedRef = database.getReference(".info/connected");
presenceChangeListener = connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
DatabaseReference con = myConnectionsRef.push();
// When this device disconnects, remove it
con.onDisconnect().removeValue()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Add this device to my connections list
// this value could contain info about the device or a timestamp too
con.setValue("ANDROID");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "### Failed to set onDisconnect ###");
e.printStackTrace();
}
});
// When I disconnect, update the last time I was seen online
lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP);
}
}
#Override
public void onCancelled(DatabaseError error) {
Log.w(TAG, "Listener was cancelled at .info/connected");
}
});
The problem that I am having is that if the user logs out, the onDisconnect doesn't execute unless I first manually disconnect from rtdb. I'm assuming that the code running on the Real-Time DB gets a permission denied since the auth is no longer valid.
//If I don't go offline first the record in rtdb will not be removed.
DatabaseReference.goOffline();
AuthUI.getInstance().signOut(this)
.addOnCompleteListener(new OnCompleteListener<Void>() {
public void onComplete(#NonNull Task<Void> task) {
// user is now signed out
Log.d(TAG, "Logged out");
application.clearData();
DatabaseReference.goOffline(); //This doesn't cause a presence update here
finish();
}
});
Above is the work-around I'm using, first telling the database to goOffline then to logout. If the user ever gets logged out by another means (the web app is seeing if multiple tabs are using the app and one logs out) the user will be left with a connection not removed.
If I don't call the goOffline() prior to logout, the connection in rtdb will not be removed, even if I force close the application.
I have also verified that I can get everything working fine if I change my rtdb rules to be ".write": "true" <-which is no good. This tells me that there is a permission denied with the onDisconnect running when a user logs out of the auth.
I would like my real-time rules to be something like this.
{
"rules": {
"auth": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
I would have hoped that the onDisconnect would still be able to execute with the auth of the user when the onDisconnect was setup.
When you attach a onDisconnect() handler, you're registering a delayed write on the Firebase servers. Whether that write is allowed is checked both when you attach the handler, and when the handler is triggered. And since your user is signed out when the write is triggered, it get rejected by your rules. There is no configuration option to change this behavior, so you'll have to come up with a different approach.
So, because 1.) the onDisconnect() execution is evaluated against the rules of the RTDB, 2.) the user who setup the onDisconnect() may lose authentication, and 3.) I would like to make the presence system secure for my auth'ed users... I came up with the following solution:
First, write the presence entries to the RTDB under a path that contains both the user's authId and a UUID to make the location "unguessable".
"/presence/" + {auth-uid} + "/connections/" + {UUID}
and setup a .onDisconnect() to remove this value stored at the unguessable location.
Then, setup the RTDB rules to do the following:
do not allow any reading of the presence data
allow users to add/modify data only under their auth directory
allow any user to delete records (they would need to know the unguessable path)
"presence": {
".read": "false",
".write": "false",
"$auth_id": {
"connections": {
"$uuid": {
".write": "(newData.exists() && $auth_id === auth.uid) || !newData.exists()"
}
}
}
}
Finally, setup a trigger function on the RTDB to read the .ref('/presence/{authid}') location and push the user's presence to another user accessible location (I'm pushing it to my Firestore DB). Also, if the user is changing from "online" to "offline" update a lastOnline timestamp to the current time.
This seems like the best solution given my requirements of having reliable and secure presence system. I hope this helps others.
It is an old question but it made me think about a possible solution and came with the following...
use onDisconnect.setValue/removeValue as long as you have control/awareness over the application
use onDisconnect.cancel and delete to data before logging out
I took #FrankvanPuffelen code and modified it but didn't tested it so....
//getFirebaseDatabase().goOnline();
//DatabaseReference.goOnline();
// Since I can connect from multiple devices, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
final FirebaseDatabase database = getFirebaseDatabase();
final DatabaseReference myConnectionsRef = database.getReference("/auth/" + getFirebaseAuth().getUid() + "/connections");
// Stores the timestamp of my last disconnect (the last time I was seen online)
final DatabaseReference lastOnlineRef = database.getReference("/auth/" + getFirebaseAuth().getUid() + "/lastOnline");
connectedRef = database.getReference(".info/connected");
presenceChangeListener = connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
// simple solution to reuse the old unique key-name otherwise current solution is like performing new registration of a new client over and over on the same client. we should use the old unique key-name until logout is performed
String keyName = SharedPrefUtil.INSTANCE.getFirebaseConnectionKeyName(context);
DatabaseReference con;
if (TextUtils.isEmpty(keyName)) {
con = myConnectionsRef.push();
SharedPrefUtil.INSTANCE.setFirebaseConnectionKeyName(context.getApplicationContext(), con.getKey());
}else{
con = myConnectionsRef.child(keyName);
}
// When this device disconnects, remove it
con.onDisconnect().removeValue()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Add this device to my connections list
// this value could contain info about the device or a timestamp too
con.setValue("ANDROID");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "### Failed to set onDisconnect ###");
e.printStackTrace();
}
});
// When I disconnect, update the last time I was seen online
lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP);
}
}
#Override
public void onCancelled(DatabaseError error) {
Log.w(TAG, "Listener was cancelled at .info/connected");
}
});
in the logout method we need to cancel the disconnect
String keyName = SharedPrefUtil.INSTANCE.getFirebaseConnectionKeyName(context);
if (!TextUtils.isEmpty(keyName)) {
final FirebaseDatabase database = getFirebaseDatabase();
final DatabaseReference myConnectionsRef = database.getReference("/auth/" + getFirebaseAuth().getUid() + "/connections/" + keyName);
// Stores the timestamp of my last disconnect (the last time I was seen online)
final DatabaseReference lastOnlineRef = database.getReference("/auth/" + getFirebaseAuth().getUid() + "/lastOnline");
// This client/user doesn't need the disconnect functionality
myConnectionsRef.onDisconnect().cancel();
// now we are on our own so we need to remove the key-name from the rmdb
myConnectionsRef.setValue(null);
// remove the key-name from the preferences so we will create a new one in the next login session
SharedPrefUtil.INSTANCE.removeFirebaseConnectionKeyName(context);
// we will not forget to disconnect last time updates
lastOnlineRef.onDisconnect().cancel()
}
AuthUI.getInstance().signOut(this)
I didn't tested it and it will not run as it is missing the SharedPrefUtil implementation

Firebase Tasks: sign in + create account

My app works with Firebase Authentication. And when user starts app I need to add new user in Firebase, but I have 3 state:
There is no account
There is an account, but the user signed out
There is an account and the user signed in
For these 3 states, I must do the next:
create account in Firebase + log in my Database (at the same time)
then sign in Firebase
sign in Firebase + log in my Database (at the
same time)
log in my Database
How to make the first item correctly using Tasks? How to control errors?
I determine whether the signed user or not, using:
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
firebaseAuthUser = true;
} else {
// User is signed out
firebaseAuthUser = false;
}
}
};
You can use FirebaseUI-Android to gracefully handle those situations for you.
It's really simple to implement! Please check it here.
You can check all FirebaseUI features here

How to know which user is trying to Sign-in?

Users are created using Email and Password. This is how I do the Sign-up:
mSignup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mEmailStr = removeSpaces(mEmail.getText().toString());
mPasswordStr = mPassword.getText().toString();
mUsernameStr = mUsername.getText().toString();
mIsSgl = mSglCheckBox.isChecked();
mUsernameStr=mUsername.getText().toString();
final User mUser = new User();
mUser.setEmail(mEmailStr);
mUser.setPassword(mPasswordStr);
mUser.setIsSgl(mIsSgl);
mUser.setStudyGroupName(mStudyGroupName);
mUser.setUsername(mUsernameStr);
FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
generateUser(mUser);
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
}
}
});
}
});
This is how I push the data into database:
public void generateUser(User user)
{
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference users;
if(user.getIsSgl())
{
users = database.getReference(user.getStudyGroupName()).child("SGL");
}
else
{
users = database.getReference(user.getStudyGroupName()).child("Student");
}
users.push().setValue(user);
}
This is how I Sign-in:
mSignin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mEmailStr = SignupActivityFragment.removeSpaces(mEmail.getText().toString());
mPasswordStr = mPassword.getText().toString();
mAuth.signInWithEmailAndPassword(mEmailStr, mPasswordStr).addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()){
FirebaseDatabase database = FirebaseDatabase.getInstance();
// thats not worked for me
database.getReference("StudyGroups").child("Student").orderByChild("email").equalTo(mEmailStr).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
userKey = childSnapShot.getKey();
}
Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
Log.v("himaAbousalem",userKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Toast.makeText(getActivity(), "Sucsses ", Toast.LENGTH_SHORT).show();
startActivity (new Intent(getActivity(),Controller.class));
}else {
Toast.makeText(getActivity(), "not sucsses", Toast.LENGTH_SHORT).show();
}
}
});
}
});
I want to query the database so that when a user signs-in by Email and password, it returns all the data of that user from the database.
How can I make the key of userId in Auth equal to the userId in database and how do I use that feature?
tl;dr - In this case, store each user using their associated uid generated by Fireabase Auth instead of using a push ID.
In your situation the challenge with using a push ID to store info specific to each user is that when a user signs in you don't know the push ID you used when you first stored their info. To find a user each time they sign in you would have to search through every user in your database until you find a matching email/password to retrieve their correct profile information - the more users you have, the longer it would take to do the search. One alternative, which would probably be faster, is to use Firebase Authentication to create users and the Firebase Database to store any user specific information.
When you create a new user using Firebase Authentication it will assign a unique user id to the user that will be the same throughout the lifetime of the user. You then use the unique user id generated by Firebase Auth instead of a push ID to store user info in the database. The next time a user signs in you get the user's uid from Firebase Auth and use it to query the database to get that user's information.
Check the guide for how to create a password-based user and how to sign a user in using Firebase Auth: Create a password-based account
In order to use the unique uid generated by Firebase Auth I suggest a few changes to your code.
Update database structure
I suggest you update your database structure by adding a new location (maybe "allUsers") for use when you create/sign in users. Right now it looks like your are breaking up students into groups. If you need to keep this structure, for reasons beyond authentication, you can use it along with my suggestion. The reason for a single location which stores all users is that you need a definite location to query when a user signs in. When using Firebase Auth, without a single location which stores all users there is no way to tell what group a user belongs to when they first sign in. You would have to check every group in order to find a match and that may take a long time. Having a location which stores all users solves that problem. Also, the query for retrieving user information from that single location is much simpler. If you do need to keep a user's information in multiple places just be sure to update their information in both places if any changes occur.
Create a class variable used to distinguish between create user and sign in existing user.
If you use the same Activity to create a new user and sign in an existing user then create a boolean variable to make a distinction between when a new user is being created and when an existing user is signing in. It will be used later in the AuthStateListener. If you handle user creation in a separate activity from general sign in then you shouldn't need this variable because each activity would have a separate AuthStateListener.
boolean mIsNewUser = false;
Move the call to generateUser() from the create user completion listener to an AuthStateListener. Also move your database query from the sign in completion listener to the AuthStateLisener
Whenever you create a user successfully they will automatically be signed in too. So, if you move your call to generateUser() from the createUserWithEmailAndPassword OnCompleteListener to your AuthStateListener you can get access to the created user's uid. When signing an existing user move your database query to the AuthStateListener as well, again so we can access the user's uid. I'm also going to create a helper method for the database query called getExistingUserInfo. As an FYI, the onComplete() callback in the OnCompleteListeners for creating and signing in users gives you access to an AuthResult which according to the API has a method for returning the current user but the documentation says to access user information in the AuthStateListener.
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
if(mIsNewUser){
//call to generate user using Uid instead of pushID
generateUser(mUser, user.getUid());
} else{
getExistingUserInfo(user.getUid());
}
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
// ...
}
}
#Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
Update your generateUser() helper method to use the uid instead of a push ID:
I'm going to assume you want to keep you existing database structure and add the single location for all users as suggested. Based on this I've made a couple of changes to the write operation you were using in generateUser(). Mainly, instead of using setValue() to write to the database I'm using updateChildren(). By using updateChildren() we can take advantage of Firebase's ability to do atomic updates. This will allow us to write to the appropriate student group location and the location storing all users simultaneously. By taking this approach if the write operation to either location fails neither location will be updated. This way you can be certain if a student is added to a group they will also be listed in the allUsers location.
private void generateUser(User user, String uid)
{
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
String userType;
String allusers = "allUsers/" + uid;
Map<String, Object> newUserUpdate = new HashMap<>();
if (user.getUsername() != null) {
if (user.isSgl()) {
userType = user.getStudyGroupName() + "/" + "SGL" + "/" + uid;
} else {
userType = user.getStudyGroupName() + "/" + "Student" + "/" + uid;
}
newUserUpdate.put(userType, user.serialize());
newUserUpdate.put(allusers, user.serialize());
database.updateChildren(newUserUpdate);
}
}
Update database query to use new location which stores all users
As I mentioned above, by creating a single location for all users you can reduce the complexity of the query used to find a user's info when they sign in. Again, if you need to store users by group you can keep that but be sure to update both locations if a users info changes.
public void getExistingUserInfo(String uid){
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference("allUsers").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//get user data from dataSnapshot
Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
Log.v("himaAbousalem",userKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Set the variable used to distinguish between existing user sign in and new user creation in the create user completion listener
FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()) {
//set boolean used in the AuthListener
mIsNewUser = true;
Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
}
}
});

Firebase Android onAuthStateChanged called twice

I've start working with new Firebase SDK.
When I'm doing user login, I'm onAuthStateChanged method is being called twice with same state (etc. user sign in).
I'm sure I'm adding the AuthStateListener only once to the FirebaseAuth reference.
Any help?
Yes, and this is very annoying. This is due a registration call. Not only that, onAuthStateChanged is going to be called many times in many different states, with no possibility of knowing which state it is.
Documentation says:
onAuthStateChanged(FirebaseAuth auth)
This method gets invoked in the UI thread on changes in the authentication state:
Right after the listener has been registered
When a user is signed in
When the current user is signed out
When the current user changes
When there is a change in the current user's token
Here some tips to discover the current state:
Registration call: skip the first call with a flag.
User signed in: user from parameter is != null.
User signed out: user from parameter is == null.
Current user changes: user from parameter is != null and last user id is != user id from parameter
User token refresh: user from parameter is != null and last user id is == user id from parameter
This listener is a mess and very bugprone. Firebase team should look into it.
While the other answers provided here might do the job, I find managing a flag cumbersome and error-prone.
I prefer debouncing the event within short periods of time. It is very unlikely, maybe even impossible, for a user to login then logout within a period of 200ms let's say.
TLDR
Debouncing means that before handling an event, you wait to see if the same event is gonna fire again within a predefined period of time.
If it did, you reset the timer and wait again.
If it didn't, you handle the event.
This is an Android question, which is not my field, but I'm sure android provides some kind of tool that can help with the task.
If not, you can make one using a simple timer.
Here's how a Javascript implementation might look like:
var debounceTimeout;
const DebounceDueTime = 200; // 200ms
function onAuthStateChanged(auth)
{
if (debounceTimeout)
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(() =>
{
debounceTimeout = null;
handleAuthStateChanged(auth);
}, DebounceDueTime);
}
function handleAuthStateChanged(auth)
{
// ... process event
}
My workaround is to use a Boolean declared globally to flag if onAuthStateChanged has need called before.
private Boolean authFlag = false;
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull final FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
if(authFlag== false) {
// Task to perform once
authFlag=true;
}
}
}
};
Usually I want to setup the UI before adding the listener and repeat the setup any time the auth state changes (avoiding the initial double call). My solution is to enhance the boolean flag solution and keep track of the uid (not the token) of the last user, which may be null.
private FirebaseAuth firebaseAuth;
private String lastUid; // keeps track of login status and changes thereof
In onCreate, I get the auth instance and set the UI accordingly, before adding the listener in onStart
#Override
protected void onCreate(Bundle savedInstanceState){
...
firebaseAuth = FirebaseAuth.getInstance();
getUserSetUI();
...
}
where getUserSetUI sets lastUid according to the auth instance
private void getUserSetUI(){
lastUid = (firebaseAuth == null || firebaseAuth.getCurrentUser() == null) ?
null : firebaseAuth.getUid();
setUI(!(lastUid == null));
}
The listener checks to see if the state has actually changed
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth auth){
String uid = auth.getUid(); // could be null
if( (uid == null && lastUid != null) || // loggedout
(uid != null && lastUid == null) || // loggedin
(uid != null && lastUid != null && // switched accounts (unlikely)
!uid.equals(lastUid))){
getUserSetUI();
}
}
if (authStateListener == null) {
authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() == null) {
//Do anything here which needs to be done after signout is complete
FirebaseAuth.getInstance().removeAuthStateListener(this);
Log.d(TAG_, "logout");
finish();
} else {
}
}
};
}
FirebaseAuth.getInstance().removeAuthStateListener(this) should be called
try{
FirebaseAuth.getInstance().signOut();
FirebaseInstanceId.getInstance().deleteInstanceId();
}catch (Exception ex){
ex.printStackTrace();
}
When user logout from gmail then the user should also be logout from firebase. This is how I resolved this issue.

Categories

Resources