Enabling Server-Side Access to Google Play Games Services

If your game uses a backend server, we recommend that you use Google Sign-In to authenticate players and securely pass the player's identity to the backend server.

In this scenario, your game prompts the player to sign in to Google Play games services as usual. When the player signs in successfully, your Google API client receives a special single-use code (called the server auth code) that the client passes to the server. Then, on the server, exchange the server auth code for an OAuth 2.0 token that the server can use to make calls to the Google Play Games Services API.

Before you begin

Before you can integrate Google Sign-In into your game, you'll first need to add your game in the Google Play Console, as described in Setting Up Google Play Games Services.

Configure Google Sign-In for player data that your game requires

In the onCreate() method of your game's sign-in activity, create a GoogleSignInOptions object with the DEFAULT_GAMES_SIGN_IN parameter. This parameter indicates that Google Sign-In should return the Gamer ID and profile information.

By default, the system automatically signs players in silently once they have opted-in. If your game requires additional information that's not included by default in the Gamer profile, such as the player's email address or Google user ID, you must request for user consent by calling the requestEmail() or requestId()methods. We don't recommend this approach as doing so disables the default automatic sign-in behavior, and may cause players to avoid signing-in due to the additional consent screens.

Specify that your game requires an auth code for your backend server by calling the requestServerAuthCode() method with server's client ID as the parameter.

Optional: You can configure the sign-in flow with additional parameters for games, by calling addExtension() and passing in a Games.GamesOptions instance. For example, you can specify that the UI hide the "connecting" pop-up dialog at the start of the sign-in flow, by calling setShowConnectingPopup() with the argument set to false.

The following code snippet shows how you might configure the game sign-in options.

@Override
protected void onCreate(Bundle savedInstanceState) {

    // Client ID for your backend server.
    String webclientId = getString(R.string.webclient_id);

    // Request authCode so we can send the code to the server.
    GoogleSignInOptions options = New GoogleSignInOptions
        .Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
        .requestServerAuthCode(webclientId)
        .build();
}

Configure the GoogleApiClient

In your sign-in activity's onCreate() method, create a GoogleApiClient object to access Google Play games services and Google Sign-In. When adding Google Sign-In to your client, pass in the GoogleSignInOptions object you created in the previous step.

The following code snippet shows how you might create the Google API client.

mGoogleApiClient = new GoogleApiClient.Builder(this)
    .addApi(Games.API)
    .addApi(Auth.GOOGLE_SIGN_IN_API, options)
    .addConnectionCallbacks(this)
    .addOnConnectionFailedListener(this)
    .build();

Provide a sign-in button

To provide a Google sign-in button in your game, you can use one of these approaches:

When players click the sign-in button, your game should initiate the sign-in flow by calling getSignInIntent() to retrieve a sign-in Intent, then call startActivityForResult() with that Intent as a parameter.

Create an associated web app for your game

If you want to use the REST APIs for Google Play Games services in your server-side app, follow these steps:

  1. Create an associated web app for your game in the Linked Apps section of the Google Play Console.
  2. Set the launch URL field with the url to access your server-side app.
  3. To get the credential information for your app:
    1. From your game in the Google Play Console, click Game Details.
    2. Scroll down to the API Console Project section and click on the link to the API console project.
    3. From the credentials screen in the Google API Console, download the client_secret.json file for your web app and save it in a location that your server can access.
  4. Restart your server-side app so it’s ready to accept requests from your game’s client app.

To learn more about calling Google REST APIs, see Authorizing and Using REST APIs.

Get the server auth code

To retrieve a server auth code that your game can use for access tokens on your backend server, call the getServerAuthCode() method on the GoogleSignInAccount object that Google Sign-In returns on successful player sign-in.

The following code snippet shows how you might retrieve the server auth code in your game's sign-in activity.

private String serverAuthCode;

@Override
protected void onActivityResult(int requestCode, int responseCode,
        Intent intent) {
    if (requestCode == RC_SIGN_IN) {
        Log.d(TAG, "onActivityResult with requestCode == RC_SIGN_IN, " +
                "responseCode=" + responseCode + ", intent=" + intent);
        GoogleSignInResult result =
            Auth.GoogleSignInApi.getSignInResultFromIntent(intent);
        if (result.isSuccess()) {
            GoogleSignInAccount acct = result.getSignInAccount();
            serverAuthCode = acct.getServerAuthCode();
        } else {
            // handle login failure
        }
    } else {
        super.onActivityResult(requestCode, responseCode, intent);
    }
}

Exchange the server auth code for an access token on the server

Send the server auth code to your backend server to exchange for access and refresh tokens. Use the access token to call the Google Play Games Services API on behalf of the player and, optionally, store the refresh token to acquire a new access token when the access token expires.

The following code snippet shows how you might implement the server-side code in the Java programming language to exchange the server auth code for access tokens.

/**
 * Exchanges the authcode for an access token credential.  The credential
 * is the associated with the given player.
 *
 * @param authCode - the non-null authcode passed from the client.
 * @param player   - the player object which the given authcode is
 *                 associated with.
 * @return the HTTP response code indicating the outcome of the exchange.
 */
private int exchangeAuthCode(String authCode, Player player) {
try {

    // The client_secret.json file is downloaded from the Google API
    // console.  This is used to identify your web application.  The
    // contents of this file should not be shared.
    //
    File secretFile = new File("client_secret.json");

    // If we don't have the file, we can't access any APIs, so return
    // an error.
    if (!secretFile.exists()) {
        log("Secret file : " + secretFile
                .getAbsolutePath() + "  does not exist!");
        return HttpServletResponse.SC_FORBIDDEN;
    }

    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
            JacksonFactory.getDefaultInstance(), new
            FileReader(secretFile));

    // Extract the application id of the game from the client id.
    String applicationId = extractApplicationId(clientSecrets
            .getDetails().getClientId());

    GoogleTokenResponse tokenResponse =
            new GoogleAuthorizationCodeTokenRequest(
            HTTPTransport,
            JacksonFactory.getDefaultInstance(),
            "https://www.googleapis.com/oauth2/v4/token",
            clientSecrets.getDetails().getClientId(),
            clientSecrets.getDetails().getClientSecret(),
            authCode,
            "")
            .execute();

    log("hasRefresh == " + (tokenResponse.getRefreshToken() != null));
    log("Exchanging authCode: " + authCode + " for token");
    Credential credential = new Credential
            .Builder(BearerToken.authorizationHeaderAccessMethod())
            .setJsonFactory(JacksonFactory.getDefaultInstance())
            .setTransport(HTTPTransport)
            .setTokenServerEncodedUrl("https://www.googleapis" +
                    ".com/oauth2/v4/token")
            .setClientAuthentication(new HttpExecuteInterceptor() {
                @Override
                public void intercept(HttpRequest request)
                        throws IOException {
                        }
            })
            .build()
            .setFromTokenResponse(tokenResponse);

    player.setCredential(credential);

    // Now that we have a credential, we can access the Games API.
    PlayGamesAPI api = new PlayGamesAPI(player, applicationId,
            HTTPTransport, JacksonFactory.getDefaultInstance());

    // Call the verify method, which checks that the access token has
    // access to the Games API, and that the player id used by the
    // client matches the playerId associated with the accessToken.
    boolean ok = api.verifyPlayer();

    // Call a Games API on the server.
    if (ok) {
        ok = api.updatePlayerInfo();
        if (ok) {
            // persist the player.
            savePlayer(api.getPlayer());
        }
    }

    return ok ? HttpServletResponse.SC_OK :
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR;

} catch (IOException e) {
    e.printStackTrace();
}
    return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}

To learn more about accessing Google APIs from a backend server on behalf of a signed-in player, see Enabling Server-Side Access.

Handle player sign-out

To sign players out of your game, call the Games.signOut() method and then sign out of the Google API client by calling GoogleSignInApi.signOut(). Do not call the disconnect() method on the Google API client directly as this may cause unexpected errors.

private void handleSignOut() {
    Log.d(TAG, "Sign-out button clicked");
    if (mGoogleApiClient.hasConnectedApi(Games.API)) {
        Games.signOut(mGoogleApiClient);
        Auth.GoogleSignInApi.signOut(mGoogleApiClient);
    }

    // do other cleanup tasks
}

For additional guidance on adding sign-in in your games, see Implementing Sign-In in Your Android Game. To see a detailed code sample showing how to use Google Sign-In to authenticate players, see the clientserverskeleton sample on GitHub.

Enviar comentarios sobre…

Play Games Services for Android
Play Games Services for Android