Интегрируйте создание ключа доступа одним касанием и вход в систему с биометрическими подсказками.

В Android 15 диспетчер учетных данных поддерживает создание и получение учетных данных одним нажатием. В этом процессе информация о создаваемых или используемых учетных данных отображается непосредственно в биометрической подсказке вместе с точкой входа для доступа к дополнительным параметрам. Этот упрощенный процесс обеспечивает более эффективный и оптимизированный процесс создания и поиска учетных данных.

Требования:

  • На устройстве пользователя настроена биометрия, и пользователь разрешает использовать ее для аутентификации в приложениях.
  • Для потоков входа эта функция включена только для сценариев с одной учетной записью, даже если для этой учетной записи доступно несколько учетных данных (например, ключ доступа и пароль).

Включить одно касание в процессах создания ключей доступа

Шаги создания этого метода соответствуют существующему процессу создания учетных данных . В вашем BeginCreatePublicKeyCredentialRequest используйте handleCreatePasskeyQuery() для обработки запроса, если он предназначен для ключа доступа.

is BeginCreatePublicKeyCredentialRequest -> {
 
Log.i(TAG, "Request is passkey type")
 
return handleCreatePasskeyQuery(request, passwordCount, passkeyCount)
}

В вашем handleCreatePasskeyQuery() включите BiometricPromptData с классом CreateEntry :

val createEntry = CreateEntry(
 
// Additional properties...
  biometricPromptData
= BiometricPromptData(
    allowedAuthenticators
= allowedAuthenticator
 
)
)

Поставщики учетных данных должны явно задать свойство allowedAuthenticator в экземпляре BiometricPromptData . Если это свойство не установлено, значение по умолчанию равно 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.authenitcationError
   
// Process the error
}

 
// Other logic...
}

Этот пример содержит информацию об успешности биометрического потока. Он также содержит другую информацию об учетных данных. В случае сбоя потока используйте код ошибки в разделе biometricPromptResult.authenticationError для принятия решений. Коды ошибок, возвращаемые как часть biometricPromptResult.authenticationError.errorCode , — это те же коды ошибок, которые определены в библиотеке androidx.biometric, например androidx.biometric.BiometricPrompt.NO_SPACE , androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS , androidx.biometric.BiometricPrompt.ERROR_TIMEOUT . и тому подобное. authenticationError также будет содержать сообщение об ошибке, связанное с 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.authenitcationError
   
// Process the error
}

 
// Other logic...