If user is signed in, LinkWithGooglePlayGamesAsync always returns AccountAlreadyLinked

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.

    async Task SignInWithGooglePlayGamesAsync(string authCode)
    {
        if(AuthenticationService.Instance.IsSignedIn)
        {
            try
            {
              await AuthenticationService.Instance.LinkWithGooglePlayGamesAsync(authCode);
              m_PlayerIdText.text = AuthenticationService.Instance.PlayerInfo.Id;
              Debug.Log("LinkWithGooglePlayGamesAsync is successful.");
            }
            catch (AuthenticationException ex) when (ex.ErrorCode == AuthenticationErrorCodes.AccountAlreadyLinked)
            {
              // Prompt the player with an error message.
              Debug.LogError("This user is already linked with the account. Log in instead.");
            }

            catch (AuthenticationException ex)
            {
              // Compare error code to AuthenticationErrorCodes
              // Notify the player with the proper error message
              Debug.LogError("LinkWithGooglePlayGamesAsync is unsuccessful.");
              Debug.LogException(ex);
            }
            catch (RequestFailedException ex)
            {
              // Compare error code to CommonErrorCodes
              // Notify the player with the proper error message
              Debug.LogError("LinkWithGooglePlayGamesAsync is unsuccessful.");
              Debug.LogException(ex);
            }
        }

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

Yes Im using AuthenticationService.Instance.SignInAnonymouslyAsync()

    async void Awake()
    {
         await UnityServices.InitializeAsync();
         Debug.Log($"Cached Session Token Exist: {AuthenticationService.Instance.SessionTokenExists}");
         await SignInCachedUserAsync();
    }

     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;
                          m_PlayerNameText.text = Social.localUser.userName;
                          m_PlayerIdText.text = Social.localUser.id;
                          task = SignInWithGooglePlayGamesAsync(code);
                });
            }
            else
            {
                Debug.Log("Login Unsuccessful");
                     Debug.Log(success);
            }
                m_StateText.text = success.ToString();
        });
    }

    async Task SignInCachedUserAsync()
    {
         // Check if a cached user already exists by checking if the session token exists
         if (!AuthenticationService.Instance.SessionTokenExists)
         {
              // if not, then do nothing
              Debug.Log("SignInCachedUserAsync SessionToken doesn't exists");
              return;
         }

         // Sign in Anonymously
         // This call will sign in the cached user.
         try
         {
              await AuthenticationService.Instance.SignInAnonymouslyAsync();
              Debug.Log("SignInCachedUserAsync succeeded!");

              // Shows how to get the playerID
              m_PlayerIdText.text = AuthenticationService.Instance.PlayerInfo.Id;
              Debug.Log($"PlayerID: {AuthenticationService.Instance.PlayerId}");
         }
         catch (AuthenticationException ex)
         {
              // Compare error code to AuthenticationErrorCodes
              // Notify the player with the proper error message
              Debug.LogError("SignInCachedUserAsync is unsuccessful.");
              Debug.LogException(ex);
         }
         catch (RequestFailedException ex)
         {
              // Compare error code to CommonErrorCodes
              // Notify the player with the proper error message
              Debug.LogError("SignInCachedUserAsync is unsuccessful.");
              Debug.LogException(ex);
          }
    }
1 Like

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.

1 Like

Hi there,

I verified with the developers. It seems like you may be on a wrong flow.
The following documentation may bring you back on the right track
https://docs.unity.com/authentication/en/manual/IdentityManagement#Handle_account_linking_conflicts

You can also use the following code to check if the account is already signed in
https://docs.unity.com/authentication/en/manual/PlayerInfo
This will return the player’s creation time and the linked identities.

Let me know if this helps

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

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.).

[quote=“newlife”, post:6, topic: 907067]
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
[/quote]

Hey I’m having the same issue could you tell me how you resolved it? would greatly appreciate it thank you

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);
}
}
}
```