Integruj tworzenie kluczy dostępu jednym kliknięciem i logowanie się za pomocą potwierdzeń biometrycznych

Credential Manager w Androidzie 15 obsługuje tworzenie i pobieranie danych logowania w ramach procesu obsługiwanego jednym kliknięciem. W tym procesie informacje o tworzonych lub używanych danych logowania są wyświetlane bezpośrednio w prośbie o wprowadzenie danych biometrycznych wraz z punktem wejścia do dodatkowych opcji. Ten uproszczony proces pozwala sprawniej i efektywniej tworzyć i pobierać dane logowania.

Wymagania:

  • Na urządzeniu użytkownika muszą być skonfigurowane dane biometryczne, a użytkownik musi zezwalać na ich używanie do uwierzytelniania w aplikacjach.
  • Ta funkcja może być włączona tylko dla pojedynczego konta na potrzeby procesów logowania, nawet jeśli są dla niego dostępne różne sposoby logowania (np. klucz dostępu i hasło).

Włączanie tworzenia kluczy dostępu jednym kliknięciem

Kroki tworzenia w ramach tej metody są zgodne z dotychczasowym procesem tworzenia danych logowania. Jeśli prośba dotyczy klucza dostępu, w BeginCreatePublicKeyCredentialRequest użyj polecenia handleCreatePasskeyQuery(), aby ją przetworzyć.

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

W handleCreatePasskeyQuery() uwzględnij BiometricPromptData z klasą CreateEntry:

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

Dostawcy danych logowania powinni wyraźnie ustawić właściwość allowedAuthenticator w instancji BiometricPromptData. Jeśli ta właściwość nie jest skonfigurowana, domyślnie stosowana jest wartość DEVICE_WEAK. W razie potrzeby ustaw opcjonalną właściwość cryptoObject.

Włączanie logowania jednym dotknięciem w procesie logowania za pomocą klucza dostępu

Podobnie jak proces tworzenia klucza dostępu ten proces będzie zgodny z istniejącą konfiguracją obsługi logowania użytkownika. W sekcji BeginGetPublicKeyCredentialOption użyj polecenia populatePasskeyData(), aby zebrać odpowiednie informacje o prośbie o uwierzytelnienie:

is BeginGetPublicKeyCredentialOption -> {
    // ... other logic

    populatePasskeyData(
        origin,
        option,
        responseBuilder,
        autoSelectEnabled,
        allowedAuthenticator
    )

    // ... other logic as needed
}

Podobnie jak w przypadku CreateEntry instancja BiometricPromptData jest ustawiona na instancję PublicKeyCredentialEntry. Jeśli nie zostanie skonfigurowany, allowedAuthenticator przyjmie domyślnie wartość BIOMETRIC_WEAK.

PublicKeyCredentialEntry(
    // other properties...

    biometricPromptData = BiometricPromptData(
        allowedAuthenticators = allowedAuthenticator
    )
)

Obsługa wyboru danych logowania

Podczas obsługi wyboru danych logowania na potrzeby tworzenia klucza dostępu lub wyboru klucza dostępu podczas logowania należy wywołać funkcję PendingIntentHandler's retrieveProviderCreateCredentialRequest lub retrieveProviderGetCredentialRequest. Zwrócone zostaną obiekty, które zawierają metadane potrzebne dostawcy. Na przykład podczas obsługi wyboru wejścia na potrzeby utworzenia klucza dostępu zaktualizuj kod w ten sposób:

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...
}

Ten przykład zawiera informacje o skutecznym przeprowadzeniu procesu biometrycznego. Zawiera on również inne informacje o danych logowania. Jeśli proces się nie powiedzie, do podjęcia decyzji użyj kodu błędu w sekcji biometricPromptResult.authenticationError. Kody błędów zwracane w ramach biometricPromptResult.authenticationError.errorCode to te same kody błędów, które są zdefiniowane w bibliotece androidx.biometric, takie jak androidx.biometric.BiometricPrompt.NO_SPACE, androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS, androidx.biometric.BiometricPrompt.ERROR_TIMEOUT i inne. authenticationError będzie też zawierać komunikat o błędzie związany z errorCode, który może być wyświetlany w interfejsie.

Podobnie wyodrębnij metadane podczas retrieveProviderGetCredentialRequest. Sprawdź, czy proces biometryczny ma wartość null. Jeśli tak, skonfiguruj własne dane biometryczne na potrzeby uwierzytelniania. Przebiega to podobnie do instrumentowania operacji 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...