Search Unity

Resolved If user is signed in, LinkWithGooglePlayGamesAsync always returns AccountAlreadyLinked

Discussion in 'Authentication' started by newlife, Jan 24, 2023.

  1. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    1,081
    Hello, Im testing this code on my Android device. Essentially it checks if the user is already signed in and in the case, LinkWithGooglePlayGamesAsync is called.
    If the user is signed in, LinkWithGooglePlayGamesAsync always returns AccountAlreadyLinked error.
    PS: I couldn't find any way to check if the account is already linked.

    Code (CSharp):
    1.     async Task SignInWithGooglePlayGamesAsync(string authCode)
    2.     {
    3.         if(AuthenticationService.Instance.IsSignedIn)
    4.         {
    5.             try
    6.             {
    7.               await AuthenticationService.Instance.LinkWithGooglePlayGamesAsync(authCode);
    8.               m_PlayerIdText.text = AuthenticationService.Instance.PlayerInfo.Id;
    9.               Debug.Log("LinkWithGooglePlayGamesAsync is successful.");
    10.             }
    11.             catch (AuthenticationException ex) when (ex.ErrorCode == AuthenticationErrorCodes.AccountAlreadyLinked)
    12.             {
    13.               // Prompt the player with an error message.
    14.               Debug.LogError("This user is already linked with the account. Log in instead.");
    15.             }
    16.  
    17.             catch (AuthenticationException ex)
    18.             {
    19.               // Compare error code to AuthenticationErrorCodes
    20.               // Notify the player with the proper error message
    21.               Debug.LogError("LinkWithGooglePlayGamesAsync is unsuccessful.");
    22.               Debug.LogException(ex);
    23.             }
    24.             catch (RequestFailedException ex)
    25.             {
    26.               // Compare error code to CommonErrorCodes
    27.               // Notify the player with the proper error message
    28.               Debug.LogError("LinkWithGooglePlayGamesAsync is unsuccessful.");
    29.               Debug.LogException(ex);
    30.             }
    31.         }
     
  2. SebT_Unity

    SebT_Unity

    Unity Technologies

    Joined:
    Jun 21, 2021
    Posts:
    282
    Hi newlife,
    Thanks for posting on the forums.

    Are you allowing the user to be created anonymously? If not and you are logging in to Google Play Games directly that may explain the message you are getting. You would not need to Link With GooglePlayGames in this scenario.

    Best.
    Seb
     
  3. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    1,081
    Yes Im using
    AuthenticationService.Instance.SignInAnonymouslyAsync()


    Code (CSharp):
    1.     async void Awake()
    2.     {
    3.          await UnityServices.InitializeAsync();
    4.          Debug.Log($"Cached Session Token Exist: {AuthenticationService.Instance.SessionTokenExists}");
    5.          await SignInCachedUserAsync();
    6.     }
    7.    
    8.      void Start(){
    9.         PlayGamesPlatform.Activate();      
    10.      }
    11.  
    12.     public void LoginGooglePlayGames()
    13.     {
    14.         PlayGamesPlatform.Instance.Authenticate((success) =>
    15.         {
    16.             if (success == SignInStatus.Success)
    17.             {
    18.                 Debug.Log("Login with Google Play games successful.");
    19.  
    20.                 PlayGamesPlatform.Instance.RequestServerSideAccess(true, code =>
    21.                 {
    22.                     Debug.Log("Authorization code: " + code);
    23.                           m_SessionText.text = code;
    24.                           m_PlayerNameText.text = Social.localUser.userName;
    25.                           m_PlayerIdText.text = Social.localUser.id;
    26.                           task = SignInWithGooglePlayGamesAsync(code);
    27.                 });
    28.             }
    29.             else
    30.             {
    31.                 Debug.Log("Login Unsuccessful");
    32.                      Debug.Log(success);
    33.             }
    34.                 m_StateText.text = success.ToString();
    35.         });
    36.     }
    37.  
    38.     async Task SignInCachedUserAsync()
    39.     {
    40.          // Check if a cached user already exists by checking if the session token exists
    41.          if (!AuthenticationService.Instance.SessionTokenExists)
    42.          {
    43.               // if not, then do nothing
    44.               Debug.Log("SignInCachedUserAsync SessionToken doesn't exists");
    45.               return;
    46.          }
    47.  
    48.          // Sign in Anonymously
    49.          // This call will sign in the cached user.
    50.          try
    51.          {
    52.               await AuthenticationService.Instance.SignInAnonymouslyAsync();
    53.               Debug.Log("SignInCachedUserAsync succeeded!");
    54.  
    55.               // Shows how to get the playerID
    56.               m_PlayerIdText.text = AuthenticationService.Instance.PlayerInfo.Id;
    57.               Debug.Log($"PlayerID: {AuthenticationService.Instance.PlayerId}");
    58.          }
    59.          catch (AuthenticationException ex)
    60.          {
    61.               // Compare error code to AuthenticationErrorCodes
    62.               // Notify the player with the proper error message
    63.               Debug.LogError("SignInCachedUserAsync is unsuccessful.");
    64.               Debug.LogException(ex);
    65.          }
    66.          catch (RequestFailedException ex)
    67.          {
    68.               // Compare error code to CommonErrorCodes
    69.               // Notify the player with the proper error message
    70.               Debug.LogError("SignInCachedUserAsync is unsuccessful.");
    71.               Debug.LogException(ex);
    72.           }
    73.     }
     
    SebT_Unity likes this.
  4. SebT_Unity

    SebT_Unity

    Unity Technologies

    Joined:
    Jun 21, 2021
    Posts:
    282
    Hi there,
    Sorry for the late reply, I have reproduced the issue locally currently speaking with the developers to see what is the best way to get around this.
     
    Julian-Unity3D likes this.
  5. SebT_Unity

    SebT_Unity

    Unity Technologies

    Joined:
    Jun 21, 2021
    Posts:
    282
  6. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    1,081
    Ok so it seems that for some reason in my case the account was already linked, even for a new install from scratch.
    So which is the correct way to check if the account is already linked to Google Play Games?

    Im using

    playerInfo.GetGooglePlayGamesId() == null 
     
  7. MiTschMR

    MiTschMR

    Joined:
    Aug 28, 2018
    Posts:
    494
    The PlayerInfo class has an
    Identities
    property that returns a list of identities. You may find something in there, though I don't know in which format that is represented (what values are used etc.).
     
  8. unity_84DFA275A8356FBA8C99

    unity_84DFA275A8356FBA8C99

    Joined:
    Jun 6, 2022
    Posts:
    7
    Hey I'm having the same issue could you tell me how you resolved it? would greatly appreciate it thank you
     
  9. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    1,081
    Im doing like this:

    using GooglePlayGames;
    using GooglePlayGames.BasicApi;
    using UnityEngine;
    using UnityEngine.UI;
    using System.Threading.Tasks;
    using Unity.Services.Core;
    using Unity.Services.Authentication;

    public class GooglePlayGamesSignInExample : MonoBehaviour
    {
    [SerializeField]
    Text m_StateText;
    [SerializeField]
    Text m_SessionText;
    [SerializeField]
    Text m_PlayerIdText;
    Task task;

    async void Awake(){
    await UnityServices.InitializeAsync();
    }

    void Start(){
    PlayGamesPlatform.Activate();
    }

    public void LoginGooglePlayGames()
    {
    PlayGamesPlatform.Instance.Authenticate((success) =>
    {
    if (success == SignInStatus.Success)
    {
    Debug.Log("Login with Google Play games successful.");

    PlayGamesPlatform.Instance.RequestServerSideAccess(true, code =>
    {
    Debug.Log("Authorization code: " + code);
    m_SessionText.text = code;
    task = SignInWithGooglePlayGamesAsync(code);
    });
    }
    else
    {
    // Disable your integration with Play Games Services or show a login button
    // to ask users to sign-in. Clicking it should call
    // PlayGamesPlatform.Instance.ManuallyAuthenticate(ProcessAuthentication).
    Debug.LogError("Login Unsuccessful");
    Debug.LogError(success);
    }
    m_StateText.text = success.ToString();
    });
    }

    async Task SignInWithGooglePlayGamesAsync(string authCode)
    {
    try
    {
    await AuthenticationService.Instance.SignInWithGooglePlayGamesAsync(authCode);
    m_PlayerIdText.text = AuthenticationService.Instance.PlayerInfo.Id;
    Debug.Log("SignInWithGooglePlayGamesAsync is successful.");
    }
    catch (AuthenticationException ex)
    {
    // Compare error code to AuthenticationErrorCodes
    // Notify the player with the proper error message
    Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
    // Compare error code to CommonErrorCodes
    // Notify the player with the proper error message
    Debug.LogException(ex);
    }
    }
    }