Firebase SDK Auth Package Trouble with Automatically Loading Scene Once Authenticated

I am stuck with a functionality of the Firebase SDK (Auth package) regarding the Scenes and it’s integration. Here’s how they work:

1st: Loading Scene
Here, I just added the FirebaseInit code EXACTLY as suggested by Patrick, which it’s only function is to call the next scene (Login/Register) once everything loads correctly.

2nd: Login/Register Scene
Here I do all the Login AND ALSO the register logic. I set up a button that alternates between the two (Activating the respective parent gameObject within the Canvas). Once the user log’s in, the 3rd scene comes into play.

3rd: App’s Main Screen Scene
Main Screen of the app, where the user can LOGOUT and return to the Login Scene.

Problem
I added the ‘LoadSceneWhenUserAuthenticated.cs’ in the 2nd Scene, and it works (kind of).
It actually does what it is supposed to. If I log in, quit the game without loging out, and open it again, it does come back directly to the 3rd scene. BUT some things are happening and they aren’t supposed to.
First
When I Sign Up a user, I call the method ‘CreateUserWithEmailAndPasswordAsync()’. Once it completes, it should activate the login screen and stay there, waiting for the user to fill in the password, but the ‘FirebaseAuth.DefaultInstance.StateChanged’ comes into play and forces the 3rd screen to be loaded, skipping several other steps that should be taken (email registration for example).
Second
As I mentioned in the end of number 1 above, if I try to log in to an account that does not have it’s email verified, it works! (due to the ‘LoadSceneWhenUserAuthenticated.cs’ which is added in the scene). Code:

var LoginTask = auth.SignInWithEmailAndPasswordAsync(_email, _password);
      LoginTask.ContinueWithOnMainThread(task =>
       {
         if (task.IsCanceled || task.IsFaulted)
         {
           Firebase.FirebaseException e =
             task.Exception.Flatten().InnerExceptions[0] as Firebase.FirebaseException;
           GetErrorMessage((AuthError)e.ErrorCode, warningLoginText);
           return;
         }
         if (task.IsCompleted)
         {
           User = LoginTask.Result;
            if (User.IsEmailVerified == true)
           {
             UIControllerLogin.instance.MainScreenScene();
           }
           else
           {
             warningLoginText.text = Lean.Localization.LeanLocalization.GetTranslationText($"Login/VerifyEmail");
           }

I know that it’s possible to fix this issue by adding an extra scene just before the login scene (as Patrick does in the youtube video) but it doesn’t make any sense in my app. It would actually only harm the UX of it.

Patrick’s Video:

I don’t understand what you are exactly saying. So best I can do is try to say what I do and see if you can in some way compare and we can figure out things.

So, I have a “splash screen” that is really just an empty scene that first gets loaded and sets up FirebaseApp.DefaultInstance, which it sounds like you have similar.

Then the second scene loads and a login/register account dialog is presented. A user first has to register their account.
Something along these lines. If the registration is successful, then I take them to the email verification. CreateAccountNew() simply handles displaying the verification dialog along with sending the verification email (after checking if the email was verified or not)

auth.CreateUserWithEmailAndPasswordAsync(emailRegIf.text, pwordRegIf.text).ContinueWithOnMainThread(task =>
        {
            if (task.IsCanceled)
            {
                CreateAccountCancelled();
            }
            else if (task.IsFaulted)
            {
                CreateAccountError(task.Exception.ToString());
            }
            else
            {
                user = task.Result;
                CreateAccountNew();
                TaskHandler.CleanTask(task);
            }
        });

Now, if a user is not verified and closes the app, it will always return to the verification screen and send a verification email. But if they are verified, it just bypasses all the dialogs and goes straight to the content. Note, it’s just 2 Unity scenes. The first to init Firebase, the second which has everything else.

Because Firebase creates a token for the user, the token remains unless it expires or you log the user out. I actually have a log out button.

auth.SignInWithEmailAndPasswordAsync(email, pword).ContinueWithOnMainThread(task =>
        {
            if(task.IsCanceled)
            {
                LoginCancelled();
                return;
            }
            if (task.IsFaulted)
            {
                LoginError(task.Exception.ToString());
                return;
            }

            user = task.Result;
            LoginSuccess();
        });

My login code is pretty much the same basic stuff, if the user is returning after they have logged out or a new device, the login dialog is used instead.

Exactly. I also have this.

This actually gave me a good idea! I will create another scene just containing the "You need to verify your email address . Going to explain it below.

May I ask HOW and WHERE you verify this? I mean, how do you know the user closed and opened the app? You verify this on awake/start of your second scene or on the “splash screen” scene?

So, you did this in a different way. If I understood correctly, you have everything in the same Scene and then you decide what to show the user by activating or deactivating the correct screen within the canvas.
I built this as recommended by Patrick’s video above. He uses a total of 5 scenes:

Loading, Main Screen (which you can choose Login or Register), Login, Register, Game.

I wanted to remove a few of them but maintaining the same logic (I did not think to do it as you did at the time) by using only 3:

Loading, Register/Login, Main Screen.

Here’s how he does the logic.
The Loading screen initializes the Firebase and redirects to the Main Screen.
If you are already logged in, the Main Screen redirects you to the Game Screen because of this code:

public class SkipLoginForAuthUsers : MonoBehaviour
{
  [SerializeField] private string _sceneToLoad = "Main Screen";
  private void Start()
  {
    FirebaseAuth.DefaultInstance.StateChanged += HandleAuthStateChanged;
    CheckUser();
  }

  private void OnDestroy()
  {
    FirebaseAuth.DefaultInstance.StateChanged -= HandleAuthStateChanged;
  }

  private void HandleAuthStateChanged(object sender, EventArgs e)
  {
    CheckUser();
  }

  private void CheckUser()
  {
    if (FirebaseAuth.DefaultInstance.CurrentUser != null)
    {
      SceneManager.LoadScene(_sceneToLoad);
    }
  }

In my case, that code is in my Login/Register scene, so whenever the State changes (as described in the post above), it automatically logs in.
I am going to test creating a new scene that contains the “You need to verify your email address” to see if it solves this issue. Will post the result soon.

I hope I could make you understand the problem a bit better.

Ah, I see what you are doing different. Ok, so funny thing is, I don’t use the statechanged event.

So, when the second scene loads, in Start, I call this method. Assuming that auth.CurrentUser has a value, which means they have logged in before and have already created their account. If it returns true, they are verified. If it’s false, then I display the verification dialog. If they had to log back in because it’s an uninstall or a new device, it still hits this method after log in to make sure they are verified.

    public bool CheckIfVerified()
    {
        return auth.CurrentUser.IsEmailVerified;
    }

I actually don’t think I watched the video above, I think I just poked around their sdk documentation and although I do have a statechanged method, I’m not actually doing anything with it.