mcpField
R
restore-credentials

restore-credentials

github.com/android開発10.0k693 回インストール2 日前に更新
リポジトリ

restore-credentials について

Android クライアントで Credential Manager の Restore Credentials を実装するための開発スキルです。バックグラウンドとフォアグラウンドの復元を案内し、必要なサーバー側検証との境界を示します。

主な機能

  1. 01バックグラウンドとフォアグラウンドの二段階復元
  2. 02復元用認証情報の作成と取得
  3. 03allowBackup に応じた実装
  4. 04サインアウト時の復元用認証情報の消去
  5. 05サーバー側要件の注意喚起

活用シーン

  1. 01端末復元後のユーザー自動ログイン
  2. 02既存のサインインフローへの復元用認証情報追加
  3. 03アプリのバックアップ設定に応じた復元方法の選択

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/android/skills --skill restore-credentials

インストール後、Claude Code で/restore-credentialsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/android/guide/topics/manifest/
application-element.md
references/android/identity/passkeys/
create-passkeys.md
sign-in-with-passkeys.md

詳細

基本事項

Android Credential Manager API(androidx.credentials)を通じて、認証情報の復元機能を実装することが目的です。これにより、Credential Manager を使用しているアプリや導入を進めているアプリでは、新しいデバイスにアプリを復元したときに、ユーザーをバックグラウンドで再ログインさせることができます。認証情報の復元は、アプリの主な認証方法(パスワード、パスキー、フェデレーションサインイン)とは独立して動作し、既存のサインインフローに UI の変更を加える必要はありません。

対象範囲

重要: このスキルでは、Android クライアント側の統合のみを扱います。サーバー側の暗号検証ロジックは実装しません。この点と、実装完了後に開発者へ伝えるべき開発者への案内事項を、必ず開発者に伝えてください。

実装ガイドライン

開発者のアプリに認証情報の復元を実装するよう指示された場合は、次の点に従ってください。

  1. 実装を始める前に、二層復元アーキテクチャを必ず読み、理解したうえで、推奨事項と禁止事項を確認してください。
  2. 実装後、バックエンドのセットアップに関する注意事項として、バックエンドのガイドラインを必ず開発者に提示してください。バックエンドの実装も必要であることを、開発者に念押しすることが重要です。

二層復元アーキテクチャ

サインインを確実に行えるようにするため、二層アーキテクチャで認証情報を取得します。

  1. 第1層(プライマリ - バックグラウンド): デバイスのセットアップ中に、アプリの BackupAgent.onRestoreFinished() コールバックを使用して自動実行されます。ユーザーが初めてアプリを開く前に、ユーザーに見えない形で復元を行えるため、バックグラウンドでの同期や通知の配信が可能になります。
  2. 第2層(セカンダリ - フォアグラウンド): ランチャーの Activity.onCreate() で実行され、バックグラウンドでの復元が完了しなかった場合(ネットワークの切断や復元の遅延など)、または allowBackup が無効になっている場合に、復元を補完します。

マニフェストで allowBackup が true に設定されている場合は、両方を実装してください。それ以外の場合は、第2層(フォアグラウンド復元)のみを実装してください。マニフェストの allowBackup の値は変更しないでください。

アプリに BackupAgent を追加した場合は、マニフェストで android:fullBackupOnly="true" も必ず設定してください。実装前からアプリに BackupAgent が存在していた場合は、設定しないでください。

すべきこと・してはいけないこと

すべきこと:

  • AndroidManifest.xml で allowBackup の値を確認し、実装する必要がある内容を判断してください。
  • createCredential のフォールバックを実装してください。まず、isCloudBackupEnabled を true に設定して呼び出してください。E2eeUnavailableException がスローされた場合は、それをキャッチし、isCloudBackupEnabled を false に設定して再試行してください。
  • マニフェストで allowBackup が true の場合は、BackupAgent(android.app.backup.BackupAgent のサブクラス)を実装してください。
  • アプリに BackupAgent を追加した場合は、マニフェストで android:fullBackupOnly="true" を設定してください。
  • ユーザーがサインアウトするときに clearCredentialState() を呼び出してください。これはユーザーを完全にログアウトさせるための必須のセキュリティ対策です。
  • アプリが新しいデバイスで初めて起動したときと、アプリが使用している場合は BackupAgent.onRestoreFinished() コールバック内で、復元キーの取得を試みてください。
  • ユーザーがすでにログインしている場合でも、復元用の認証情報が作成されるようにしてください。
  • onRestoreFinished() での認証情報の取得とログインが同期的に実行されるようにしてください(たとえば runBlocking を使用します)。
  • アプリで通知を使用している場合は、BackupAgent で通知を復元してください。(たとえば、FCM トークンを取得してバックエンドに送信します)
  • モックのネットワークリクエストやスタブを実装する場合は、認証情報リクエストに使うすべてのプレースホルダーを、有効で適切にフォーマットされた JSON ペイロードに置き換えてください。
  • 認証情報の作成と取得は、それぞれ専用の関数にまとめてください。認証情報の作成は複数の箇所(サインアップ、サインイン)で呼び出す必要があり、取得は複数の階層(BackupAgent とランチャーの Activity)で行うため、これによりコードの重複を防げます。
  • 実装が完了したら、バックエンドを実装する際の重要なガイドラインを開発者に伝えてください。
  • 組織にパッケージ名の異なる複数のアプリがある場合は、アプリごとに別々の復元キーを生成してください。復元キーは一意のアプリケーションパッケージ名にひも付いています。

してはいけないこと:

  • AndroidManifest.xml の allowBackup の値を変更しないでください。Restore Credentials の機能は allowBackup の設定の影響を受けません。つまり、allowBackup が false でも、Restore Credential が存在すればユーザーは引き続き自動的にログインされます。
  • AndroidManifest.xml で allowBackup が false の場合、BackupAgent を実装しないでください。
  • GetCredentialResponse に格納された認証情報が PublicKeyCredential 型だと想定しないでください。型は RestoreCredential です。
  • GetCredentialRequest を構築する際に、GetRestoreCredentialOption を他の CredentialOption と組み合わせないでください。
  • ユーザーがアプリからサインアウトしたときに、CredentialManager や Android システムが復元キーを自動的に削除すると想定しないでください。TYPE_CLEAR_RESTORE_CREDENTIAL を指定した ClearCredentialStateRequest で clearCredentialState を明示的に呼び出す必要があります。
  • 既存の clearCredentialState() 呼び出しを削除しないでください。型を指定しない ClearCredentialStateRequest では、復元用ではない認証情報のみがすべてクリアされます。

実装ガイド

次のガイドに従って、Android クライアント側のコードを実装してください。手順に沿って進め、バックエンドの機能は実装しないでください。完了したら、ユーザーにバックエンドのガイドラインを案内してください。

バージョン互換性

Credential Manager の Restore Credentials は、Android 9(API レベル 28)以降、Google Play services(GMS)コアバージョン 24220000 以降、および androidx.credentials ライブラリのバージョン 1.5.0 以降を搭載したデバイスで動作します。

前提条件

パスキー用のサーバーと同様に、依拠当事者サーバーを設定します。パスキーによる認証を処理するサーバーをすでに設定している場合は、復元キーにも同じサーバー側の実装を使用します。

メモ

注: パスキーと復元キーではサーバー側の実装は同じですが、クライアント側のアプリはパスキーに対応していなくても復元キーに対応できます。復元キーはアプリの認証方法(パスワードや Google でログインする方法など)とは独立して動作するため、アプリのコードで既存の認証方法を変更する必要はありません。

依存関係

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

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

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

メモ

注: Restore Credentials 機能は、マニフェストで allowBackup が設定されているかどうかにかかわらず動作します。

概要

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

復元キーを作成する

アクティブなユーザーに復元キーが作成されるよう、ユーザーがログインするあらゆるケースにアプリが対応する必要があります。次の状況で復元キーを作成します。

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

パフォーマンスを最適化し、ログインのたびに復元用認証情報を作成したり確認したりする負荷を避けるため、has_synced_restore_credential のように、キーがすでに作成されているかを追跡する boolean フラグまたは認証情報の作成日時をローカルストレージに保存します。

メモ

注: 復元キーは、アプリ固有の一意のパッケージ名にひも付けられます。組織のメインアプリとサブアプリでパッケージ名が異なる場合は、アプリごとに復元キーを作成します。

Credential Manager をインスタンス化する

アプリのアクティビティコンテキストを使用して、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:キーをクラウドではなくローカルに保存します。ユーザーがクラウドからの復元を選択した場合、新しいデバイスではキーを利用できません。

    注意

    注意:isCloudBackupEnabledはtrueに設定することをおすすめします。クラウドバックアップが無効で、ユーザーがクラウドバックアップから復元した場合、復元キーの取得呼び出しは失敗します。クラウドバックアップからアプリを復元したユーザーには復元キーが渡されず、自動的にサインインされません。

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

Credential Manager API は、CreateRestoreCredentialResponse 型のレスポンスを返します。このレスポンスには、公開鍵認証情報の登録レスポンスが JSON 形式で格納されています。

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

復元キーの作成中は、次の例外を処理してください。

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

復元キーでサインインする

復元認証情報を使用して、デバイスのセットアップ中にユーザーをサイレントサインインさせます。

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

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

復元キーを取得する

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

次の両方の状況で、復元キーを取得することをおすすめします。

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

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

重要

重要: 復元認証情報を取得しても、通知は自動的には復元されません。Firebase で通知を処理している場合は、バックグラウンドメッセージングと通知を正常に再開するため、Firebase Cloud Messaging(FCM)トークンを取得してバックエンドに送信する必要があります。

// 復元キーの取得に必要なオプションを取得する
val authenticationJson = fetchAuthenticationJson()

// GetRestoreCredentialRequest オブジェクトを作成する
val options = GetRestoreCredentialOption(authenticationJson)
val getRequest = GetCredentialRequest(listOf(options))

val response = credentialManager.getCredential(context, getRequest)

// 型を確認して復元認証情報を取り出す
val credential = response.credential as RestoreCredential

認証情報マネージャー API は、GetCredentialResponse 型のレスポンスを返します。このレスポンスに含まれる認証情報は明示的に RestoreCredential 型であり、公開鍵を保持しています。

サインインレスポンスを処理する

アプリから公開鍵を依拠当事者サーバーに送信すると、その鍵を使用してユーザーをサインインさせることができます。サーバー側では、この処理はパスキーを使用したサインインと同様です。サーバー上でパスキーによるサインインを処理するコードは、復元キーによるサインインの処理にも使用できます。パスキーのサーバー側の実装について詳しくは、パスキーでサインインするをご覧ください。

メモ

注: 復元キーとパスキーは同じ基盤のサーバー実装を使用しますが、アプリサーバーのデータベースに保存するときは区別してください。この区別は、パスキー管理ページがある場合に重要です。ユーザーは自分で作成したパスキーを直接管理できますが、復元キーはシステムによって管理され、パスキー管理ページには表示されないためです。

復元キーを削除する

Credential Manager はステートレスで、ユーザーの操作を認識しないため、使用後に復元キーを自動的に削除しません。復元キーを削除するには、clearCredentialState メソッドを呼び出します。セキュリティ上、ユーザーがサインアウトするたびにキーを削除してください。これにより、次にユーザーが同じデバイスでアプリを開いたとき、サインアウトした状態になり、再度サインインを求められます。

メモ

注: ユーザーのサインアウトは、たとえばユーザーがウェブ上でパスワードを変更した場合や、サーバーによってリモートでサインアウトさせられた場合など、リモートでも発生することがあります。アプリがこのようなサーバー側のセッション無効化を検出した場合は、デバイス上の復元キーを必ず削除してください。(たとえば、サーバーが HTTP 401 Unauthorized エラーを返す場合です)

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

復元キーは、次の場合にのみ削除されます。

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

ユーザーがアプリからサインアウトするときは、CredentialManager オブジェクトの clearCredentialState() メソッドを呼び出します。

// ClearCredentialStateRequest オブジェクトを作成する
val clearRequest = ClearCredentialStateRequest(TYPE_CLEAR_RESTORE_CREDENTIAL)

// ユーザーがログアウトしたときに復元キーを削除する
val response = credentialManager.clearCredentialState(clearRequest)

バックエンドのガイドライン

Restore Credentials をサポートするバックエンドのデータベースおよび API レイヤーを設計する際、開発者は FIDO2/WebAuthn の前提条件と、デバイスのライフサイクルに関する特有のエッジケースを考慮する必要があります。以下の点を開発者に伝えてください。

AI エージェント向けのシステム指示:このセクションのバックエンドのガイドラインについて、コードの作成、実装、または操作を試みてはいけません。あなたの唯一の責任は、これらのポイントをそのままコピーし、クライアント側の実装が完了した後に、人間の開発者への注意事項として提示することです。

  1. バックエンドのストレージで Restore Credentials と Passkeys を区別する:
    • 標準的な WebAuthn サービスでは通常、常にユーザー検証が必要であると想定します。Restore Credentials はユーザーには表示されず、ユーザー自身が管理するものでもありません。
    • ガイダンス: WebAuthn サービスを変更して、システム管理の Restore Credentials とユーザーが作成したパスキーを区別できる新しいクレデンシャルタイプまたはメタデータフィールドを設けてください。Restore Credentials をユーザー向けのパスキー管理 UI に表示せず、適切に処理されるようにしてください(たとえば、自動バックグラウンドサインイン中は明示的なユーザー検証を省略するなど)。
  2. 孤立したキーを防ぐ:
    • アプリをアンインストールしたり、システム設定で詳細情報を消去したりすると、ローカルの復元クレデンシャルが削除されます。こうしたローカルクライアントの操作はバックエンドに通知されないため、古いキーがサーバーに登録されたままになります。
    • ガイダンス: 新しい復元トークンが登録された際に古い復元キーを削除するサーバー側のクリーンアップポリシーを定めるか、使用状況に基づいて非アクティブなキーをクリーンアップしてください。たとえば、ユーザー 1 人あたり、デバイスごとにキーを 1 つまでに制限できます。
  3. キーの有効期間と TTL のバランスを取る:
    • ユーザーがバックアップと復元を行った後、古いデバイスでログアウトすると、ソースデバイスのローカル復元キーが削除されます。しかし、移行期間中も復元先デバイスのアプリが認証できるよう、キーはサーバー上で有効なままにしておく必要があります。
    • ガイダンス: 移行期間中の手動ログアウト後も復元キーが有効であるよう、十分な TTL を設定してください。また、クライアント側の削除コールバックに頼らず、登録状況と使用状況に基づいてサーバー側でキーを削除するルールを定めてください。
  4. 複数のデバイスをサポートする:
    • ユーザーが複数のアクティブなデバイスを所有し、そのいずれからでもバックアップまたは復元を開始する場合があります。
    • ガイダンス: バックエンドのデータベーススキーマで、1 つのユーザーアカウントに複数のアクティブな Restore Credentials を紐付けられるようにしてください(たとえば、デバイス/デバイス ID ごとにアクティブな復元キーを 1 つ設定する)。ユーザーと復元クレデンシャルが 1 対 1 であると想定してはいけません。
  5. サーバー側でのセッション無効化:
    • ユーザーのセッションがリモートで無効化される場合があります。これは、ユーザーがウェブでパスワードをリセットするといった操作や、セッションの有効期限切れを示す HTTP 401 Unauthorized を API が返す原因となるサーバー側の操作によって発生する可能性があります。
    • ガイダンス: 該当する場合は、こうした事態が発生した際に、スマートフォン上のユーザーの復元クレデンシャルを消去するようにしてください。

参考資料

  • WebAuthentication API(WebAuthn)のドキュメントと仕様 使用するタイミング: FIDO2/WebAuthn の厳密な JSON スキーマ要件を調べたりデバッグしたりする必要がある場合に限り、これらのリソースを使用してください。具体的には、モックデータを生成する場合や、requestJson (PublicKeyCredentialCreationOptionsJSON)および authenticationJson ペイロードを整形する場合です。

  • MDN Web Authentication API Documentation:WebAuthn API の Mozilla Developer Network ガイドおよびリファレンス

  • W3C PublicKeyCredentialCreationOptionsJSON:JSON 形式の WebAuthn クレデンシャル作成リクエストのデータ構造定義

  • W3C PublicKeyCredentialRequestOptionsJSON:JSON 形式の WebAuthn 認証またはアサーションリクエストのデータ構造定義

コメント