リンク済みアカウント ログインを使用すると、サービスに Google アカウントをすでにリンクしているユーザーに対して Google でワンタップ ログインを有効にできます。これにより、ユーザー名とパスワードを再入力することなく、ワンクリックでログインできるため、ユーザー エクスペリエンスが向上します。また、ユーザーがサービスで重複するアカウントを作成する可能性も低くなります。
リンクされたアカウントによるログインは、Android のワンタップ ログイン フローの一部として利用できます。つまり、アプリでワンタップ機能がすでに有効になっている場合は、別のライブラリをインポートする必要はありません。
このドキュメントでは、リンクされたアカウントのログインをサポートするように Android アプリを変更する方法について説明します。
仕組み
- ワンタップ ログイン フローでリンク済みアカウントを表示するようにオプトインします。
- ユーザーが Google にログインしていて、Google アカウントをサービス上のアカウントにリンクしている場合、リンクされたアカウントの ID トークンが返されます。
- ユーザーに、リンクされたアカウントでサービスにログインするオプションを含む One Tap ログイン プロンプトが表示されます。
- ユーザーがリンクされたアカウントで続行することを選択すると、ユーザーの ID トークンがアプリに返されます。このトークンを、ステップ 2 でサーバーに送信されたトークンと照合して、ログインしたユーザーを識別します。
設定
開発環境をセットアップする
開発ホストに最新の Google Play 開発者サービスを入手します。
- Android SDK Manager を開きます。
[SDK Tools] で [Google Play 開発者サービス] を見つけます。
これらのパッケージのステータスが [インストール済み] でない場合は、両方を選択し、[パッケージをインストール] をクリックします。
アプリを構成する
プロジェクト レベルの
build.gradle
ファイルで、buildscript
セクションとallprojects
セクションの両方に Google の Maven リポジトリを含めます。buildscript { repositories { google() } } allprojects { repositories { google() } }
「Link with Google」API の依存関係をモジュールのアプリレベルの Gradle ファイル(通常は
app/build.gradle
)に追加します。dependencies { implementation 'com.google.android.gms:play-services-auth:21.3.0' }
リンクされたアカウントでのログインをサポートするように Android アプリを変更する
リンクされたアカウントのログイン フローの終了時に、ID トークンがアプリに返されます。ユーザーをログインさせる前に、ID トークンの完全性を確認する必要があります。
次のコードサンプルは、ID トークンを取得して確認し、その後ユーザーをログインさせる手順を示しています。
ログイン インテントの結果を受け取るアクティビティを作成する
Kotlin
private val activityResultLauncher = registerForActivityResult( ActivityResultContracts.StartIntentSenderForResult()) { result -> if (result.resultCode == RESULT_OK) { try { val signInCredentials = Identity.signInClient(this) .signInCredentialFromIntent(result.data) // Review the Verify the integrity of the ID token section for // details on how to verify the ID token verifyIdToken(signInCredential.googleIdToken) } catch (e: ApiException) { Log.e(TAG, "Sign-in failed with error code:", e) } } else { Log.e(TAG, "Sign-in failed") } }
Java
private final ActivityResultLauncher<IntentSenderResult> activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), result -> { If (result.getResultCode() == RESULT_OK) { try { SignInCredential signInCredential = Identity.getSignInClient(this) .getSignInCredentialFromIntent(result.getData()); verifyIdToken(signInCredential.getGoogleIdToken()); } catch (e: ApiException ) { Log.e(TAG, "Sign-in failed with error:", e) } } else { Log.e(TAG, "Sign-in failed") } });
ログイン リクエストを作成する
Kotlin
private val tokenRequestOptions = GoogleIdTokenRequestOptions.Builder() .supported(true) // Your server's client ID, not your Android client ID. .serverClientId(getString("your-server-client-id") .filterByAuthorizedAccounts(true) .associateLinkedAccounts("service-id-of-and-defined-by-developer", scopes) .build()
Java
private final GoogleIdTokenRequestOptions tokenRequestOptions = GoogleIdTokenRequestOptions.Builder() .setSupported(true) .setServerClientId("your-service-client-id") .setFilterByAuthorizedAccounts(true) .associateLinkedAccounts("service-id-of-and-defined-by-developer", scopes) .build()
ログイン保留中のインテントを起動する
Kotlin
Identity.signInClient(this) .beginSignIn( BeginSignInRequest.Builder() .googleIdTokenRequestOptions(tokenRequestOptions) .build()) .addOnSuccessListener{result -> activityResultLauncher.launch(result.pendingIntent.intentSender) } .addOnFailureListener {e -> Log.e(TAG, "Sign-in failed because:", e) }
Java
Identity.getSignInClient(this) .beginSignIn( BeginSignInRequest.Builder() .setGoogleIdTokenRequestOptions(tokenRequestOptions) .build()) .addOnSuccessListener(result -> { activityResultLauncher.launch( result.getPendingIntent().getIntentSender()); }) .addOnFailureListener(e -> { Log.e(TAG, "Sign-in failed because:", e); });
ID トークンの完全性を確認する
Google API クライアント ライブラリを使用する
本番環境で Google ID トークンを検証する場合は、Java Google API クライアント ライブラリを使用することをおすすめします。
Java
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
...
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
// Specify the CLIENT_ID of the app that accesses the backend:
.setAudience(Collections.singletonList(CLIENT_ID))
// Or, if multiple clients access the backend:
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
.build();
// (Receive idTokenString by HTTPS POST)
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken != null) {
Payload payload = idToken.getPayload();
// Print user identifier
String userId = payload.getSubject();
System.out.println("User ID: " + userId);
// Get profile information from payload
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
// Use or store profile information
// ...
} else {
System.out.println("Invalid ID token.");
}
GoogleIdTokenVerifier.verify()
メソッドは、JWT 署名、aud
クレーム、iss
クレーム、exp
クレームを検証します。
ID トークンが Google Workspace または Cloud 組織アカウントを表すことを確認する必要がある場合は、Payload.getHostedDomain()
メソッドから返されたドメイン名を確認することで、hd
クレームを検証できます。