1

If I delete a user directly from my Firebase Console, this user still have a valid data on my Android Device.

Of course if I then access firebase resources (e.g. Realtime Database) that doesn't work as expected.

But this cause a misalignment in the client because if I have valid user data I show a specific UI for authenticated users, instead if I have no user authenticated I show another UI.

How could I manage this situation?

EDIT: what I've found, but I don't now if that is okay or is a workaround is to call the reload() on my FirebaseUser.

From the documentation this should throw and Exception but that doesn't happen. What happens is that my user reference become null:

private void initializeUI(FirebaseUser user) {
        user.reload();
        if (null != user) {
            mUser = user;
        } else {
           // User must have been disabled or deleted from console
        }

I call initializeUI here:

@Override
public void onAuthStateChanged(@NonNull final FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();

                if (null != user) {
                    initializeSignInUI(user);
                } else {
                    initializeSignOutUI();
                }
            } 

As a more info:

If I open my App the user is still alive on client side. The trigger for authentication user is fired and here, with my code above I can manage the situation. But I don't know if this is actually a workaround or the right practice.

EDIT 2 Just to reformulate my question:

This method is working well:

public boolean validUser(FirebaseUser user) {
        boolean validUser = false;
        if (null != user) {
            try {
                user.reload();
                if (null != user) {
                    validUser = true;
                }
            } catch (Exception e) {
            //} catch (FirebaseAuthInvalidUserException e) {
                validUser = false;
            }
        }
        return validUser;
    }

Could I consider that a valid solution or there'a another best practice? This solution works only with FirebaseAuth without the need of interact with FirebaseDatabase. I can call this method every time have to check the user authentication.

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
Cod3Flu3nc3
  • 147
  • 1
  • 13
  • do you have a user node in the database? – Peter Haddad Feb 19 '18 at 08:54
  • After login (the user is created in the Auth section) I create a user node on my database, yes. But when I delete from the console I've a trigger that clean up also my DB. – Cod3Flu3nc3 Feb 19 '18 at 08:55
  • 1
    Possible duplicate of [Firebase Authentication State Change does not fire when user is disabled or deleted](https://stackoverflow.com/questions/38345085/firebase-authentication-state-change-does-not-fire-when-user-is-disabled-or-dele) – AL. Feb 19 '18 at 09:02
  • @AL. My scenario is quite different. I've edited my answer to explain better the scenario. If I've an already authenticated user in my device and I delete it from my console what I'm asking here is not how to secure my DB from him/her but I to check that It has been deleted to update my UI and secondary to update my environment for no user authenticated. – Cod3Flu3nc3 Feb 19 '18 at 09:08
  • @AL. So I think this not a duplicated. I'm asking for something more. – Cod3Flu3nc3 Feb 19 '18 at 09:10
  • @AL. Do you thinks it's better I cancel my question and I post an answer in the 'possible' duplicated one? I thought should be better to ask another one because I've found a different way but I don't know if is a workaround or a valid method. So express your opinion ;) – Cod3Flu3nc3 Feb 19 '18 at 09:58
  • yes delete this question @Cod3Flu3nc3 and post answer there then if you found it – Peter Haddad Feb 19 '18 at 10:07
  • @PeterHaddad okay! – Cod3Flu3nc3 Feb 19 '18 at 10:09
  • @PeterHaddad I cannot do it... 'cause there are answers... The system didn't let me do it. – Cod3Flu3nc3 Feb 19 '18 at 10:10
  • @Cod3Flu3nc3 ohh okay, did you see my answer as a workaround to the problem? You will be able to retrieve the data of the user in the beginning and according to the situation update the visibility of the UI – Peter Haddad Feb 19 '18 at 10:11
  • @PeterHaddad yes, but my solution only deals with FirebaseAuth, it seems more slim to me. The matter is: this solution works well in all situation... so I prefer my solution. Otherwise I prefer yours. – Cod3Flu3nc3 Feb 19 '18 at 10:18
  • @PeterHaddad Okay, thanks. Anyway this has been a really good brainstorming! I'm sure we have added some new interesting point of view to this scenario! Thanks again. – Cod3Flu3nc3 Feb 19 '18 at 10:29

2 Answers2

4

If your user is logged in, in your applicaiotn and you are manually deleting it from the Firebase Console, the user will remain active, till the token will be refreshed. So for about at most an hour, the user will remain authenticated. So if you want to restrict the access of a user instantly, you need to sign him out.

But there is another workaround, in which you can create a new node in your Firebase database named usersToLogOut and add there all the user ids as keys and the boolean true as a value. The database should look like this:

Firebase-root
     |
     --- usersToLogOut
             |
             --- uid1: true
             |
             --- uid2: true

The next step, when you detele that account manually, you need to add the uid of the user under this node. You need to also to use, Firebase Security Rules, to revoke access for unauthorized users. The rules should look like this:

{
  "rules": {
    "usersToLogOut": {
      ".read": true,
      ".write": false
    },
    "posts": {
      ".read": "auth != null && !root.child('usersToLogOut').child(auth.uid).exists()"
    }
  }
}

Edit1:

According to your edit, you say: what I'm asking here is not how to secure my DB from him/her but I to check that It has been deleted but this the easier way way in which you can achieve this, by using the rules above. If you delete the user manually from the console this doesn't mean that you are deleteing everything with it, including database records. You need to do this your self. So the simplest way is to use rules.

Additionally, if you delete all user records, then you can add a listener and force him sign-out but this means that you need to search into you database for all records and remove them accordingly. The first solution is easier, because you only need to add a single record in your database and that's it!

Edit2:

When you are deleting a user manually this doesn't mean that the firebaseUser object will be null, so to check for nullity it does not make any sense because the user will still be authenticated till the next token refresh. So to solve this, you need to use Firebase rules to restrict the access.

So your code will always work. What I was trying to say is that between the time in which you delete the user manually from the console and the time in which you get refreshed token, it can be up to an hour in which the user will still have access to your app, even if he is deleted. To stop this, for that hour, you need to use the solution above.

Edit3 according to OP's comments:

Your code works well and will always work but the problem is, even if you delete the user from the console he will still have accees to the database till the next token refresh. And yes, the user will be able to access the database. That token will be valid for about an hour and if you do not want that, you can restrict using the security rules and in that hour the user not have access anymore.

With other words if you delete it also from client side and if it is not valid and if someone else has 'stolen' this token could use it to access the DB. Not the user who is using your app but someone that could have stolen that token.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Hi Alex, if you look and my other edit I've build .a method that doesn't inlcude access the DB but on is dealing only with FirebaseAuth. I have already from DB side all triggers that clean up the deleted users. – Cod3Flu3nc3 Feb 19 '18 at 10:08
  • I saw this and that's why I answered you accordingly. When you are deleting a user `manually` this doesn't mean that the `firebaseUser` object will be `null`, so to check for nullity it does not make any sense because the user will still be authenticated till the next token refresh. So to solve this, you need to use Firebase rules to restrict the access. – Alex Mamo Feb 19 '18 at 10:14
  • So you are telling me that the code above works well but there could be chances for which it couldn't work? Because up to now in my app this code is working. – Cod3Flu3nc3 Feb 19 '18 at 10:17
  • It seems like the .reload() refresh also the user token. – Cod3Flu3nc3 Feb 19 '18 at 10:20
  • No, your code will always work. What I was trying to say is that between the time in which you delete the user manually from the console and the time in which you get refreshed token, it can be up to an hour in which the user will still have access to your app, even if he is deleted. To stop this, for that hour, you need to use the solution above. – Alex Mamo Feb 19 '18 at 10:21
  • Did you understood now? – Alex Mamo Feb 19 '18 at 10:23
  • Yep, that's a good point. So if you wanna reformulate the answer giving that explanation I guess I will accept it ;) Explain well that point. This is a good subject from a security point of view in which someone could impersonate my deleted user. But as you have said the code works well. But as for the app itself if i alway check for a fresh token my app will always works. Ain't it? – Cod3Flu3nc3 Feb 19 '18 at 10:25
  • Wait, wait :) I mean. The above code works well. So the user using the 'official' app cannot access the DB because I check if the user is valid and I do a restrict the access from a client side point of view. I did't really check if I can still access the DB indead. Anyway, if it's like you say, that the token could by valid for an hour, this situation could only occurs if someone 'impersonate' my user from an 'attacking' app. – Cod3Flu3nc3 Feb 19 '18 at 10:35
  • Yes, that above code works well and will always work but the problem is, even if you delete the user from the console he **`will`** still have accees to the database till the next token refresh. Yes, user will be able to access the database. Yes, that token will be valid for about an hour and if you do not want that, you can restrict using the security rules and in that hour the user not have access anymore. Is it clear know? – Alex Mamo Feb 19 '18 at 10:40
  • It was clear also the first time ;) But you said the user using the app could access the database. But the user using the official app, if I coded well, actually can't because I delete it also from client side if it is not valid (my function, remember?). But if someone else has 'stolen' this token could use it to access the DB. It's that that I would highlight in your answer. Not the user using my app but someone that could have stolen the token. – Cod3Flu3nc3 Feb 19 '18 at 10:48
  • It's just a metter of 'scenario' what you say it's right. How could I explain myself? If you want we could also chat... but I'm still not abile to do it :D – Cod3Flu3nc3 Feb 19 '18 at 10:49
  • Change the answer with this scenario and I'll will accept it for sure! – Cod3Flu3nc3 Feb 19 '18 at 10:56
2

To check if the user has been deleted in the database, then try this:

FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
String useruid=user.getUid();
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("users").child(useruid);
ref.addValueEventListener(new ValueEventListener(){
 @Override
public void onDataChange(DataSnapshot dataSnapshot) {
  if(!dataSnapshot.exists()){
     //update UI
 }
}

  @Override
 public void onCancelled(FirebaseError firebaseError) {


   }
});

The above will check if the useruid is there or not, and since you are deleting also from the database, then it will not be found and then you can update the UI using setVisiblity() Assuming you have this in DB:

    users
      useruid
         username: userx
         email: userx@gmail.com
      useruid
         username: usery
         email:usery@gmail.com
Peter Haddad
  • 78,874
  • 25
  • 140
  • 134