# Issue with AuthenticateAppleAsync from quick login

**URL:** <https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034>\
**Category:** Local Setup\
**Created:** [October 7, 2020, 7:45pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034 "2020-10-07T19:45:55Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 7, 2020, 7:45pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/1 "2020-10-07T19:45:55Z")

</div>

We are successfully linking apple id with user nakama accounts, but when returning to the app after initial account creation, we get the apple quick login flow, and when we try to AuthenticateAppleAsync with the returned credentials, we get server error:401 and ApiResponseException: Server key invalid. Any idea why this would fail?

Nakama 2.13 Unity SDK 2.6.0

---

<div class="post-metadata">

**Author:** ![lugehorsam](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/lugehorsam/32/314_2.png) [@lugehorsam](https://forum.heroiclabs.com/u/lugehorsam)\
**Post date:** [October 7, 2020, 8:13pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/2 "2020-10-07T20:13:18Z")

</div>

@oscargoldman does the key used by the client match the configured key on the server?

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 7, 2020, 8:23pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/3 "2020-10-07T20:23:50Z")

</div>

which key are we referring to? the socket.server\_key used to initialize the Client object?

---

<div class="post-metadata">

**Author:** ![lugehorsam](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/lugehorsam/32/314_2.png) [@lugehorsam](https://forum.heroiclabs.com/u/lugehorsam)\
**Post date:** [October 7, 2020, 8:46pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/4 "2020-10-07T20:46:00Z")

</div>

@oscargoldman yep.

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 7, 2020, 8:51pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/5 "2020-10-07T20:51:57Z")

</div>

yes, absolutely. All other nakama api calls are behaving as expected.

---

<div class="post-metadata">

**Author:** ![novabyte](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/novabyte/32/1324_2.png) [@novabyte](https://forum.heroiclabs.com/u/novabyte)\
**Post date:** [October 8, 2020, 6:26am UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/6 "2020-10-08T06:26:20Z")

</div>

@oscargoldman can you share the Unity code you’ve written to obtain the credentials from the Unity plugin and pass them into the client SDK?

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 3:09pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/7 "2020-10-08T15:09:31Z")

</div>

Before we do that, since it’s quite a lot of code, I’ve just looked up the api for this in the nakama source:  
///   
public async Task AuthenticateAppleAsync(string username, string token, Dictionary\<string, string\> vars) {  
var response = await \_apiClient.AuthenticateAppleAsync(username, string.Empty, new ApiAccountApple {Token = token, \_vars = vars});  
return new Session(response.Token, response.Created);  
}

What is the vars Dictionary expecting?

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 3:12pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/8 "2020-10-08T15:12:38Z")

</div>

oh looks like that’s the .net api, but the same question applies to the unity sdk. the authenticateAppleAsync has the username, token, and vars paramaters. What do we need for vars?

---

<div class="post-metadata">

**Author:** ![zyro](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/zyro/32/14_2.png) [@zyro](https://forum.heroiclabs.com/u/zyro)\
**Post date:** [October 8, 2020, 3:23pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/9 "2020-10-08T15:23:51Z")

</div>

@oscargoldman The `vars` parameter is extra information you might include with the authentication request to be cached alongside the session. It’s not required for authentication, and will not be the cause of your issue.

The `"Server key invalid."` error message is only returned if you make an authentication request with the wrong server key. As @novabyte said can you share the code you use to retrieve Apple Sign In credentials and pass them to the authentication call?

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 3:53pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/10 "2020-10-08T15:53:09Z")

</div>

using System;  
using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;

using AppleAuth;  
using AppleAuth.Native;  
using AppleAuth.Enums;  
using AppleAuth.Extensions;  
using AppleAuth.Interfaces;  
using System.Text;

namespace com.skylightgames.lyrical.business.login\_system  
{  
public class AppleSignInManager  
{  
private static AppleSignInManager \_instance;

```
    private const string PLAYERPREFS_APPLE_USER_KEY = "AppleSignInManager.AppleUserId";

    private IAppleAuthManager _appleAuthManager;
    private Action _onSignInComplete;

    public IAppleIDCredential appleIdCredential { get; private set; }

    public string token 
    { 
        get
        {
            if (appleIdCredential != null)
                return Encoding.UTF8.GetString(appleIdCredential.IdentityToken);
            return null;
        } 
    }

    public bool isLoggedIn { get; private set; }
    public event Action QUICK_LOGIN_SUCCESS;
    public event Action QUICK_LOGIN_FAILED;

    public event Action CREDENTIALS_REVOKED;
    public event Action CREDENTIALS_ERROR;

    public static AppleSignInManager GetInstance() {
        if (_instance == null)
        {
            _instance = new AppleSignInManager();
        }
        return _instance;
    }

    public void init()
    {
        isLoggedIn = false;
        // If the current platform is supported
        if (AppleAuthManager.IsCurrentPlatformSupported)
        {
            // Creates a default JSON deserializer, to transform JSON Native responses to C# instances
            var deserializer = new PayloadDeserializer();
            // Creates an Apple Authentication manager with the deserializer
            this._appleAuthManager = new AppleAuthManager(deserializer);

            this._appleAuthManager.SetCredentialsRevokedCallback(result =>
            {
                CREDENTIALS_REVOKED?.Invoke();
                Debug.Log("Received revoked callback " + result);
                PlayerPrefs.DeleteKey(PLAYERPREFS_APPLE_USER_KEY);
            });

            // If we have an Apple User Id available, get the credential status for it
            if (PlayerPrefs.HasKey(PLAYERPREFS_APPLE_USER_KEY))
            {
                var storedAppleUserId = PlayerPrefs.GetString(PLAYERPREFS_APPLE_USER_KEY);
                this.checkCredentialStatus(storedAppleUserId);
            }
            // If we do not have an stored Apple User Id, attempt a quick login
            else
            {
                this.attemptQuickLogin();
            }

            Game.GAME_UPDATE_EVENT -= onUpdate;
            Game.GAME_UPDATE_EVENT += onUpdate;
        }
    }

    private static void onUpdate()
    {
        if (_instance != null && _instance._appleAuthManager != null)
        {
            _instance._appleAuthManager.Update();
        }
    }

    //so we'd initialize this is in SkylightLyriko2D if the platform is ios

    //then we'll need to check and see the status of the current credentials
    //if they are still valid I think we do the quick login flow on app startup.
    //if they are not valid or don't exist, then we wait for Main.scene to load,
    //and when the user clicks Sign In To Apple we get the credentials, and then login via
    //Nakama

    private void checkCredentialStatus (string appleUserId)
    {
        // If there is an apple ID available, we should check the credential state
        this._appleAuthManager.GetCredentialState(
            appleUserId,
            state =>
            {
                switch (state)
                {
                // If it's authorized, login with that user id
                case CredentialState.Authorized:
                        Debug.Log($"AppleSignInManager::checkCredentialStatus: authorized");
                        this.attemptQuickLogin();
                        break;

                // If it was revoked, or not found, we need a new sign in with apple attempt
                // Discard previous apple user id
                case CredentialState.Revoked:
                case CredentialState.NotFound:
                        Debug.Log($"AppleSignInManager::checkCredentialStatus: revoked or not found");
                        PlayerPrefs.DeleteKey(PLAYERPREFS_APPLE_USER_KEY);
                        isLoggedIn = false;
                        CREDENTIALS_REVOKED?.Invoke();
                        //SIGN_IN_COMPLETED?.Invoke();
                        break;
                }
            },
            error =>
            {
                var authorizationErrorCode = error.GetAuthorizationErrorCode();
                isLoggedIn = false;
                CREDENTIALS_ERROR?.Invoke();
                Debug.Log($"AppleSignInManager::checkCredentialStatus: Error while trying to get credential state " + authorizationErrorCode.ToString() + " " + error.ToString());
            });
    }

    private void attemptQuickLogin()
    {
        var quickLoginArgs = new AppleAuthQuickLoginArgs();
        Debug.Log("AppleSignInManager::attemptQuickLogin: attempt quick login");
        // Quick login should succeed if the credential was authorized before and not revoked
        this._appleAuthManager.QuickLogin(
            quickLoginArgs,
            credential =>
            {
                isLoggedIn = false;
                // If it's an Apple credential, save the user ID, for later logins
                appleIdCredential = credential as IAppleIDCredential;
                if (appleIdCredential != null)
                {
                    PlayerPrefs.SetString(PLAYERPREFS_APPLE_USER_KEY, credential.User);
                    isLoggedIn = true;
                }
                QUICK_LOGIN_SUCCESS?.Invoke();
                Debug.Log("AppleSignInManager::attemptQuickLogin: Quick login successful");
            },
            error =>
            {
                // If Quick Login fails, we should show the normal sign in with apple menu, to allow for a normal Sign In with apple
                var authorizationErrorCode = error.GetAuthorizationErrorCode();
                isLoggedIn = false;
                QUICK_LOGIN_FAILED?.Invoke();
                Debug.LogWarning("AppleSignInManager::attemptQuickLogin: Quick Login Failed " + authorizationErrorCode.ToString() + " " + error.ToString());
            });
    }

    private void signInWithApple()
    {
        var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName);

        this._appleAuthManager.LoginWithAppleId(
            loginArgs,
            credential =>
            {
                Debug.Log("AppleSignInManager::signInWithApple:Sign in with Apple complete ");
                // If a sign in with apple succeeds, we should have obtained the credential with the user id, name, and email, save it
                PlayerPrefs.SetString(PLAYERPREFS_APPLE_USER_KEY, credential.User);
                appleIdCredential = credential as IAppleIDCredential;
                isLoggedIn = true;
                _onSignInComplete?.Invoke();
                _onSignInComplete = null;
            },
            error =>
            {
                var authorizationErrorCode = error.GetAuthorizationErrorCode();
                Debug.Log("AppleSignInManager::signInWithApple:Sign in with Apple failed " + authorizationErrorCode.ToString() + " " + error.ToString());
                isLoggedIn = false;
                _onSignInComplete?.Invoke();
                _onSignInComplete = null;

            });
    }

    public void connect(Action<object> tokenHandler)
    {
        if(isLoggedIn)
        {
            if (appleIdCredential != null)
                tokenHandler?.Invoke(Encoding.UTF8.GetString(appleIdCredential.IdentityToken));
            else
                tokenHandler?.Invoke(null);
        }
        else
        {
            _onSignInComplete = () =>
            {
                if (isLoggedIn)
                {
                    if (appleIdCredential != null)
                        tokenHandler?.Invoke(Encoding.UTF8.GetString(appleIdCredential.IdentityToken));
                    else
                        tokenHandler?.Invoke(null);
                }
            };
            signInWithApple();
        }
    }

}

```

}

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 3:56pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/11 "2020-10-08T15:56:27Z")

</div>

the above is our apple sign in manager, we can see that we successfully quick login for a returning user who has already authorized apple via sign in. The resulting event triggers this function in our nakama manager:

public static async Task signInApple(string token)  
{  
NakamaResponse response = new NakamaResponse();  
try  
{  
Debug.Log("NakamaManager::signInApple: start - token:{token}"); session = await \_instance.client.AuthenticateAppleAsync(null, token, null); Debug.Log(“NakamaManager::signInApple: process session - token:{token}”);

```
            response.payload = await processSession(session);
        }
        catch (ApiResponseException e)
        {
            Debug.Log($"NakamaManager::signInApple server error: {e.StatusCode}");
            Debug.LogException(e);
            response.error = UserDataManager.ERROR_SERVER;
        }
        catch (Exception e)
        {
            Debug.Log($"NakamaManager::signInApple internet error");
            Debug.LogException(e);
            response.error = UserDataManager.ERROR_INTERNET;
        }
        return response;
    }
```

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 4:06pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/12 "2020-10-08T16:06:54Z")

</div>

We can see in the xcode console that the nakama signInWithApple function receives the token

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 4:09pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/13 "2020-10-08T16:09:00Z")

</div>

And on a clean install of our app prior to a user signing in with apple, nakama works perfectly and all the native and custom endpoints are working, using the same server key.

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 8, 2020, 4:10pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/14 "2020-10-08T16:10:10Z")

</div>

What’s also maybe strange is there is no error reported in the nakama console

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 9, 2020, 3:08pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/15 "2020-10-09T15:08:07Z")

</div>

Can anyone confirm that it’s the appleIdCredentials.IdentityToken that we use for AuthenticateAppleAsync? we’re using Encoding.UTF8.GetString on the byte array to create a string for the nakama call.

---

<div class="post-metadata">

**Author:** ![lugehorsam](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/lugehorsam/32/314_2.png) [@lugehorsam](https://forum.heroiclabs.com/u/lugehorsam)\
**Post date:** [October 9, 2020, 4:48pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/16 "2020-10-09T16:48:33Z")

</div>

@oscargoldman we’ve identified the issue lies in our .NET and are pushing a fix to it in the next day or so.

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 9, 2020, 5:01pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/17 "2020-10-09T17:01:20Z")

</div>

oh man, thank you so much for the news. we were going a little crazy with this one. Look forward to the patch!

---

<div class="post-metadata">

**Author:** ![lugehorsam](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/lugehorsam/32/314_2.png) [@lugehorsam](https://forum.heroiclabs.com/u/lugehorsam)\
**Post date:** [October 10, 2020, 2:38pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/18 "2020-10-10T14:38:02Z")

</div>

@oscargoldman Thanks for filing the issue, we’ve merged this PR into the .NET client which resolves the issue and can update the Unity client with the new Nakama .DLL on Monday [https://github.com/heroiclabs/nakama-dotnet/pull/44](https://github.com/heroiclabs/nakama-dotnet/pull/44)

---

<div class="post-metadata">

**Author:** ![oscargoldman](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/oscargoldman/32/28_2.png) [@oscargoldman](https://forum.heroiclabs.com/u/oscargoldman)\
**Post date:** [October 12, 2020, 8:44pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/19 "2020-10-12T20:44:54Z")

</div>

Hi, any update on the Nakama Unity SDK patch?

---

<div class="post-metadata">

**Author:** ![lugehorsam](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/lugehorsam/32/314_2.png) [@lugehorsam](https://forum.heroiclabs.com/u/lugehorsam)\
**Post date:** [October 13, 2020, 4:03pm UTC](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034/20 "2020-10-13T16:03:27Z")

</div>

@oscargoldman yep, this commit has your fix:

> <https://github.com/heroiclabs/nakama-unity/commit/76a702d86a2053c554543fe7f2c665b14fa777e0>

We haven’t done the release through the Asset Store yet (that will come at some later, undetermined date) so I recommend depending on the commit using the Unity Package Manager instructions outlined in the README.md. This is the preferred dependency method anyway.

[Next page](https://forum.heroiclabs.com/t/issue-with-authenticateappleasync-from-quick-login/1034.md?page=2)
