Skip to content

Instantly share code, notes, and snippets.

@manwithsteelnerves
Last active January 22, 2026 11:07
Show Gist options
  • Select an option

  • Save manwithsteelnerves/0535562a4f2d6ad5ea2d03c68979abde to your computer and use it in GitHub Desktop.

Select an option

Save manwithsteelnerves/0535562a4f2d6ad5ea2d03c68979abde to your computer and use it in GitHub Desktop.
Voxel Busters Essential Kit Game Services Server Auth on iOS
public void LoadServerCredentials()
{
GameServices.LoadServerCredentials((result, error) =>
{
if(error == null)
{
StartCoroutine(VerifyIosServerCredentials(result.ServerCredentials));
}
else
{
Log("Loading server credentials failed with error. Error: " + error);
}
});
}
private IEnumerator VerifyIosServerCredentials(ServerCredentials credentials, bool isAppleArcadeGame = false)
{
#pragma warning disable
WWWForm form = new WWWForm();
form.AddField("publicKeyUrl", credentials.IosProperties.PublicKeyUrl);
form.AddField("timestamp", System.Convert.ToString(credentials.IosProperties.Timestamp));
form.AddField("signature", System.Convert.ToBase64String(credentials.IosProperties.Signature));
form.AddField("salt", System.Convert.ToBase64String(credentials.IosProperties.Salt));
form.AddField("playerId", isAppleArcadeGame ? GameServices.LocalPlayer.DeveloperScopeId : GameServices.LocalPlayer.Identifier); //Ref: https://developer.apple.com/documentation/gamekit/gklocalplayer/fetchitems(foridentityverificationsignature:)#Discussion
form.AddField("bundleId", Application.identifier);
UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Post("https://.../authenticate", form);
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Success response from server! " + www.downloadHandler.text);
}
#pragma warning restore
}
// Firebase function
import * as functions from 'firebase-functions';
import * as verifier from 'gamecenter-identity-verifier';
export const authenticate = functions.https.onRequest((request : any, response : any) => {
const identity = {
publicKeyUrl: request.body.publicKeyUrl,
timestamp: request.body.timestamp,
signature: request.body.signature,
salt: request.body.salt,
playerId: request.body.playerId,
bundleId: request.body.bundleId
};
console.log("Identity : ", identity);
verifier.verify(identity, function (err : any, token : any) {
if (!err) {
// use token in here.
return response.status(200).json({ message : 'successfully verified with details : '+ (JSON.stringify(token)) });
} else {
console.error("Error : " , err);
return response.status(500).json({ error : err } );
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment