ユーザーに保存された認証情報を取得する

Credentials API を使用してユーザーを自動的にアプリにログインし、保存されている認証情報をリクエストして取得します。

始める前に

Android Studio プロジェクトを構成する

CredentialsClient オブジェクトを作成する

保存されている認証情報をリクエストするには、CredentialsClient のインスタンスを作成して Credentials API にアクセスする必要があります。

CredentialsClient mCredentialsClient;

// ...

mCredentialsApiClient = Credentials.getClient(this);

CredentialRequest オブジェクトを作成する

CredentialRequest オブジェクトは、認証情報をリクエストするログイン システムを指定します。パスワード ベースのログインには setPasswordLoginSupported メソッドを使用し、Google ログインなどのフェデレーション ログイン サービスには setAccountTypes() メソッドを使用して、CredentialRequest を作成します。

mCredentialRequest = new CredentialRequest.Builder()
    .setPasswordLoginSupported(true)
    .setAccountTypes(IdentityProviders.GOOGLE, IdentityProviders.TWITTER)
    .build();

IdentityProviders で定義されている定数を使用して、よく使用されるログイン プロバイダを指定します。他のログイン プロバイダの場合は、プロバイダを一意に識別する任意の文字列を使用します。認証情報の保存には、認証情報の取得に使用したものと同じプロバイダ ID を使用する必要があります。

保存されている認証情報をリクエストする

CredentialsClient オブジェクトと CredentialRequest オブジェクトを作成したら、リクエスト オブジェクトを CredentialsClient.request() メソッドに渡して、アプリ用に保存されている認証情報をリクエストします。

  mCredentialsClient.request(mCredentialRequest).addOnCompleteListener(
      new OnCompleteListener<CredentialRequestResponse>() {
          @Override
          public void onComplete(@NonNull Task<CredentialRequestResponse> task) {

              if (task.isSuccessful()) {
                  // See "Handle successful credential requests"
                  onCredentialRetrieved(task.getResult().getCredential());
                  return;
              }

              // See "Handle unsuccessful and incomplete credential requests"
              // ...
          }
      });

addOnCompleteListener() メソッドを使用して、リクエストの処理の成功と失敗を処理するコールバックを定義します。

成功した認証情報リクエストを処理する

ログインに成功したことを示すトースト 認証情報リクエストが成功したら、生成される Credential オブジェクトを使用して、ユーザーのアプリへのログインを完了します。getAccountType() メソッドを使用して、取得した認証情報の種類を判別し、適切なログイン プロセスを完了します。たとえば Google ログインの場合、ユーザー ID を含む GoogleSignInClient オブジェクトを作成し、そのオブジェクトを使用してログインフローを開始します。パスワード ベースのログインの場合は、認証情報オブジェクトから取得したユーザーの ID とパスワードを使用して、アプリのログイン プロセスを完了します。

private void onCredentialRetrieved(Credential credential) {
    String accountType = credential.getAccountType();
    if (accountType == null) {
        // Sign the user in with information from the Credential.
        signInWithPassword(credential.getId(), credential.getPassword());
    } else if (accountType.equals(IdentityProviders.GOOGLE)) {
        // The user has previously signed in with Google Sign-In. Silently
        // sign in the user with the same ID.
        // See https://developers.google.com/identity/sign-in/android/
        GoogleSignInOptions gso =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .requestEmail()
                        .build();

        GoogleSignInClient signInClient = GoogleSignIn.getClient(this, gso);
        Task<GoogleSignInAccount> task = signInClient.silentSignIn();
        // ...
    }
}

保存された複数の認証情報を処理する

Smart Lock のアカウント選択ツール

認証情報を選択するためにユーザー入力が必要な場合、request() タスクは ResolvableApiException で失敗します。getStatusCode()RESOLUTION_REQUIRED を返すことを確認し、例外の startResolutionForResult() メソッドを呼び出して、ユーザーにアカウントの選択を求めるプロンプトを表示します。次に、Credential.EXTRA_KEYgetParcelableExtra() メソッドに渡して、ユーザーが選択した認証情報をアクティビティの onActivityResult() メソッドから取得します。

mCredentialsClient.request(request).addOnCompleteListener(
        new OnCompleteListener() {
            @Override
            public void onComplete(@NonNull Task task) {
                if (task.isSuccessful()) {
                    // ...
                    return;
                }

                Exception e = task.getException();
                if (e instanceof ResolvableApiException) {
                    // This is most likely the case where the user has multiple saved
                    // credentials and needs to pick one. This requires showing UI to
                    // resolve the read request.
                    ResolvableApiException rae = (ResolvableApiException) e;
                    resolveResult(rae, RC_READ);
                } else if (e instanceof ApiException) {
                    // The user must create an account or sign in manually.
                    Log.e(TAG, "Unsuccessful credential request.", e);

                    ApiException ae = (ApiException) e;
                    int code = ae.getStatusCode();
                    // ...
                }
            }
        });
private void resolveResult(ResolvableApiException rae, int requestCode) {
    try {
        rae.startResolutionForResult(MainActivity.this, requestCode);
        mIsResolving = true;
    } catch (IntentSender.SendIntentException e) {
        Log.e(TAG, "Failed to send resolution.", e);
        hideProgress();
    }
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // ...

    if (requestCode == RC_READ) {
        if (resultCode == RESULT_OK) {
            Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
            onCredentialRetrieved(credential);
        } else {
            Log.e(TAG, "Credential Read: NOT OK");
            Toast.makeText(this, "Credential Read Failed", Toast.LENGTH_SHORT).show();
        }
    }

    // ...

}

保存されている認証情報が見つからない場合、ユーザーはアカウントを作成するか、手動でログインする必要があります。getStatusCode() から SIGN_IN_REQUIRED が返された場合は、必要に応じて登録プロセスとログイン プロセスを迅速化できます。これにより、最近使用したログイン情報(メールアドレスや名前など)を選択するようユーザーに促し、フォームの一部のフィールドにその情報を自動的に入力できます。 詳しくは、ユーザーにログインのヒントを提供するをご覧ください。

ログインが成功したら、ユーザーが認証情報を保存できるようにして、すべてのデバイスでの今後の認証を自動化できるようにします。