Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Question Unity Player Accounts Login Every Time

Discussion in 'Authentication' started by Swerve-Studios, Jul 2, 2023.

  1. Swerve-Studios

    Swerve-Studios

    Joined:
    Jan 26, 2022
    Posts:
    3
    I have recently been playing around with the new Unity Player Accounts package and have finally got to the point where it is working in my code, with one caveat. Every time I close out of the app and reopen it, it prompts the user to log in again. If I select "Google", it logs me right back in. Not a huge deal but I feel like this is not the intended. Below is the general flow of my setup. I used the scripts from the sample scene:
    1. Game on first launch shows login screen with either Unity Auth or Anonymous
    2. Both options result in a player pref being created to indicate the first launch occurred, which skips the login selection screen
    3. On close out and subsequent boots, anonymous login is started on awake.
    4. Unity's auth windows pops up, you log in, then everything works as before
    I assume step 3 is where I went wrong, but the documentation is very brief and this was the only way I could get leaderboards and saves to work with Unity accounts. Do I need to be saving my auth token somewhere locally and calling it back on app launches?
     
  2. CtrlAltBees

    CtrlAltBees

    Joined:
    Mar 15, 2022
    Posts:
    3
    Was looking around for this answer myself but I think I found a solution (with a caveat)

    Basically, you want to store the PlayerAccountService.Instance.AccessToken into playerprefs to use to signin next time. This prevents the login window from popping up every time.

    Caveat is I have no idea how long that token stays valid for so you need to wrap that in a try/catch to re-sign in when that fails

    my code looks something like this


    Code (CSharp):
    1.  
    2.            string _cachedToken = PlayerPrefs.GetString("access_token");
    3.             if (!_cachedToken.IsEmpty())
    4.             {
    5.                 try
    6.                 {
    7.                     await AuthenticationService.Instance.SignInWithUnityAsync(_cachedToken);
    8.                 }
    9.                 catch (PlayerAccountsException ex)
    10.                 {
    11.                     Debug.LogException(ex);
    12.                     // if sign in using cached token fails, start sign in process again
    13.                     PlayerPrefs.DeleteKey("access_token");
    14.                     await PlayerAccountService.Instance.StartSignInAsync();
    15.                 }
    16.             } else
    17.             {
    18.                 await PlayerAccountService.Instance.StartSignInAsync();
    19.             }
    20.  
    21. ...
    22. // put this in start or somewhere early
    23.  
    24. PlayerAccountService.Instance.SignedIn += SignInWithUnity;
    25. ...
    26.  
    27.  
    28. // code from the sample/tutorial
    29. async void SignInWithUnity()
    30.     {
    31.         // this helper signs in with unity player accounts first and then uses that acces token to sign in to auth
    32.         try
    33.         {
    34.             //set playerprefs here after we login
    35.             PlayerPrefs.SetString("access_token", PlayerAccountService.Instance.AccessToken);
    36.             await AuthenticationService.Instance.SignInWithUnityAsync(PlayerAccountService.Instance.AccessToken);
    37.              
    38.             Debug.Log("SignIn with ugs is successful. token is " + AuthenticationService.Instance.AccessToken);
    39.         }
    40.         catch (AuthenticationException ex)
    41.         {
    42.             // Compare error code to AuthenticationErrorCodes
    43.             // Notify the player with the proper error message
    44.             Debug.LogException(ex);
    45.         }
    46.         catch (RequestFailedException ex)
    47.         {
    48.             // Compare error code to CommonErrorCodes
    49.             // Notify the player with the proper error message
    50.             Debug.LogException(ex);
    51.         }
    52.     }
     
  3. MiTschMR

    MiTschMR

    Joined:
    Aug 28, 2018
    Posts:
    524
    Why don’t you check for a session token and use the
    SignInAnonymously
    method if one exists? My flow looks like this:
    upload_2023-8-10_19-41-16.png
     
  4. socialtrens

    socialtrens

    Joined:
    Oct 23, 2017
    Posts:
    65
    I have the same problem. Every time I use UPA, android never caches the session token. If I go with your flow, it means that the player has to re-login via UPA every time, because the session token is not cached.

    Your flows work in the Unity editor, but not on Android device.

    Is there a way to get the session token and store it manually? Or maybe this is a bug?
     
    Last edited: Aug 14, 2023
  5. erickb_unity

    erickb_unity

    Unity Technologies

    Joined:
    Sep 1, 2021
    Posts:
    100
    The session token will be cached once your sign in to the authentication service after logging in to UPA.

    A simplified version of this would look something like:

    Code (CSharp):
    1.  
    2.     async Task SignInAsync()
    3.     {
    4.         if (AuthenticationService.Instance.SessionTokenExists)
    5.         {
    6.             await AuthenticationService.Instance.SignInAnonymouslyAsync();
    7.         }
    8.         else
    9.         {
    10.             PlayerAccountService.Instance.SignedIn -= OnPlayerAccountSignIn;
    11.             PlayerAccountService.Instance.SignedIn += OnPlayerAccountSignIn;
    12.             await PlayerAccountService.Instance.StartSignInAsync();
    13.         }
    14.     }
    15.  
    16.     async void OnPlayerAccountSignIn()
    17.     {
    18.         // Make sure this is called after successfully logging in to UPA and the next operation is successful
    19.         await AuthenticationService.Instance.SignInWithUnityAsync(PlayerAccountService.Instance.AccessToken);
    20.     }
    21.  
    Important to note that the flow where UPA login is called will finish outside of the initial task scope due to relying on the event being triggered.
     
  6. elevenab_unity

    elevenab_unity

    Joined:
    Mar 9, 2020
    Posts:
    15
    Does the SignInAnonymouslyAsync put me back into the same account as the UPA one? We have implemented in app purchases and would like to stick to only UPA
     
  7. MiTschMR

    MiTschMR

    Joined:
    Aug 28, 2018
    Posts:
    524
    Yes, because UPA is a linked identity to the account. If you sign in with UPA, you sign in to the account.
     
  8. rafalbudziszewski

    rafalbudziszewski

    Joined:
    May 29, 2019
    Posts:
    5
    Hi! A follow-up question. After executing
    Code (CSharp):
    1. await AuthenticationService.Instance.SignInAnonymouslyAsync();
    the
    Code (CSharp):
    1. PlayerAccountService.Instance.AccessToken
    remains null. How to get the access token for the cached player that has been auto logged in using SignInAnonymouslyAsync() ?
     
  9. MiTschMR

    MiTschMR

    Joined:
    Aug 28, 2018
    Posts:
    524
    You don't need it. If the user has already linked the account (or signed in with UPA the first time) the account is linked meaning the user does only need to use UPA for signing in if the cached session token is not available. When signing in with the cached session token (to the linked account) all the information is already there.

    If you however still need the access token, you need to again do the full sign in flow by calling PlayerAccountService.Instance.StartSignInAsync() etc.
     
  10. rafalbudziszewski

    rafalbudziszewski

    Joined:
    May 29, 2019
    Posts:
    5
    Thanks for a quick answer! It is very helpful!
    I wanted to use the access token to validate player's requests to the backend API. Or should I rather use AuthenticationService.Instance.AccessToken for that?
     
  11. MiTschMR

    MiTschMR

    Joined:
    Aug 28, 2018
    Posts:
    524
    What backend API, yours? Then yes, the second one is better, because the first one is for UPA only.
     
  12. rafalbudziszewski

    rafalbudziszewski

    Joined:
    May 29, 2019
    Posts:
    5
    Yes, this is my custom backend. Thanks! It is all clear now:)