Google Playゲームサービスへのサーバサイドアクセスを有効にする



  • この記事は、Google Playゲームサービスに関する記事を和訳したものです。
  • 原文: Enabling Server-Side Access to Google Play Games Services
  • 元記事のライセンスは CC-BYで、この和訳記事のライセンスは CC-BYです。
  • 自己責任でご利用ください。
  • 和訳した時期は 2019年7月ころです。

もしあなたのゲームがバックエンドサーバを使用するならば、プレイヤーを認証し、プレイヤーの IDをバックエンドサーバに安全に渡すために、Google Sign-Inを使用することをお勧めします。

このシナリオでは、あなたのゲームは通常どおり、プレイヤーに Google Playゲームサービスにサインインすることを促します。 プレイヤーが正常にサインインしたとき、GoogleSignInAccountオブジェクトは、クライアントがサーバに渡す特別な一回限りのコード(サーバ認証コードと呼ばれる)を含んでいます。 それから、サーバ上で、サーバ認証コードと、サーバが Google Playゲームサービス APIに呼び出しをするために使用することができる OAuth 2.0トークンを交換します。

あなたのゲームにサインインを追加する方法の詳細については、Androidゲームでのサインインを参照してください。

プレイヤーを認証するために Googleサインインを使用する方法を示す詳細なコードサンプルを見るには、GitHub上の clientserverskeleton sampleを参照してください。

始める前に

Googleサインインをあなたのゲームに統合する前に、Google Playゲームサービスをセットアップするに記載されているように、まず、Google Play Consoleにあなたのゲームを追加する必要があるでしょう。

クライアント上でサインインを実行する

GoogleSignInClientクラスは、現在サインインしているプレイヤーのアカウントを取得するための主要なエンドポイントです、そして、彼らが以前に端末にてあなたのアプリ上でそうしていない場合には、プレイヤーをサインインさせるものです。

サインインクライアントを作成するには、次の手順に従います:

  1. GoogleSignInOptionsオブジェクトを経由して、サインインクライアントを作成します。 あなたのサインインを構成するために GoogleSignInOptions.Builderにて、GoogleSignInOptions.DEFAULT_GAMES_SIGN_INを指定しなければなりません。
  2. また、パラメータとしてサーバのクライアント IDを伴う GoogleSignInOptions.Builder.requestServerAuthCode()メソッドを呼び出すことによって、あなたのゲームが、あなたのバックエンドサーバのための認証コードを必要とすることを指定しなければなりません。 サーバ認証コードを取得するに記述しているように、あなたのバックエンドサーバ上でアクセストークンのための認証コードを、後に取得するでしょう。
  3. GoogleSignIn.getClient()メソッドを呼び出し、以前に構成したオプションを渡します。 もし呼び出しが成功したならば、Googleサインイン APIは、GoogleSignInClientインスタンスを返します。
  4. ひとたび GoogleSignInClientインスタンスを取得したならば、サイレントサインインを実行するに記述しているように、アクティビティの onResume()からサイレントにプレイヤーをサインインさせるように進める必要があります。

これが例です:

private static final int RC_SIGN_IN = 9001;
private GoogleSignInClient mGoogleSignInClient;

private void startSignInForAuthCode() {

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

  GoogleSignInOptions signInOption = new
      GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
      .requestServerAuthCode(webClientId)
      .build();

  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  Intent intent = signInClient.getSignInIntent();
  startActivityForResult(intent, RC_SIGN_IN);
}

あなたのゲームに関連するウェブアプリを作成する

もしあなたのサーバサイドアプリにて Google Playゲームサービス用の REST APIを使用したければ、次の手順に従います:

  1. Google Play ConsoleLinked Appsセクションにて、あなたのゲームに関連するウェブアプリを作成します。
  2. launch URLフィールドに、あなたのサーバサイドのアプリにアクセスするための URLをセットします。
  3. あなたのアプリのための資格情報を取得するには:
    1. Google Play Consoleにてあなたのゲームから Game Detailsをクリックします。
    2. API Console Projectセクションまでスクロールし、APIコンソールプロジェクトへのリンクをクリックします。
    3. Google API Consoleにて credentials画面からあなたのウェブアプリ用の client_secret.jsonファイルをダウンロードし、あなたのサーバがアクセスすることができる場所にそれを保存します。
  4. サーバサイドのアプリを再起動すると、あなたのゲームのクライアントアプリからリクエストを受け入れる準備が整います。

Google REST APIの呼び出しの詳細については、Authorizing and Using REST APIsを参照してください。

サーバ認証コードを取得する

あなたのゲームがあなたのバックエンドサーバ上のアクセストークンのために使用することができるサーバ認証コードを取得するには、プレイヤーがサインインに成功したときに Googleサインインが返す GoogleSignInAccountオブジェクトの getServerAuthCode()メソッドを呼び出します。

Here's an example:


// Auth code to send to backend server.
private String mServerAuthCode;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == RC_SIGN_IN) {
    GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
    if (result.isSuccess()) {
      mServerAuthCode = result.getSignInAccount().getServerAuthCode();
    } else {
      String message = result.getStatus().getStatusMessage();
      if (message == null || message.isEmpty()) {
        message = getString(R.string.signin_other_error);
      }
      new AlertDialog.Builder(this).setMessage(message)
          .setNeutralButton(android.R.string.ok, null).show();
    }
  }
}

サーバ認証コードをサーバ上のアクセストークンと交換する

アクセスおよび更新トークンを交換するために、あなたのバックエンドサーバにサーバ認証コードを送信します。 プレイヤーに代わって Google Playゲームサービス APIを呼び出すためにアクセストークンを使用し、必要に応じて、アクセストークンが失効したときに新しいアクセストークンを受け入れるために、更新トークンを格納します。

次のコードスニペットは、サーバ認証コードをアクセストークンと交換するために、Javaプログラミング言語にてサーバサイドのコードを実装する方法を示しています。

/**
 * 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;
}

サインインプレイヤーの代わりにバックエンドサーバから Google APIにアクセスする方法の詳細については、Enabling Server-Side Accessを参照してください。

プレイヤーのサインアウトを処理する

あなたのゲームからプレイヤーをサインアウトさせるには、GoogleSignInClient上の signOut()メソッドを呼び出します。 コードスニペットの例については、プレイヤーをサインアウトさせるを参照してください。