React-native-firebase: Authentication not consistently persisting between sessions

Created on 13 Apr 2018  路  18Comments  路  Source: invertase/react-native-firebase

Issue

Some of our users (about 20% at this point) are losing their authentication between sessions. This includes terminating the app, or simply leaving it in the background for a while. The effected users have to re-login every session. For those 20% it is happening very frequently.

We offer both Facebook and Phone authentication. The problem is not discriminating between providers- both are experiencing this.

This is the onAuthStateChanged subscription code in our root component.

componentDidMount() {
    this.unsubscribeFromAuth = Firebase.auth().onAuthStateChanged((user) => {
        if (user && user.uid) {
            Firebase.auth().currentUser.getIdToken(true).then((token) => {
                if (!token) {
                    Helpers.logout(false);
                }
                else {
                    // init rest of app, send user to primary navigation component, etc...
                }
            })
            .catch(() => {
                Helpers.logout(false);
            });
        }
        else
            // send user to login screen
    });
}

componentWillUnmount() {
    if (this.unsubscribeFromAuth) {
        this.unsubscribeFromAuth();
        this.unsubscribeFromAuth = null;
    }
}

This is the logout method. If the parameter passed is false, an error message appears. The users getting logged out are not getting the error message. We have confirmed that the error message is functioning properly for other cases. This means that the logout() function isn't being called.

logout(intentional) {

    const logoutMessage = (intentional) ? 'You have been logged out.' : 'Sorry! Something went wrong and you were signed out.';
    // show logoutMessage

    Firebase.auth().signOut().then(() => {
        console.log('signed out');
        LoginManager.logOut();
        Firebase.analytics().logEvent('logout', { error: (intentional) ? 0 : 1 });
        return Storage.delete('credential');
    })
    .then(() => {
        console.log('deleted credential');
        // go to login screen
    })
    .catch((error) => {
        Log.error(error);
        // go to login screen
    });
}

It is possible that this is related to #962. There seems to be a correlation between the users affected by both issues, but it is not a 100% match by any means.

Environment

  1. Application Target Platform: iOS (we target both but do not have enough Android users to know if it is affecting Android)
  1. Development Operating System: macOS High Sierra
  1. Build Tools: Xcode 9.2, iOS 10.0 through 11.3
  1. React Native version: 0.54.4
  1. RNFirebase Version: 3.3.1
  1. Firebase Module: Authentication

Any ideas? Thanks!

General Needs Triage iOS Authentication Waiting for User Response

Most helpful comment

@chrisbianca can I ask what was the issue here? I'm encountering a similar issue with Firebase Auth in an Angular project and am having trouble narrowing it down.

All 18 comments

Actually, this seems to be affecting closer to 40% of our users, who have to re-login every time. This is a very UX-breaking issue that we're not sure how to deal with.

Can I ask why you're doing this part?

Firebase.auth().currentUser.getIdToken(true).then((token) => { ... }

When you say an error appears - how are you presenting this to your user?
I assume you have checked the error property in analytics to clarify that your assumption is correct?

Beyond that, I'm really not to sure what to suggest - ultimately onAuthStateChanged is a wrapper around the underlying functionality from the native SDK, although we do do some caching in the JS side.

Having a look at the code, there is currently the tiniest point of time where the user might incorrectly be reported as null: https://github.com/invertase/react-native-firebase/blob/master/lib/modules/auth/index.js#L106

You'll notice that we set _authResult to true, before creating the User. If, in that instant, a new subscription to onAuthStateChanged was created then it would send null, rather than the User object (https://github.com/invertase/react-native-firebase/blob/master/lib/modules/auth/index.js#L137) which would be incorrect. This should be a tiny fraction of time, but I guess it's possible - I'm just surprised that it would lead to so many people being affected...

I can certainly fix this, or you could manually change the file in your build to move the user creation before the setting of the _authResult and do another release to see whether this makes any difference?

I'm assuming you haven't been able to reproduce locally at all?

Can I ask why you're doing this part?

We call Firebase.auth().currentUser.getIdToken(true).then((token) => { ... } because after the user is logged in we immediately need the token to attach to our location service HTTP POST URL so that its requests are authenticated.

When you say an error appears - how are you presenting this to your user?

If there is ever an explicit error with authentication, we log the user out, send them to the login screen, and display an error message. This mostly applies to edge cases where the authentication may expire or be otherwise invalidated mid-session. However, in this case the user is sent to the login screen without any error message after having authenticated in a recent session.

When the app boots, we subscribe to onAuthStateChanged and then wait for the callback. If the callback indicates they are authenticated, then they get sent into the app. If they're not authenticated, they start on the login screen. The latter is happening for these users. They get no error message, they just get sent to the login screen. This suggests that the user parameter could be coming back as undefined.

I assume you have checked the error property in analytics to clarify that your assumption is correct?

When this happens, the logout function is not called, therefore we receive no analytics data from the logout event.

I'm assuming you haven't been able to reproduce locally at all?

I have not been able to reproduce this myself yet. I'm only going off of reports from our users. It seems to consistently affect a select number of users. In other words, only X% of devices/users are affected, rather than X% of sessions.

I'll have a chat with @Salakar and talk through this change to confirm it won't affect anything else then try and get a release out.

Is there any pattern to the type of devices that are experiencing this issue? Are they newer, faster devices? Or older, slower devices? Or is it just random? Seems odd that it's the same users/devices that are seeing the issue rather than just a percentage of sessions unless there is some correlation in the performance of the devices...

I've just published v4.0.6 which has this possible fix in - it would be great if you're able to roll this out and see whether it addresses your issues?

Sounds good. We're shipping a new version in the next 36 hours, we'll update to 4.0.6 and see what happens.

Perfect, let us know.

@wbattel4607 Have you had a chance to get this released and tested?

We've released it and are monitoring for any changes in behavior. I'll let you know what we find.

Perfect, thanks. Fingers crossed!

@wbattel4607 How's this looking?

We've been getting fewer reports, although I am hesitant to say it's resolved yet. If you would like to close the issue, go ahead. If we should discover the problem persists we can create a new issue and reference this one.

Will do, thanks.

@chrisbianca can I ask what was the issue here? I'm encountering a similar issue with Firebase Auth in an Angular project and am having trouble narrowing it down.

currently have the same issue in my application. i use firestore listeners to stream data into the application but after being left in the background for lets say 2 hours or more and going back to the application the app no longer recieves data from firestore. User has to log out and login back with firebase auth to get it working again. which indicates to me that its an auth issue

Any updates on this?

@ankitbishtapollo this issue was opened in 2018, and closed in 2018. Why would there be any updates on a 2 year stale issue? If you have problems with current stable versions please open a new issue and respect the template, then people can try to help

Ok @mikehardy will raise a new ticket. You can close this

Was this page helpful?
0 / 5 - 0 ratings