GoogleAuthUtilおよび Plus.APIからマイグレーションする



  • この記事は、Google Sign-In for Android に関する記事を和訳したものです。
  • 原文: Migrate from GoogleAuthUtil and Plus.API
  • 元記事のライセンスは CC-BYで、この和訳記事のライセンスは CC-BYです。
  • 自己責任でご利用ください。
  • 和訳した時期は 2019年6月ころです。

もし、GoogleAuthUtil.getTokenあるいは Plus.APIを使用して過去に Googleサインインと統合したならば、より良いセキュリティおよびより良いユーザエクスペリエンスのために、最新のサインイン APIにマイグレーションする必要があります。

アクセストーンのアンチパターンからマイグレーションする

GoogleAuthUtil.getTokenを用いて取得したアクセストーンを、IDアサーションとしてあなたのバックエンドサーバに送信すべきではありません、トークンがあなたのバックエンドに発行されたことを簡単に検証することはできないので、攻撃者からのアクセストーンの挿入に対して脆弱なままとなります。

例えば、あなたの Androidコードが以下の例のようになっているならば、あなたのアプリを現在のベストプラクティスにマイグレーションする必要があります。

Android code

この例では、アクセストーンは、GoogleAuthUtil.getToken呼び出しのための scopeパラメータとして、oauth2:と、スコープ文字列を使用します(oauth2:https://www.googleapis.com/auth/plus.login)。

GoogleAuthUtil.getTokenを用いて受け取るアクセストークンを用いて認証する代わりに、IDトークンフローあるいは認証コードフローのいずれかを使用してください。

IDトークンフローにマイグレーションする

もし、ユーザの ID、電子メールアドレス、名前、あるいはプロファイル写真の URLが必要とするすべてであるならば、IDトークンフローを使用します。

IDトークンフローにマイグレーションするには、以下の変更を行います:

Androidクライアント側

  • もしそれをリクエストしているならば、GET_ACCOUNTS(Contacts)パーミッションを削除します
  • GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()、あるいは AccountManager.newChooseAccountIntent()を使用しているコードを、GoogleSignInOptions.Builder.requestIdToken(...) 構成を用いた Auth.GOOGLE_SIGN_IN_APIに切り替えます。

サーバ側

  • IDトークン認証のための新しいエンドポイントを作成します
  • あなたのクライアントアプリがマイグレーションされた後、古いエンドポイントをオフにします

サーバ認証コードフローにマイグレーションする

もし、あなたのサーバが、Google Drive、Youtube、あるいは、Contactsといった、他の Google APIにアクセスすることを必要とするならば、サーバ認証コードフローを使用します。

サーバ認証コードフローにマイグレーションするには、以下の変更を行います:

Androidクライアント側

  • もしそれをリクエストしているならば、GET_ACCOUNTS(Contacts)パーミッションを削除します
  • GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()、あるいは AccountManager.newChooseAccountIntent()を使用しているコードを、GoogleSignInOptions.Builder.requestServerAuthCode(...) 構成を用いた Auth.GOOGLE_SIGN_IN_APIに切り替えます。

サーバ側

  • サーバ認証コードフローのための新しいエンドポイントを作成します。
  • あなたのクライアントアプリがマイグレーションされた後、古いエンドポイントをオフにします

あなたの古い、および、新しいエンドポイントの間で、まだ APIアクセスロジックを共有することができます。 例えば:

GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(...);
String accessToken = tokenResponse.getAccessToken();
String refreshToken = tokenResponse.getRefreshToken();
Long expiresInSeconds = tokenResponse.getExpiresInSeconds();

// Shared by your old and new implementation, old endpoint can pass null for refreshToken
private void driveAccess(String refreshToken, String accessToken, Long expiresInSeconds) {
   GoogleCredential credential = new GoogleCredential.Builder()
           .setTransPort(...)
           ...
           .build();
   credential.setAccessToken(accessToken);
   credential.setExpiresInSeconds(expiresInSeconds);
   credential.setRefreshToken(refreshToken);
}

GoogleAuthUtil IDトークンフローからマイグレーションする

もし、IDトークンを取得するために GoogleAuthUtilを使用しているならば、新しいサインイン APIのIDトークンフローにマイグレーションする必要があります。

例えば、もしあなたの Androidコードが次の例のようになっているならば、マイグレーションする必要があります:

Android code

この例では、IDトークンのリクエストは、GoogleAuthUtil.getToken 呼び出しのための ‘scope’ パラメータとして、audience:server:client_id と、あなたのウェブサーバのためのクライアント IDを使用します(audience:server:client_id:9414861317621.apps.googleusercontent.com)。

新しいサインイン APIの IDトークンフローは、次の利点を持っています:

  • 合理化された、ワンタップのサインインエクスペリエンス
  • あなたのサーバは、追加のネットワーク呼び出しなしでユーザのプロファイル情報を取得することができる

IDトークンフローにマイグレーションするには、以下の変更を行います:

Androidクライアント側

  • もしそれをリクエストしているならば、GET_ACCOUNTS(Contacts)パーミッションを削除します
  • GoogleAuthUtil、code>Plus.API、AccountPicker.newChooseAccountIntent()、あるいは AccountManager.newChooseAccountIntent()を使用しているコードを、GoogleSignInOptions.Builder.requestIdToken(...) 構成を用いた Auth.GOOGLE_SIGN_IN_APIに切り替えます。

サーバ側

新しいサインイン APIは、OpenID Connect仕様に準拠した IDトークンを発行します、それは、GoogleAuthUtil.getTokenとは異なります、それは、廃止予定の形式を使用しています。 特に、発行者は、今や https://accounts.google.comになります、それは、httpsスキーマを伴います。

あなたのマイグレーションプロセス中に、あなたのサーバは、あなたの古い、および、新しい Androidクライアントの両方からの IDトークンを検証する必要があります。 両方のトークンの形式を検証するには、使用するクライアントライブラリに対応する変更を行います(それを使用している場合):

  • Java (Google APIs Client Libraries): 1.21.0以降にアップグレードする
  • PHP (Google APIs Client Libraries): もし v1を使用しているならば、1.1.6以降にアップグレードする; もし v2を使用しているならば、2.0.0-R1以降にアップグレードする
  • Node.js: 0.9.7以降にアップグレードする
  • Pythonあるいは独自の実装: https://accounts.google.comaccounts.google.comの両方の発行者を受け入れる

GoogleAuthUtilサーバ認証コードフローからマイグレーションする

もし、サーバ認証コードを取得するために GoogleAuthUtilを使用しているならば、新しいサインイン APIの認証コードフローにマイグレーションする必要があります。

例えば、もしあなたの Androidアプリが次の例のようになっているならば、マイグレーションする必要があります:

Android code

この例では、サーバ認証コードのリクエストは、GoogleAuthUtil.getToken 呼び出しのための scope パラメータとして、oauth2:server:client_id と、あなたのウェブサーバのためのクライアント IDを使用します(oauth2:server:client_id:9414861317621.apps.googleusercontent.com)。

新しいサインイン APIの ID認証コードフローは、次の利点を持っています:

  • 合理化された、ワンタップのサインインエクスペリエンス
  • もし以下のマイグレーションガイドに従うならば、認証コードを交換するとき、ユーザのプロファイル情報を含んでいる IDトークンを取得することができます

新しい認証コードフローにマイグレーションするには、以下の変更を行います:

Androidクライアント側

  • もしそれをリクエストしているならば、GET_ACCOUNTS(Contacts)パーミッションを削除します
  • GoogleAuthUtilPlus.APIAccountPicker.newChooseAccountIntent()、あるいは AccountManager.newChooseAccountIntent()を使用しているコードを、GoogleSignInOptions.Builder.requestServerAuthCode(...) 構成を伴う Auth.GOOGLE_SIGN_IN_APIに切り替えます。

サーバ側

あなたの現在のコードを維持します、ただし、GoogleAuthorizationCodeTokenRequestオブジェクトを構築するとき、トークンサーバのエンドポイントとして https://www.googleapis.com/oauth2/v4/tokenを指定します、そうすれば、別のネットワーク呼び出しを必要とせずに、ユーザの電子メール、ユーザ ID、およびプロファイル情報を取得することができます。 このエンドポイントは完全に後方互換性があり、以下のコードは、あなたの古い、および新しい Androidクライアントの実装から取得されたサーバ認証コードに対して動作するでしょう。

GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(
                transport,
                jsonFactory,
                // Use below for tokenServerEncodedUrl parameter
                "https://www.googleapis.com/oauth2/v4/token",
                clientSecrets.getDetails().getClientId(),
                clientSecrets.getDetails().getClientSecret(),
                authCode,
                REDIRECT_URI)
               .execute();

...

// You can also get an ID token from auth code exchange.
GoogleIdToken googleIdToken = tokenResponse.parseIdToken();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
        .setAudience(Arrays.asList(SERVER_CLIENT_ID))
        .setIssuer("https://accounts.google.com")
        .build();
// Refer to ID token documentation to see how to get data from idToken object.
GoogleIdToken idToken = verifier.verify(idTokenString);
...