[この記事は Laurence Moroney 、デベロッパー アドボケートによる Android Developers Blog の記事 "Using Credentials between your Server and Google Services " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]
本記事は、Google Sign-In に関するシリーズの第 4 回です。このシリーズは、Google Play サービス 8.3 の開始とともに投稿されたユーザー エクスペリエンスの改善 に関する記事から始まりました。第 2 回の記事では、プログラミング モデルをより簡単にする、API の更新 について取り上げました。また、前回第 3 回の記事では、バックエンドのサーバーで Google Sign-In を使ってユーザーを認証する方法 をご紹介しました。
今回は、サインインしたアプリのサービスをユーザーが認可することによって、Google ドライブなどの Google API にアクセスできるようにする方法について説明します。
Google Sign-In を使うと、ユーザーが料理の写真を撮って Google ドライブに保存するというような、Google と連携するアプリを簡単に作成することができます。これを実現するには、サインイン後に API へのアクセスに必要なスコープを追加で要求します。通常、このアクセスは(最初のサインインと同時ではなく)必要に応じて要求します。つまり、ユーザー エクスペリエンスのベストプラクティス に従い、ユーザーが実行するアクションの最中(たとえば、オーダーした食事がテーブルに届き、アプリのユーザーが Google ドライブに保存するために写真を撮ろうとしたタイミング)に要求します。このタイミングでスコープを要求することで、アクセスが許可される可能性が最も高くなり、Android Marshmallow 6.0 のランタイム パーミッション モデル とも一致します。
このような連携を行う場合は、ユーザーがアプリを利用していなくても継続してサーバーがアクセスできるようにしたり、ユーザーが作成したデータを自身のデータベースに格納するといった目的で、サーバーのデータにアクセスすることが多くなります。このフローを図で示すと下記の図 1 のようになります。これには、すべてのプラットフォームで動作するという利点もあります。
図 1. クレデンシャルを使った Google サービスへのアクセス
実現するには、以下のステップを実行します。
ステップ 1 : サーバー認証のシナリオは第 3 回 の記事で説明したので、このサンプル では Android アプリの標準的なコードを示します。特に ServerAuthCodeActivity に注目してください。
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
// The serverClientId is an OAuth 2.0 web client ID
// Details at: https://developers.google.com/identity/sign-in/android/?utm_campaign=android_discussion_server_021116&utm_source=anddev&utm_medium=blogstart step 4
.requestServerAuthCode(serverClientId)
.requestEmail()
.build();
実行するには、サーバーのウェブ クライアント ID が必要になります。取得方法についての詳細は、こちら をご覧ください(ステップ 4 を参照)。
実行すると、スコープ DRIVE_APPFOLDER が要求され、Google ドライブへのアクセスをアプリに許可するかを問うメッセージが表示され、Auth Code も要求されます。
サインインが成功すると、次のようにしてアカウント オブジェクトから Auth Code を取得することができます。
if (result.isSuccess()) {
GoogleSignInAccount acct = result.getSignInAccount();
String authCode = acct.getServerAuthCode();
}
(ここ で示したサンプルの onActivityResult からの引用です)
次に、この Auth Code を HTTPS POST を使ってサーバーに送信します。Auth Code の交換が終わると、ユーザーの Google ドライブにアクセスできる状態になります[重要:アクティブなユーザーによる正当な要求であることを保証するため、Auth Code は認証済みのリクエストでバックエンドに送信するようにしてください]。
ステップ 2 : GoogleAuthorizationCodeTokenRequest クラスを使い、サーバー上で Auth Code を Token と交換します。
// Set path to the Web application client_secret_*.json file you downloaded from the
// Google Developers Console: https://console.developers.google.com/project/_/apiui/credential
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json" ; // Be careful not to share this!
String REDIRECT_URI = "/path/to/web_app_redirect" // Can be empty if you don’t use web redirects
// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
GoogleClientSecrets .load(
JacksonFactory .getDefaultInstance(), new FileReader (CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest (
new NetHttpTransport (),
JacksonFactory .getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token" ,
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
REDIRECT_URI)
.execute();
String accessToken = tokenResponse.getAccessToken();
String refreshToken = tokenResponse.getRefreshToken();
Long expiresInSeconds = tokenResponse.getExpiresInSeconds();
// You can also get an ID token from the exchange result if basic profile scopes are requested
// e.g. starting GoogleSignInOptions.Builder from GoogleSignInOptions.DEFAULT_SIGN_IN like the
// sample code as used here: http://goo.gl/0Unpq8
//
// GoogleIdToken googleIdToken = tokenResponse.parseIdToken();
続いて、GoogleTokenResponse から発行された Token を使い、GoogleCredential オブジェクトを作成します。
GoogleCredential credential = new GoogleCredential .Builder ()
.setTransport(new NetHttpTransport ())
.setJsonFactory(JacksonFactory .getDefaultInstance())
.setClientSecrets(clientSecrets)
.build();
credential.setAccessToken(accessToken);
credential.setExpiresInSeconds(expiresInSeconds);
credential.setRefreshToken(refreshToken);
Refresh Token が利用可能で、ユーザーがサインインし直すことなく API にアクセスできるようにしたい場合は、StoredCredential を使って資格情報を保存し、再利用することができます。
ステップ 3: 取得した資格情報を使って、Google サービスにアクセスします。先ほどから挙げている食事のシナリオでいえば、運ばれてきた料理やレシートの写真を Google ドライブに保存したり、そこから取り出したりすることができます。これを行うには、たとえば次のようなコードを記述します。
Drive drive = new Drive .Builder (new NetHttpTransport (),
JacksonFactory .getDefaultInstance(),
credential)
.setApplicationName("Auth Code Exchange Demo" )
.build();
File file = drive.files().get ("appfolder" ).execute();
今回は、サーバーから Google API を呼び出すことによって、ユーザーの Google Sign-In 資格情報を使用する方法について説明しました。この手法や Google Sign-In テクノロジーの詳細については、Google Identity Platform ウェブサイトにアクセスしてください。
Posted by Eiji Kitamura - Developer Relations Team