firebaseunity-game-enginefirebase-authenticationfirebase-admin

Firebase Auth - how to refresh access token without current user object


I am accessing my backend with an access token obtained from firebase auth the following way:

  1. login via email & password
  2. receive the current user object
  3. obtain the token from the user object
  4. store the token locally to allow furher access to my backend (which uses firebase admin to validate the token)

This works, as long as the access token is stale. This may as well work, if the application remains open and an 403 due to an expired token can be catched (I can just reuse the current user object to obtain a new token). However, if the token expires while the app is closed, opening it again (no more user object) results in forcing the user to reenter its credentials, does it?

One way that came to my mind was using the custom tokens functionality: I could send the refresh token to the client after a login, which then stores it and would use it to log in (in an automatic manner) instead of using the credentials. But the word "custom" made me think that I am on the wrong way somehow. There surely must be an easy way to do this with the intended functions.

Can any one help me out with this?

Greetings,

Codehai


Solution

  • Using this listener refreshes the token automatically, won't work in editor.

    For my code to work, somehow I have to add TaskScheduler.FromCurrentSynchronizationContext() on all Firebase Tasks..

     void Start()
        {
          auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
          auth.IdTokenChanged += IdTokenChanged;
        }
    
    void IdTokenChanged(object sender, System.EventArgs eventArgs)
        {
            Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
            if (senderAuth == auth && senderAuth.CurrentUser != null && !fetchingToken)
            {
                fetchingToken = true;
                senderAuth.CurrentUser.TokenAsync(true).ContinueWith(
                    task =>
                    {
    
                        if (task.IsCanceled)
                        { 
                            Debug.Log("canceled");
                        }
    
                        if (task.IsFaulted)
                        {
                            foreach (var errors in task.Exception.InnerExceptions)
                            {
                                Debug.Log(errors.InnerException.Message);
                            }
                        }
    
                        Debug.Log("New Token: " + task.Result);
                        // save task.Result
                        fetchingToken = false;
                    }, TaskScheduler.FromCurrentSynchronizationContext());
            }
        }
    
    private void OnDestroy()
        {
            auth.IdTokenChanged -= IdTokenChanged;
        }