question

diovanmarques avatar image
diovanmarques asked

Unity Game Center Authentication Failed

Hi, I'm trying to have Secure Authentication when logging in to Playfab using GameCenter, but I always receive the error "Authentication failed. Signature does not match the authentication request data".

I know I have to fetch the data from Apple using a request in native code, which I am able to do, but couldn't get PlayFab to accept the data.

I tried using this code https://gist.github.com/BastianBlokland/bbc02a407b05beaf3f55ead3dd10f808 , this code https://github.com/desertkun/GameCenterAuth and the iOS Native Pro unity asset, but none of them worked.

I tried altering the native code from some of these plugins because some of them seem to already encode the data to base64 and maybe I didn't need everything encoded, but it didn't work.

I tried encoding the Signature to base64 as the OP said in this post https://community.playfab.com/questions/52821/unity-game-center-secure-authentication-problem.html , but it didn't work.

I tried logging every information I can get from the PlayFabError I receive, but the only information provided is "400 Bad Request" and "Authentication failed. Signature does not match the authentication request data".

I know some time ago apple deprecated generateIdentityVerificationSignatureWithCompletionHandler in place of fetchItemsForIdentityVerificationSignature but using either of them seems to make no difference.

I tried possibly every combination of solutions from all the posts, documentation, videos, commentaries, etc I could find but nothing seems to work.

I have no idea which of the data is incorrect, or if all of them are incorrect, or any detail besides a vague "there's something wrong", and the documentation from PlayFab is also extremely vague on this.

Does someone had to deal with this recently and was successful in doing so? I would really appreciate some help

Thanks in advance

unity3dsdksappleAuthentication
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image
Gosen Gao answered

We do not know the specific behavior of the third-party plugin you are using. According to Apple's official documentation, the workflow is:

  1. Call the fetchItems(forIdentityVerificationSignature:) method in your app.
  2. Send the publicKeyURL, signature, salt, and timestamp parameters to the third-party server you’re using for authentication.
  3. Use the publicKeyURL on the third-party server to download the public key.
  4. Verify with the appropriate signing authority that Apple signed the public key.
  5. Retrieve the player’s teamPlayerID and the app’s bundle ID (see CFBundleIdentifier).
  6. Concatenate the following information into a data buffer in the listed order:
    • The teamPlayerID property in UTF-8 format
    • The app’s bundle ID in UTF-8 format
    • The timestamp parameter in big-endian UInt64 format
    • The salt parameter
  7. Generate an SHA-256 hash value for the buffer.
  8. Using the public key that you downloaded in step 3, verify that the generated hash value from step 7 matches the signature parameter that the API provides.

Please check your plugin to see if it behaves according to the documentation.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

diovanmarques avatar image
diovanmarques answered

@Gosen Gao

I'm not sure about this, but in this case, wouldn't PlayFab be the third-party server I'm using for authentication?

These plugins I tried using simply make the call for fetchItems(forIdentityVerificationSignature:) in iOS native code and return me the data (publicKeyURL, signature, salt and timestamp) inside Unity, which then I use to Log In With Game Center in a call similar to this

 PlayFabClientAPI.LoginWithGameCenter(new LoginWithGameCenterRequest()
 {               
  PlayerId = Social.localUser.id,
  CreateAccount = create,         
  PublicKeyUrl = publicKeyURL,
  Salt = salt,
  Signature = signature,
  Timestamp = timestamp.ToString(),               
  InfoRequestParameters = new GetPlayerCombinedInfoRequestParams
   {
      GetUserAccountInfo = true
    }
 }, result, error); 

I tried using different plugins for the fecthItems call since I was unsure on how they handled the data received from Apple and maybe something didn't match how PlayFab expected the data, but none of them worked, despite multiple people reported being successful in using these plugins and making the call to PlayFab with the data in the same way I did

3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image Gosen Gao commented ·

Sorry for the confusion, PlayFab is the third-party server, and we are using the same workflow to check if the signature matches the publicKeyURL, salt, Timestamp, app’s bundle ID and PlayerID. You can follow this workflow to check the signature to see which data is incorrect.

0 Likes 0 ·
diovanmarques avatar image diovanmarques commented ·

So if I understood correctly, PlayFab is doing this workflow with the data I provide, the concatenated data isn't matching the signature but it can't exactly say which of the data is incorrect, so it's just returns me the "Signature does not match the authentication request data" error?

I'll try doing this workflow manually to see if I can find the problem and I'll post here once I have some news, thanks!

0 Likes 0 ·
Gosen Gao avatar image Gosen Gao diovanmarques commented ·

Yes, you are correct. If you have any other questions, please feel free to post a new thread for it.

0 Likes 0 ·
diovanmarques avatar image
diovanmarques answered

FINALLY GOT IT!

I put this aside for some time and went back to it today and finally got it to work.

For future people who may come across this problem, I don't know exactly what was the solution, but here's what I did:

First, I used this library: https://github.com/desertkun/GameCenterAuth

Second, I remembered seeing somewhere that Apple did some changes regarding the Game Center playerId and we are supposed to use the teamPlayerId, so I altered the library to retrieve the teamPlayerId, since I was unsure if Unity's Social API Social.localUser.id was returning the teamPlayerId or the playerId, and I used the id retrieved by the library in the Playfab login.

In the meantime between I posted this question and today, the app was approved in the appstore (using Playfab Login without authentication), and we had to fill some forms/docs in the Agreements, Tax and Banking area of the AppStore Connect for the IAP to work.

I did a build with a lot of logs to check the data that was being retrieved by the library and use it to test the Playfab login with Insomnia, but the login actually worked.

I think there's a remote possibility that the teamPlayerId change was the solution, but my theory is that the lack of filling those information regarding taxes and stuff was purposely by Apple preventing the authentication for the app, possibly related to the bundleId.

So in the end, I used the data retrieved from the library as it came (without encoding or decoding anything) and it worked, basically like this

PlayFabClientAPI.LoginWithGameCenter(new LoginWithGameCenterRequest
            {
                CreateAccount = true,
                PlayerId = authenticationData.playerId,
                PublicKeyUrl = authenticationData.publicKeyUrl,
                Salt = authenticationData.salt,
                Signature = authenticationData.signature,
                Timestamp = authenticationData.timestamp.ToString(),
                InfoRequestParameters = new GetPlayerCombinedInfoRequestParams
                {
                    GetUserAccountInfo = true
                }
            }, OnSuccess, OnFailed)
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Nate avatar image
Nate answered

Unity's docs say that Social.localUser.id returns teamPlayerID for iOS 12.4 and newer and playerID for older versions.

My solution for this was changing the native method called from the deprecated generateIdentityVerificationSignature to the recommended fetchItemsForIdentityVerificationSignature. Then using Social.localUser.id started working.

You might have to bump up your min iOS version to 13.5 to make sure you support it. I was okay doing that. It also ensures Social.localUser.id always returns teamPlayerID.

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Spektra Games avatar image Spektra Games commented ·

Min ios version to 12.4 is not enough do you think? Why 13.5? And secondly, is it possible to share your native method that name fetchItemsForIdentityVerificationSignature? We are fighting with same issues

0 Likes 0 ·
Nate avatar image Nate Spektra Games commented ·

teamPlayerID was introduced in 12.4, but the fetchItems... method was in 13.5.

I started with this gist, then just swapped in the new method. The signatures are the same, so you can just drop it in. I haven't tried it, but the plugin linked above might be easiest to use, then just fork or modify it with the new method here.

1 Like 1 ·
Daniel Lupascu avatar image
Daniel Lupascu answered

I am getting this from the previous method ..

EntryPointNotFoundException: GenerateIdentityVerificationSignature assembly: type: member:(null),I am getting this from the previous method.. EntryPointNotFoundException: GenerateIdentityVerificationSignature assembly: type: member:(null)

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.