認証情報マネージャーで認証情報の復元を実装する

このページでは、復元キーの作成、復元キーを使用したログイン、復元キーの削除を行う方法について説明します。

バージョンの互換性

認証情報マネージャーの復元認証情報は、Android 9(API レベル 28)以降、Google Play 開発者サービス(GMS)コア バージョン 24220000 以降、androidx.credentials ライブラリのバージョン 1.5.0 以降を搭載したデバイスで動作します。

前提条件

パスキーのサーバーと同様の証明書利用者サーバーをセットアップします。パスキーによる認証を処理するようにサーバーがすでに設定されている場合は、復元キーに同じサーバーサイド実装を使用します。

依存関係

アプリ モジュールの build.gradle ファイルに次の依存関係を追加します。

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha02")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02")
}

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha02"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02"
}

Restore Credentials は、androidx.credentials ライブラリのバージョン 1.5.0 以降で利用できます。ただし、可能な限り、依存関係の最新の安定版を使用することをおすすめします。

概要

  1. 復元鍵を作成する: 復元鍵を作成するには、次の操作を行います。
    1. 認証情報マネージャーをインスタンス化する: CredentialManager オブジェクトを作成します。
    2. アプリサーバーから認証情報作成オプションを取得する: アプリサーバーから復元キーを作成するために必要な詳細情報をクライアント アプリに送信します。
    3. 復元キーを作成する: ユーザーがアプリにログインしている場合は、ユーザーのアカウントの復元キーを作成します。
    4. 認証情報の作成レスポンスを処理する: 認証情報をクライアント アプリからアプリサーバーに送信して処理し、例外を処理します。
  2. 復元キーでログインする: 復元キーでログインする手順は次のとおりです。
    1. アプリサーバーから認証情報の取得オプションを取得する: アプリサーバーから復元キーを取得するために必要な詳細情報をクライアント アプリに送信します。
    2. 復元キーを取得する: ユーザーが新しいデバイスをセットアップするときに、認証情報マネージャーに復元キーをリクエストします。これにより、ユーザーは追加の入力なしでログインできます。
    3. 認証情報の取得レスポンスを処理する: クライアント アプリからアプリサーバーに復元キーを送信して、ユーザーをログインさせます。
  3. 復元キーを削除する。

復元キーを作成する

アプリは、ユーザーがログインするすべてのケースをカバーし、アクティブ ユーザーに復元キーが作成されるようにする必要があります。次のシナリオで復元キーを作成します。

  • ユーザーがログインしていて、復元キーがまだ作成されていない場合(メインの Activity の onCreate メソッドなど)。
  • ユーザーがログインしているとき、または新しいアカウント登録フローを完了しているとき。

パフォーマンスを最適化し、ログインのたびに復元認証情報を作成または確認するオーバーヘッドを回避するには、boolean フラグまたは認証情報作成タイムスタンプをローカル ストレージ(has_synced_restore_credential など)に設定して、鍵がすでに作成されているかどうかを追跡します。

認証情報マネージャーをインスタンス化する

アプリのアクティビティ コンテキストを使用して、CredentialManager オブジェクトをインスタンス化します。

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

アプリサーバーから認証情報作成オプションを取得する

アプリサーバーで FIDO 準拠のライブラリを使用して、復元認証情報の作成に必要な情報(ユーザー、アプリ、追加の構成プロパティに関する情報など)をクライアント アプリに送信します。サーバーサイドの実装の詳細については、サーバーサイドのガイダンスをご覧ください。

復元キーを作成する

サーバーから送信された公開鍵作成オプションを解析したら、これらのオプションを CreateRestoreCredentialRequest オブジェクトにラップし、CredentialManager オブジェクトを指定して createCredential() メソッドを呼び出すことで、復元鍵を作成します。

// createRestoreRequest contains the details sent by the server 
val response = credentialManager.createCredential(context, createRestoreRequest)

コードに関する主なポイント

  • CreateRestoreCredentialRequest オブジェクトには次のフィールドがあります。

    • requestJson: PublicKeyCredentialCreationOptionsJSON の Web Authentication API 形式でアプリサーバーから送信される認証情報作成オプション。
    • isCloudBackupEnabled: Boolean フィールド。復元キーをクラウドにバックアップするかどうかを決定します。デフォルトでは、このフラグは true です。このフィールドには次の値が設定されます。

      • true: (推奨)この値は、ユーザーが Google バックアップとエンドツーエンドの暗号化(画面ロックなど)を有効にしている場合に、復元キーのクラウドへのバックアップを有効にします。
      • false: この値は、鍵をクラウドではなくローカルに保存します。ユーザーがクラウドから復元することを選択した場合、新しいデバイスでは鍵を使用できません。

認証情報の作成レスポンスを処理する

Credential Manager API は、CreateRestoreCredentialResponse タイプのレスポンスを返します。このレスポンスには、JSON 形式の公開鍵認証情報の登録レスポンスが含まれています。

アプリから証明書利用者サーバーに公開鍵を送信します。この公開鍵は、パスキーの作成時に生成される公開鍵に似ています。サーバーでパスキーの作成を処理する同じコードで、復元キーの作成も処理できます。サーバーサイドの実装について詳しくは、パスキーのガイダンスをご覧ください。

復元キーの作成プロセス中に、次の例外を処理します。

  • CreateRestoreCredentialDomException: requestJson が無効で、PublicKeyCredentialCreationOptionsJSON の WebAuthn 形式に準拠していない場合に発生します。
  • E2eeUnavailableException: この例外は、isCloudBackupEnabled が true であるにもかかわらず、ユーザーのデバイスにデータ バックアップやエンドツーエンドの暗号化(画面ロックなど)がない場合に発生します。
    すべてのケースで復元認証情報が作成されるようにするには、isCloudBackupEnabled を true に設定して createCredential を呼び出し、E2eeUnavailableException を明示的に処理する必要があります。E2eeUnavailableException がスローされた場合は、キャッチして、isCloudBackupEnabled を false に設定して createCredential を再度呼び出します。
  • IllegalArgumentException: この例外は、createRestoreRequest が空であるか、有効な JSON ではない場合、または WebAuthn の仕様に準拠する有効な user.id がない場合に発生します。

復元キーでログインする

Restore Credentials を使用して、デバイスのセットアップ プロセス中にユーザーをバックグラウンドでログインさせます。

アプリサーバーから認証情報取得オプションを取得する

サーバーから復元キーを取得するために必要なオプションをクライアント アプリに送信します。このステップの同様のパスキー ガイダンスについては、パスキーでログインするをご覧ください。サーバーサイドの実装の詳細については、サーバーサイド認証ガイドをご覧ください。

復元キーを取得する

新しいデバイスで復元キーを取得するには、CredentialManager オブジェクトの getCredential() メソッドを呼び出します。

次の両方のシナリオで、復元キーを取得することをおすすめします。

  • デバイスでアプリを初めて起動したとき。このシナリオでの認証情報の復元は、アプリデータの復元とは独立しています。
  • アプリデータのバックアップと復元が有効になっている場合は、アプリデータが復元された直後に復元キーを取得します。BackupAgent を使用してアプリのバックアップを構成し、onRestoreFinished コールバック内で getCredential 機能を完了します。onRestore メソッドは使用しないでください。このメソッドは Key-Value バックアップの場合にのみ呼び出されます。一方、onRestoreFinished は、あらゆる種類のバックアップ復元で確実に呼び出されます。これにより、ユーザーが新しいデバイスを初めて開いたときに遅延が発生する可能性を回避し、ユーザーがアプリを開くのを待たずにアプリを操作できるようになります。たとえば、ユーザーが新しいデバイスでアプリを初めて開く前に、アプリからユーザーに通知を送信できます。これは、メッセージ アプリやコミュニケーション アプリに特に関連しています。

新しい BackupAgent を作成し、以前に allowBackup="true" でバックアップを有効にしていた場合は、アプリのマニフェストでブール値 android:fullBackupOnly="true" を設定します。これにより、アプリのバックアップと復元の動作が維持されます。

// Fetch the options required to get the restore key
val authenticationJson = fetchAuthenticationJson()

// Create the GetRestoreCredentialRequest object
val options = GetRestoreCredentialOption(authenticationJson)
val getRequest = GetCredentialRequest(listOf(options))

val response = credentialManager.getCredential(context, getRequest)

// Type-check and extract the restore credential
val credential = response.credential as RestoreCredential

Credential Manager API は、GetCredentialResponse タイプのレスポンスを返します。このレスポンスに含まれる認証情報は、明示的に RestoreCredential 型であり、公開鍵を保持しています。

ログイン レスポンスを処理する

アプリから証明書利用者サーバーに公開鍵を送信します。この公開鍵を使用してユーザーをログインさせることができます。サーバー側では、このアクションはパスキーを使用したログインに似ています。サーバーでパスキーによるログインを処理する同じコードで、復元キーによるログインも処理できます。パスキーのサーバーサイド実装の詳細については、パスキーでログインするをご覧ください。

復元キーを削除する

認証情報マネージャーはステートレスであり、ユーザー アクティビティを認識しないため、使用後に復元キーを自動的に削除することはありません。復元キーを削除するには、clearCredentialState メソッドを呼び出します。セキュリティを確保するため、ユーザーがログアウトするたびにキーを削除します。これにより、ユーザーが同じデバイスで次にアプリを開いたときに、ユーザーはログアウトされ、再度ログインするよう求められます。

アプリのアンインストールは、ユーザーがログアウトする際と同様に、対応する復元キーをデバイスから削除する意図があると解釈されます。

復元キーは、次の状況でのみ削除されます。

  • システムレベルのアクション: ユーザーがアプリをアンインストールするか、アプリのデータを消去します。
  • アプリレベルの呼び出し: アプリのコードでユーザーのログアウトを処理するときに clearCredentialState() を呼び出して、プログラムで鍵を削除します。

ユーザーがアプリからログアウトしたら、CredentialManager オブジェクトの clearCredentialState() メソッドを呼び出します。

// Create a ClearCredentialStateRequest object
val clearRequest = ClearCredentialStateRequest(TYPE_CLEAR_RESTORE_CREDENTIAL)

// When the user logs out, delete the restore key
val response = credentialManager.clearCredentialState(clearRequest)