Step 2. Log in
Implement login so that users can log in to the app with their Google Play Games profile without signing up separately. Before you begin, complete Step 1. Set up the integration.
Google Play Games login works only on Android, and because the Add-on returns an authorization code for server exchange, it follows the Authorization Code flow.
1. Get Google Play Games credentials
The Google Play Games login Add-on splits the Play Games authentication work into three methods. The app calls these methods in order to receive an authorization code for server exchange.
IsAuthenticatedAsync(): Checks the current Play Games authentication status without showing a screenSignInAsync(): Shows the Play Games account selection screen. If the user is already authenticated, it ends immediately without a screenRequestServerSideAccessAsync(): Requests an authorization code for server exchange while the user is authenticated
1.1. Check the authentication status and log in
First check the status with IsAuthenticatedAsync(), and if the user is not authenticated, open the login screen with SignInAsync(). If the user is already authenticated, SignInAsync() ends immediately without a screen, so you can skip the status check and call it directly. However, checking the status first lets the app control when the login screen appears.
using Hive.Axyl.Auth.Addon.GPG;
using Hive.Axyl.Core;
using UnityEngine;
// The Add-on is registered only in Android builds.
if (!HiveCore.TryResolve<IGooglePlayGamesPlugin>(out var gpg))
{
// Not Android, or the Add-on is not registered → offer other login methods
return;
}
var authState = await gpg.IsAuthenticatedAsync(new IsAuthenticatedRequest());
if (authState is GooglePlayGamesServiceIsAuthenticatedResult.NotAuthenticated)
{
var signIn = await gpg.SignInAsync(new SignInRequest());
switch (signIn)
{
case GooglePlayGamesServiceSignInResult.Success:
break; // Authentication complete → proceed to request the authorization code
case GooglePlayGamesServiceSignInResult.UserCanceled:
// The user closed the Play Games login screen → keep the login screen
return;
case GooglePlayGamesServiceSignInResult.NotAuthenticated:
// Authentication ended without a login screen, but the user is still not authenticated → offer other login methods
return;
case GooglePlayGamesServiceSignInResult.Failure failure:
HiveError signInError = failure.Problem;
Debug.LogError($"[{signInError.Code}] {signInError.Message} (trace: {signInError.TraceId})");
return;
// Safety net: unhandled results and unknown new results (UnknownOutcome)
default:
Debug.LogWarning($"Unhandled result: {signIn.GetType().Name}");
return;
}
}
else if (authState is GooglePlayGamesServiceIsAuthenticatedResult.Failure stateFailure)
{
HiveError stateError = stateFailure.Problem;
Debug.LogError($"[{stateError.Code}] {stateError.Message} (trace: {stateError.TraceId})");
return;
}
If the app needs to stop authentication while the login screen is open, call CancelCurrentSignIn(). The pending SignInAsync() ends with Failure, and Failure.Problem.Code contains Cancelled.
Response status
We recommend handling the response cases of GooglePlayGamesServiceIsAuthenticatedResult and GooglePlayGamesServiceSignInResult with a switch statement.
| Method and response case | Description | App client handling |
|---|---|---|
IsAuthenticatedAsync() → Success | The user is already authenticated | Proceed directly to requesting the authorization code |
IsAuthenticatedAsync() → NotAuthenticated | The user is not authenticated. This is not an error. | Call SignInAsync() |
SignInAsync() → Success | Login succeeded | Proceed to requesting the authorization code |
SignInAsync() → UserCanceled | The user closed the Play Games login screen | Keep the login screen |
SignInAsync() → NotAuthenticated | It ended without a login screen, but the user is still not authenticated | Offer other login methods |
UnknownOutcome | A new result that this SDK version does not know | Log it and handle it conservatively |
Failure | Common Failure. Cancellation by the app (Cancelled) also branches here. See Common error handling. | Handle according to the common error handling criteria |
1.2. Request an authorization code for server exchange
RequestServerSideAccessAsync
After authentication, call RequestServerSideAccessAsync() to receive an authorization code for server exchange. You use this authorization code as ProviderCode in Exchange external authorization codes.
| Field name | Type | Required | Description |
|---|---|---|---|
WebClientId | string | Required | Web application type OAuth client ID prepared in Check the Google Play Games login credentials. If you leave it empty, ArgumentException is thrown. |
ForceRefreshToken | bool | Optional | Whether to get a new refresh token issued. Set it to true for the first exchange or if the previous exchange failed. If omitted, it is false. |
using Hive.Axyl.Auth.Addon.GPG;
using Hive.Axyl.Core;
using UnityEngine;
// The Add-on is registered only in Android builds.
if (!HiveCore.TryResolve<IGooglePlayGamesPlugin>(out var gpg))
{
return;
}
var accessResult = await gpg.RequestServerSideAccessAsync(
new RequestServerSideAccessRequest {
WebClientId = "{webClientId}",
ForceRefreshToken = true,
});
string serverAuthCode; // ProviderCode for external authorization code exchange
switch (accessResult)
{
case GooglePlayGamesServiceRequestServerSideAccessResult.Success success:
serverAuthCode = success.Data.ServerAuthCode;
break;
case GooglePlayGamesServiceRequestServerSideAccessResult.NotAuthenticated:
// Not authenticated → call SignInAsync first and try again
return;
case GooglePlayGamesServiceRequestServerSideAccessResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
return;
// Safety net: unhandled results and unknown new results (UnknownOutcome)
default:
Debug.LogWarning($"Unhandled result: {accessResult.GetType().Name}");
return;
}
Warning
ServerAuthCode is a credential that can be used only once. Do not leave it in logs, crash reports, or analytics events.
Response status
| Response case | Description | App client handling |
|---|---|---|
Success | The authorization code was issued successfully. Use Data.ServerAuthCode as ProviderCode. | Proceed with external authorization code exchange |
NotAuthenticated | The user is not authenticated | Call SignInAsync(), and then retry |
UnknownOutcome | A new result that this SDK version does not know | Log it and handle it conservatively |
Failure | Common Failure. Cases where the Play Games settings are not in place (FailedPrecondition) also branch here, and the cause is stored in Failure.Problem.Code. See Common error handling. | Handle according to the common error handling criteria |
2. Exchange the external authorization code
Send the authorization code you received to Exchange external authorization codes to convert it into credentials to use for login. Put Provider.GooglePlayGames in ProviderId, and put the redirect URI that you registered in the Web application type OAuth client in Check the Google Play Games login credentials as is in RedirectUri.
Google Play Games does not use PKCE in this step, so do not put a value in CodeVerifier.
using Hive.Axyl.Auth;
using Hive.Axyl.Core;
IAuthService auth = HiveCore.Resolve<IAuthService>();
var exchange = await auth.ExchangeProviderTokenAsync(new ProviderTokenRequest {
ProviderId = Provider.GooglePlayGames,
ProviderCode = serverAuthCode,
RedirectUri = redirectUri,
});
if (exchange is not AuthExchangeProviderTokenResult.Success exchanged)
{
// For exchange failure handling, see [Exchange external authorization codes](provider-token-exchange.md)
return;
}
string gpgProviderToken = exchanged.Data.ProviderToken; // ProviderToken of the login request
string gpgProviderUserId = exchanged.Data.ProviderUserId; // ProviderUserId of the login request
3. Log in with an external authentication provider
Call Log in with an external authentication provider with the gpgProviderUserId and gpgProviderToken obtained from the exchange. Specify Provider.GooglePlayGames for ProviderId.
using Hive.Axyl.Auth;
using Hive.Axyl.Core;
IAuthService auth = HiveCore.Resolve<IAuthService>();
var (codeVerifier, codeChallenge) = CreatePkce();
var result = await auth.LoginProviderAsync(new ProviderLoginRequest {
ProviderId = Provider.GooglePlayGames,
ProviderUserId = gpgProviderUserId,
ProviderToken = gpgProviderToken,
DeviceKey = deviceKey,
ClientId = "{clientId}",
CodeChallenge = codeChallenge,
CodeChallengeMethod = CodeChallengeMethod.S256,
});
if (result is AuthLoginProviderResult.Success success)
{
// Login succeeded → issue tokens and activate the session.
await StartSessionAsync(success.Data.AuthorizationCode, codeVerifier, success.Data.PlayerId);
}
// For other response cases and all call parameters, see [Log in with an external authentication provider](provider-login.md)
Note
The PKCE values generated here are used when exchanging the authorization code issued by the Hive Axyl authentication server for tokens. They are unrelated to the authorization code for server exchange from the previous step.
CreatePkce() is a helper defined in Create a guest account. For the definition of StartSessionAsync() and the session activation procedure, see Issue tokens and activate the session.