Apple Game Center sign-in
Players who are signed in to Game Center on their iPhone, iPad or Mac sign in to your game without a password or a browser. The game sends Game Center's signed proof to auth4.dev, which checks it with Apple's key and returns auth4.dev tokens.
1. Allow your app's bundle id
Game Center sign-in is set per game application. Allow the bundle id of each app that may sign in, for example com.example.arcade for iOS and com.example.arcade.macfor macOS. Game Center is on as soon as one bundle id is allowed, and off when the list is empty. Browser and server applications can't use it.
PUT /management/tenants/{tenantId}/clients/{clientId}/game-center
Content-Type: application/json
{ "allowed_bundle_ids": ["com.example.arcade", "com.example.arcade.mac"] }Owners and admins can change the list. The API reference page for AUTH4D-311 has every field and error.
2. Sign in from Unity
The Unity SDK doesn't call GameKit itself. Give the client a Game Center adapter in Auth4ClientOptions.GameCenter, then call SignInWithGameCenterAsync. The Game Center Sign-In sample in the Unity package has an adapter built on Apple's GameKit plug-in for Unity. Add the plug-in to your project and the AUTH4_APPLE_GAMEKIT scripting define symbol for iOS and macOS. The adapter fetches a new signature for every sign-in:
packages/sdk-unity/Samples~/GameCenterSignIn/AppleGameKitGameCenter.cspublic async Task<GameCenterIdentity> FetchIdentityAsync(CancellationToken cancellationToken)
{
// GameKit shows its own sign-in UI the first time; later calls reuse the result.
if (_authenticated == null || _authenticated.IsFaulted || _authenticated.IsCanceled)
{
_authenticated = GKLocalPlayer.Authenticate();
}
var local = await _authenticated;
cancellationToken.ThrowIfCancellationRequested();
var items = await local.FetchItems();
return new GameCenterIdentity(
IsAppleArcade ? local.GamePlayerId : local.TeamPlayerId,
Application.identifier,
items.PublicKeyUrl,
items.GetSignature(),
items.GetSalt(),Apple Arcade games send the gamePlayerID instead of the teamPlayerID; set IsAppleArcade on the sample adapter. Then sign in:
packages/sdk-unity/Samples~/GameCenterSignIn/GameCenterSignInSample.csprivate void SignIn()
{
Run(async () =>
{
try
{
await _client.SignInWithGameCenterAsync(_cancellation.Token);
}
catch (Auth4EmailVerificationRequiredException required)
{
_emailStep = required.Continuation;
_status = "This game needs a verified email address.";
}
});
}The full sample is packages/sdk-unity/Samples~/GameCenterSignIn/GameCenterSignInSample.cs. On other platforms, or without an adapter, the call throws PlatformNotSupportedException.
What identity data you get
- Game Center gives auth4.dev only the player id it signed. It shares no email address, display name or avatar.
- Every token names the method in
idp, which isgame_center, and carriessub, the player's auth4.dev user ID. Key game data bysub. - The player id is stored as the player's Game Center identity in your project. It isn't put in tokens. Because Apple's
teamPlayerIDis the same in all of a team's games, the iOS and macOS versions of a game sign in to the same account. - A Game Center account and an email, Steam or Discord account are separate players unless the player links them.
What auth4.dev checks
- The bundle id is one you allowed for the application.
- The signature is at most five minutes old.
- The key comes from Apple's server over HTTPS, and its certificate chains to the certificate authority Apple uses. auth4.dev keeps that authority's certificates itself.
- The signature matches the player id, bundle id, timestamp and salt.
- The same signature was not used before. A replayed request is refused.
Each of these failures answers invalid_grant without saying which check failed. Ask the player to try again: the adapter then fetches a new signature.
Saving a guest's progress
When a guest is signed in, SignInWithGameCenterAsync links the Game Center player to the guest instead. The player keeps the same user ID and stops being a guest, and the guest session is replaced. If the Game Center player already has an account in your project, the call fails with identity_in_use and the guest stays as it was. Accounts are never merged: sign out and sign in with Game Center to reach the existing account.
The verified email step
Game Center shares no email address, so under the application's default setting the verified email step applies, as it does for Steam. A player without a verified address gets Auth4EmailVerificationRequiredException instead of a session. Ask for an address in your game, then send and confirm a six-digit code:
packages/sdk-unity/Samples~/GameCenterSignIn/GameCenterSignInSample.csprivate void SendCode()
{
Run(async () =>
{
await _client.SendGameCenterEmailCodeAsync(_emailStep, _email, _cancellation.Token);
_status = "We sent a code to " + _email.Trim() + ".";
});
}
private void ConfirmCode()
{
Run(async () =>
{
await _client.ConfirmGameCenterEmailCodeAsync(_emailStep, _code, _cancellation.Token);
_emailStep = null;
_code = string.Empty;
});
}- The address is saved on the account, so later Game Center sign-ins skip the step, and tokens carry
emailwithemail_verified: true. invalid_codelets the player try again.email_unavailablemeans another player uses the address, so ask for a different one. The step lasts ten minutes; after that, sign in with Game Center again.- For silent sign-in with no prompt, set Require a verified email to Off on the application. Players then have no
emailclaim.
Other engines and your own code
Any game can call POST /t/{tenantId}/game-center/token with what GameKit returned: the player id, bundle id, publicKeyURL, signature, salt and timestamp. The signature and salt are base64 and the timestamp is a number. Send it from the game itself: the endpoint refuses requests from web pages.