Android 15 では、認証情報マネージャーは認証情報の作成と取得のシングルタップ フローをサポートしています。このフローでは、作成または使用される認証情報の情報が、その他のオプションへのエントリ ポイントとともに、生体認証プロンプトに直接表示されます。この簡素化されたプロセスにより、認証情報の作成と取得のプロセスがより効率的かつ合理化されます。
要件:
- ユーザーのデバイスで生体認証が設定されており、ユーザーがアプリケーションへの認証に生体認証を使用することを許可している。
- ログインフローの場合、この機能は単一アカウントのシナリオでのみ有効になります。そのアカウントで複数の認証情報(パスキーやパスワードなど)が利用可能な場合でも同様です。
パスキー作成フローでシングルタップを有効にする
このメソッドの作成手順は、既存の認証情報の作成プロセスと一致します。BeginCreatePublicKeyCredentialRequest
内で、リクエストがパスキーに関するものである場合は、handleCreatePasskeyQuery()
を使用してリクエストを処理します。
is BeginCreatePublicKeyCredentialRequest -> { Log.i(TAG, "Request is passkey type") return handleCreatePasskeyQuery(request, passwordCount, passkeyCount) }
handleCreatePasskeyQuery()
に、CreateEntry
クラスを含む BiometricPromptData
を含めます。
val createEntry = CreateEntry( // Additional properties... biometricPromptData = BiometricPromptData( allowedAuthenticators = allowedAuthenticator ), )
認証情報プロバイダは、BiometricPromptData
インスタンスで allowedAuthenticator
プロパティを明示的に設定する必要があります。このプロパティが設定されていない場合、デフォルト値は DEVICE_WEAK
です。ユースケースで必要な場合は、オプションの cryptoObject
プロパティを設定します。
ログイン パスキー フローでシングルタップを有効にする
パスキー作成フローと同様に、ユーザー ログインの処理に関する既存の設定に従います。BeginGetPublicKeyCredentialOption
で、populatePasskeyData()
を使用して、認証リクエストに関する関連情報を収集します。
is BeginGetPublicKeyCredentialOption -> { // ... other logic populatePasskeyData( origin, option, responseBuilder, autoSelectEnabled, allowedAuthenticator ) // ... other logic as needed }
CreateEntry
と同様に、BiometricPromptData
インスタンスは PublicKeyCredentialEntry
インスタンスに設定されます。明示的に設定されていない場合、allowedAuthenticator
はデフォルトで BIOMETRIC_WEAK
になります。
PublicKeyCredentialEntry( // other properties... biometricPromptData = BiometricPromptData( allowedAuthenticators = allowedAuthenticator ) )
認証情報エントリの選択を処理する
パスキーの作成またはログイン時のパスキーの選択の認証情報エントリの選択を処理する際に、必要に応じて PendingIntentHandler's retrieveProviderCreateCredentialRequest
または retrieveProviderGetCredentialRequest
を呼び出します。これらは、プロバイダに必要なメタデータを含むオブジェクトを返します。たとえば、パスキー作成エントリの選択を処理する場合は、次のようにコードを更新します。
val createRequest = PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent) if (createRequest == null) { Log.i(TAG, "request is null") setUpFailureResponseAndFinish("Unable to extract request from intent") return } // Other logic... val biometricPromptResult = createRequest.biometricPromptResult // Add your logic based on what needs to be done // after getting biometrics if (createRequest.callingRequest is CreatePublicKeyCredentialRequest) { val publicKeyRequest: CreatePublicKeyCredentialRequest = createRequest.callingRequest as CreatePublicKeyCredentialRequest if (biometricPromptResult == null) { // Do your own authentication flow, if needed } else if (biometricPromptResult.isSuccessful) { createPasskey( publicKeyRequest.requestJson, createRequest.callingAppInfo, publicKeyRequest.clientDataHash, accountId ) } else { val error = biometricPromptResult.authenticationError // Process the error } // Other logic... }
この例には、生体認証フローの成功に関する情報が含まれています。また、認証情報に関するその他の情報も含まれています。フローが失敗した場合は、biometricPromptResult.authenticationError
のエラーコードを使用して判断します。biometricPromptResult.authenticationError.errorCode
の一部として返されるエラーコードは、androidx.biometric.BiometricPrompt.NO_SPACE、androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS、androidx.biometric.BiometricPrompt.ERROR_TIMEOUT など、androidx.biometric ライブラリで定義されているエラーコードと同じです。authenticationError
には、UI に表示できる errorCode
に関連付けられたエラー メッセージも含まれます。
同様に、retrieveProviderGetCredentialRequest
中にメタデータを抽出します。生体認証フローが null
かどうかを確認します。認証に独自の生体認証を設定します。これは、get オペレーションが計測される方法と似ています。
val getRequest = PendingIntentHandler.retrieveProviderGetCredentialRequest(intent) if (getRequest == null) { Log.i(TAG, "request is null") setUpFailureResponseAndFinish("Unable to extract request from intent") return } // Other logic... val biometricPromptResult = getRequest.biometricPromptResult // Add your logic based on what needs to be done // after getting biometrics if (biometricPromptResult == null) { // Do your own authentication flow, if necessary } else if (biometricPromptResult.isSuccessful) { Log.i(TAG, "The response from the biometricPromptResult was ${biometricPromptResult.authenticationResult?.authenticationType}") validatePasskey( publicKeyRequest.requestJson, origin, packageName, uid, passkey.username, credId, privateKey ) } else { val error = biometricPromptResult.authenticationError // Process the error } // Other logic...