ワンタップサインインクライアントを使用して、ユーザーがアプリへのサインインに以前使用した資格情報の1つを取得するための許可をユーザーに要求します。これらのクレデンシャルは、Googleアカウント、またはChrome、Androidオートフィル、またはSmart Lock forPasswordsを使用してGoogleで保存したユーザー名とパスワードの組み合わせのいずれかです。
クレデンシャルが正常に取得されると、クレデンシャルを使用して、ユーザーをアプリにスムーズにサインインできます。
ユーザーが資格情報を保存していない場合、UIは表示されず、通常のサインアウトエクスペリエンスを提供できます。
ワンタップサインインはどこで使用すればよいですか?
アプリでユーザーがサインインする必要がある場合は、サインイン画面にワンタップUIを表示します。これは、[Googleでログイン]ボタンが既にある場合でも役立ちます。ワンタップUIは、以前にログインに使用したユーザーのクレデンシャルのみを表示するように構成できるため、ログイン頻度が低いユーザーに通知することができます。前回のログイン方法を確認し、アプリで誤って新しいアカウントを作成するのを防ぎます。
アプリでサインインがオプションの場合は、サインインによってエクスペリエンスが向上する画面でワンタップサインインを使用することを検討してください。たとえば、ユーザーがサインアウト中にアプリでコンテンツを閲覧できるが、コメントや投稿しかできない場合サインイン後にショッピングカートにアイテムを追加します。これは、ワンタップサインインの賢明なコンテキストです。
サインインオプションアプリも、上記の理由により、サインイン画面でワンタップサインインを使用する必要があります。
あなたが始める前に
- で説明したようにGoogle APIコンソールプロジェクトとAndroidプロジェクトを設定ワンタップサインインを使ってみましょう。
- パスワードベースのサインインをサポートする場合は、オートフィルのためにアプリを最適化し、ユーザーがサインインした後にパスワードの資格情報を保存することができるように(またはスマートロックは、パスワードに使用)。
1.ワンタップサインインクライアントを構成します
保存されたパスワード、保存されたGoogleアカウント、またはそのいずれかを使用してユーザーにサインインするように、ワンタップサインインクライアントを構成できます。 (新しいユーザーにはワンタップアカウントを作成し、できるだけ多くのリピーターには自動またはワンタップサインインを有効にするために、両方をサポートすることをお勧めします。)
あなたのアプリは、パスワードベースのサインインの使用、使用している場合setPasswordRequestOptions()
パスワード資格の要求を可能にします。
あなたのアプリは、Googleのサインインの使用、使用している場合setGoogleIdTokenRequestOptions()
GoogleのIDトークンの要求を有効にして設定するには:
サーバクライアントIDを設定しては、Google APIコンソールで作成されたID 。これはサーバーのクライアントIDであり、AndroidクライアントIDではないことに注意してください。
承認されたアカウントでフィルタリングするようにクライアントを構成します。このオプションを有効にすると、ワンタップクライアントは、ユーザーが過去に使用したGoogleアカウントでアプリにログインするように求めるだけです。そうすることで、ユーザーが既にアカウントを持っているかどうか、または使用したGoogleアカウントがわからない場合にユーザーが正常にログインできるようになり、ユーザーがアプリで誤って新しいアカウントを作成するのを防ぐことができます。
あなたが可能な場合、自動的にユーザーに署名したい場合は、して機能を有効にする
setAutoSelectEnabled()
。次の基準が満たされている場合、自動サインインが可能です。- ユーザーは、アプリ用に保存されたクレデンシャルを1つだけ持っています。つまり、1つの保存されたパスワードまたは1つの保存されたGoogleアカウントです。
- ユーザーは、自動サインイン自分で無効にしていないGoogleアカウントの設定を。
オプションですが、サインインのセキュリティを向上させ、リプレイ攻撃を回避するために、ナンスの使用を強く検討することをお勧めします。使用setNonceを各要求でnonceを含めること。 SAFETYNETの参照ナンスの入手ナンスを生成する上での提案と追加の詳細についてのセクションを。
Java
public class YourActivity extends AppCompatActivity { // ... private SignInClient oneTapClient; private BeginSignInRequest signInRequest; @Override public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) { super.onCreate(savedInstanceState, persistentState); oneTapClient = Identity.getSignInClient(this); signInRequest = BeginSignInRequest.builder() .setPasswordRequestOptions(PasswordRequestOptions.builder() .setSupported(true) .build()) .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder() .setSupported(true) // Your server's client ID, not your Android client ID. .setServerClientId(getString(R.string.default_web_client_id)) // Only show accounts previously used to sign in. .setFilterByAuthorizedAccounts(true) .build()) // Automatically sign in when exactly one credential is retrieved. .setAutoSelectEnabled(true) .build(); // ... } // ... }
Kotlin
class YourActivity : AppCompatActivity() { // ... private lateinit var oneTapClient: SignInClient private lateinit var signInRequest: BeginSignInRequest override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) oneTapClient = Identity.getSignInClient(this) signInRequest = BeginSignInRequest.builder() .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder() .setSupported(true) .build()) .setGoogleIdTokenRequestOptions( BeginSignInRequest.GoogleIdTokenRequestOptions.builder() .setSupported(true) // Your server's client ID, not your Android client ID. .setServerClientId(getString(R.string.your_web_client_id)) // Only show accounts previously used to sign in. .setFilterByAuthorizedAccounts(true) .build()) // Automatically sign in when exactly one credential is retrieved. .setAutoSelectEnabled(true) .build() // ... } // ... }
2.サインインしたユーザーを確認します
サインインしたユーザーまたはサインアウトしたユーザーがアクティビティを使用できる場合は、ワンタップサインインUIを表示する前に、ユーザーのステータスを確認してください。
また、プロンプトを閉じるか、プロンプトの外側をタップして、ユーザーがワンタップサインインの使用をすでに拒否しているかどうかを追跡する必要があります。これは、アクティビティのブールプロパティと同じくらい簡単です。 (参照ワンタップUIの表示を停止以下、。)
3.ワンタップサインインUIを表示します
ユーザーが署名されていないと、すでにワンタップサインインを使用して低下していない場合は、クライアントオブジェクトの呼び出しbeginSignIn()
メソッドを、とにリスナーを添付してTask
、それが返されます。アプリは、通常の活動の中でこれを行うonCreate()
メソッドまたはシングルアクティビティアーキテクチャを使用するときに画面遷移した後。
ユーザーがアプリの保存済みクレデンシャルを持っている場合、ワンタップクライアントは成功リスナーを呼び出します。成功リスナーでは、保留中から意図を取得するTask
結果とに渡しstartIntentSenderForResult()
ワンタップサインインUIを開始します。
ユーザーが保存された資格情報を持っていない場合、ワンタップクライアントは失敗リスナーを呼び出します。この場合、アクションは必要ありません。アプリのサインアウトエクスペリエンスを引き続き表示できます。ただし、ワンタップサインアップをサポートしている場合は、ここからそのフローを開始して、シームレスなアカウント作成エクスペリエンスを実現できます。参照してください。 1つのタップを持つ新たなアカウントを作成します。
Java
oneTapClient.beginSignIn(signUpRequest)
.addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
@Override
public void onSuccess(BeginSignInResult result) {
try {
startIntentSenderForResult(
result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.getLocalizedMessage());
}
});
Kotlin
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this) { result ->
try {
startIntentSenderForResult(
result.pendingIntent.intentSender, REQ_ONE_TAP,
null, 0, 0, 0, null)
} catch (e: IntentSender.SendIntentException) {
Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnFailureListener(this) { e ->
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.localizedMessage)
}
4.ユーザーの応答を処理します
ワンタップサインインプロンプトに対するユーザの応答は、あなたの活動の使ってアプリに報告されますonActivityResult()
メソッドを。ユーザーがサインインすることを選択した場合、結果は保存されたクレデンシャルになります。ユーザーがいずれか、でワンタップUIを閉じたり、その外側をタップして署名することを拒否した場合、結果はコードを返しますRESULT_CANCELED
。アプリは両方の可能性を処理する必要があります。
取得した資格情報を使用してサインインします
ユーザーがアプリで共有資格情報を選択した場合、あなたはから意図データを渡すことによって、それらを取得することができますonActivityResult()
ワンタップクライアントのにgetSignInCredentialFromIntent()
メソッド。資格はnull以外になりますgoogleIdToken
ユーザーがあなたのアプリとGoogleアカウントの資格情報、またはnull以外の共有場合はプロパティをpassword
、ユーザーが保存したパスワードを共有した場合の特性を。
クレデンシャルを使用して、アプリのバックエンドで認証します。
- ユーザー名とパスワードのペアが取得された場合は、ユーザーが手動で指定した場合と同じ方法で、それらを使用して署名します。
Googleアカウントのクレデンシャルが取得された場合は、IDトークンを使用してバックエンドで認証します。リプレイ攻撃を回避するためにナンスを使用することを選択した場合は、バックエンドサーバーの応答値を確認してください。参照IDトークンを使用してバックエンドで認証を。
Java
public class YourActivity extends AppCompatActivity { // ... private static final int REQ_ONE_TAP = 2; // Can be any integer unique to the Activity. private boolean showOneTapUI = true; // ... @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQ_ONE_TAP: try { SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data); String idToken = credential.getGoogleIdToken(); String username = credential.getId(); String password = credential.getPassword(); if (idToken != null) { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token."); } else if (password != null) { // Got a saved username and password. Use them to authenticate // with your backend. Log.d(TAG, "Got password."); } } catch (ApiException e) { // ... } break; } } }
Kotlin
class YourActivity : AppCompatActivity() { // ... private val REQ_ONE_TAP = 2 // Can be any integer unique to the Activity private var showOneTapUI = true // ... override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { REQ_ONE_TAP -> { try { val credential = oneTapClient.getSignInCredentialFromIntent(data) val idToken = credential.googleIdToken val username = credential.id val password = credential.password when { idToken != null -> { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token.") } password != null -> { // Got a saved username and password. Use them to authenticate // with your backend. Log.d(TAG, "Got password.") } else -> { // Shouldn't happen. Log.d(TAG, "No ID token or password!") } } } catch (e: ApiException) { // ... } } } } // ... }
ワンタップUIの表示を停止する
ユーザーがサインインを拒否した場合は、への呼び出しgetSignInCredentialFromIntent()
スローされますApiException
とCommonStatusCodes.CANCELED
ステータスコードを。これが発生した場合は、ワンタップサインインUIを一時的に無効にして、プロンプトが繰り返されることでユーザーを煩わせないようにする必要があります。次の例では、アクティビティにプロパティを設定することでこれを実現しています。このプロパティを使用して、ユーザーにワンタップサインインを提供するかどうかを決定します。しかし、あなたはまたに値を保存することができSharedPreferences
またはいくつかの他の方法を使用します。
ワンタップサインインプロンプトの独自のレート制限を実装することが重要です。そうしないと、ユーザーが連続して複数のプロンプトをキャンセルした場合、OneTapクライアントは次の24時間ユーザーにプロンプトを表示しません。
Java
public class YourActivity extends AppCompatActivity { // ... private static final int REQ_ONE_TAP = 2; // Can be any integer unique to the Activity. private boolean showOneTapUI = true; // ... @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQ_ONE_TAP: try { // ... } catch (ApiException e) { switch (e.getStatusCode()) { case CommonStatusCodes.CANCELED: Log.d(TAG, "One-tap dialog was closed."); // Don't re-prompt the user. showOneTapUI = false; break; case CommonStatusCodes.NETWORK_ERROR: Log.d(TAG, "One-tap encountered a network error."); // Try again or just ignore. break; default: Log.d(TAG, "Couldn't get credential from result." + e.getLocalizedMessage()); break; } } break; } } }
Kotlin
class YourActivity : AppCompatActivity() { // ... private val REQ_ONE_TAP = 2 // Can be any integer unique to the Activity private var showOneTapUI = true // ... override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { REQ_ONE_TAP -> { try { // ... } catch (e: ApiException) { when (e.statusCode) { CommonStatusCodes.CANCELED -> { Log.d(TAG, "One-tap dialog was closed.") // Don't re-prompt the user. showOneTapUI = false } CommonStatusCodes.NETWORK_ERROR -> { Log.d(TAG, "One-tap encountered a network error.") // Try again or just ignore. } else -> { Log.d(TAG, "Couldn't get credential from result." + " (${e.localizedMessage})") } } } } } } // ... }
5.サインアウトを処理します
ユーザーがサインアプリのうち一つをタップクライアントの呼び出すとsignOut()
メソッドを。呼び出しsignOut()
自動サインインを再びユーザーがサインインするまで無効になります。
自動サインインを使用しない場合でも、ユーザーがアプリからサインアウトすると、使用するPlayサービスAPIの認証状態もリセットされるため、この手順は重要です。
次のステップ
Googleクレデンシャルを取得するようにワンタップクライアントを構成した場合、アプリはユーザーのGoogleアカウントを表すGoogleIDトークンを取得できるようになりました。あなたができる方法を学びバックエンドでこれらのトークンを使用します。
あなたはGoogleのサインインをサポートしている場合、あなたはまたしてワンタップクライアントを使用することができる摩擦アカウント作成アプリに流れる追加します。