0

My goal for this app is to have persistent log in, so that the user of my Flutter app needs to sign in only once (unless they sign out) and whenever my Flutter app restarts, they do not need to log back in. I saw many examples with using Firebase Authentication and the .currentUser() method, but I am still having to log in every time I restart the app. I have tested this on the simulator (ios) and on my physical iphone while running debug mode on xCode (usb connection). Is it possible that I cannot test this functionality this way? Because I do see a message pop up on both android studio and xCode terminals that mention lost connection to device or stopped running because of the restarting. If that's the case, how can I test that persistent log in is working?

If that isn't the case, what am I doing wrong?? I've included the code below. This is happening within a stateful widget, of course.

final _auth = FirebaseAuth.instance;

checkIfCurrentUserExists() async {
  try {
    await _auth.currentUser().then((user) {
      print('this is the user $user');
      if (user != null && user.email != null) {
        userIsLoggedIn = true;
        // this works fine!
      }
    });
  } catch (e) {
   print('current user was not found $e');
   // this works fine!
  }
}

// called inside initState() 
setClientOnLoad() async {
  await Spryte.checkIfCurrentUserExists();
  var doesCurrentUserExist = userIsLoggedIn;
  var currentUser = await returnCurrentUser();
  if (doesCurrentUserExist == false) {
    //if user is not authenticated, set anonymous user
    // this works fine!
  } 
  else {
    //print('current user does exist');
    await foo(currentUser.uid);
    // 'foo' is meant to retrieve some data about the client on loading of the app
    // so that the user doesn't have to log in every time the app restarts
    // but for some reason it's not working for me
  }
}
2
  • what's the implementation for the returnCurrentUser() function? Commented Mar 5, 2020 at 22:44
  • @AlfredJingle it simply returns the current user with ''' return await _auth.currentUser(); ''' Commented Mar 6, 2020 at 15:37

2 Answers 2

2

I have got the same problem. I was able to sign in but when restarting the app, I was getting another random UID.

It might sound stupid, but make sure you are not calling signInAnonymously(); at any point in your app without checking if there is already a current user.

This was my problem, I was always signing in anonymously at every app restart.

Here is what I did from my starting app page (which takes care of setting up the app including the user):

Future<FirebaseUser> signInAnonymously() async {
    AuthResult result = await _auth.signInAnonymously();
    final FirebaseUser user = result.user;

    assert(user != null);
    assert(await user.getIdToken() != null);

    return user;
  }

And here is the checking method:

Future<FirebaseUser> tryToFetchUser() async {
    var user = await _auth.currentUser();
    if (user == null) {
      user = await FirebaseAuth.instance.onAuthStateChanged.first;
    }
    if (user == null) {
      user = await signInAnonymously();
    }
    return Future.value(user);
  }

I hope it will help some of you and avoid wasting time on stupid mistakes as I did!

Sign up to request clarification or add additional context in comments.

Comments

1

You r calling setClientOnLoad() which is async inside init() method & other app navigation depends on this method so u need wrap all your async stuff in FutureBuilder(). if not then build() method ll be called before complete execution of setClientOnLoad() e.g. :-

FutureBuilder(
  future: setClientOnLoad(),
  builder: (context, AsyncSnapshot<R> snapshot) {
    if (snapshot.data == null) {
      return Center(child: CircularProgressIndicator());
    }
    // after executing method completely
  },
);

3 Comments

Hi, thanks for your reply. I have tried this way: in the same stateful widget that my above code is in, Widget build(BuildContext context { return FurtureBuilder( future: setClientOnLoad(), builder: (context, AsyncSnapshot <dynamic> snapshot) { if (snapshot.data == null) { return Center(child: CircularProgressIndicator()); } return Scaffold() } ) }) and that just shows the circular progress indicatory for a while till it freezes. Never shows the scaffold
use scaffold then future builder & after u got data then show the required output on that commented line in answer above
Thanks, that worked for logging in the user, but I already had that functionality. With the above code, I was trying to get the user to stay logged in, even after closing the app, until the user decides to log out. From what I read on multiple websites, _auth.currentUser() is supposed to retrieve a cached user from firebase; the most recently logged in user. Instead, it is returning null? My goal is to have users remain logged in after closing the flutter app. Is this not the right way to go about it? I've also tried using shared preferences and it did not work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.