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

W Androidzie 15 Menedżer danych logowania obsługuje proces tworzenia i pobierania danych logowania za pomocą jednego kliknięcia. W tym procesie informacje o tworzonych lub używanych danych logowania są wyświetlane bezpośrednio w oknie biometrycznym wraz z punktem wejścia do większej liczby opcji. Ten uproszczony proces sprawia, że tworzenie i pobieranie danych logowania jest bardziej wydajne i sprawne.

Wymagania:

  • Na urządzeniu użytkownika skonfigurowano dane biometryczne i użytkownik zezwala na ich używanie do uwierzytelniania w aplikacjach.
  • W przypadku procesów logowania ta funkcja jest włączona tylko w scenariuszach z jednym kontem, nawet jeśli dla tego konta dostępnych jest wiele danych logowania (np. klucz dostępu i hasło).

Włączanie pojedynczego kliknięcia w procesie tworzenia klucza dostępu

Czynności tworzenia tej metody są zgodne z dotychczasowym procesem tworzenia danych logowania. W ramach BeginCreatePublicKeyCredentialRequest użyj handleCreatePasskeyQuery(), aby przetworzyć prośbę, jeśli dotyczy ona klucza dostępu.

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 ustawiona, domyślną wartością jest DEVICE_WEAK. W razie potrzeby ustaw opcjonalną właściwość cryptoObject.

Włączanie logowania jednym dotknięciem w przypadku kluczy dostępu

Podobnie jak w przypadku tworzenia klucza dostępu, ten proces będzie zgodny z dotychczasową konfiguracją obsługi logowania użytkowników. W sekcji BeginGetPublicKeyCredentialOption użyj elementu 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 wyraźnie ustawiona, domyślna wartość parametru allowedAuthenticator to BIOMETRIC_WEAK.

PublicKeyCredentialEntry(
    // other properties...

    biometricPromptData = BiometricPromptData(
        allowedAuthenticators = allowedAuthenticator
    )
)

Obsługa wyboru wpisu danych logowania

Podczas obsługi wyboru wpisu danych logowania w przypadku tworzenia klucza dostępu lub wybierania klucza dostępu podczas logowania wywołaj odpowiednio funkcję PendingIntentHandler's retrieveProviderCreateCredentialRequest lub retrieveProviderGetCredentialRequest. Zwracają one obiekty zawierające metadane potrzebne dostawcy. Na przykład podczas obsługi wyboru wpisu dotyczącego tworzenia 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 powodzeniu procesu biometrycznego. Zawiera też inne informacje o dokumencie. Jeśli proces się nie powiedzie, podejmij decyzję na podstawie kodu błędu podanego w sekcji biometricPromptResult.authenticationError. Kody błędów zwracane w ramach parametru biometricPromptResult.authenticationError.errorCode są takie same jak kody błędów zdefiniowane w bibliotece androidx.biometric, np. androidx.biometric.BiometricPrompt.NO_SPACE, androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS, androidx.biometric.BiometricPrompt.ERROR_TIMEOUT i podobne. authenticationError będzie też zawierać komunikat o błędzie związany z errorCode, który można wyświetlić w interfejsie.

Podobnie wyodrębniaj metadane podczas retrieveProviderGetCredentialRequest. Sprawdź, czy proces biometryczny jest null. Jeśli tak, skonfiguruj własne dane biometryczne, aby się uwierzytelnić. Działa to podobnie jak w przypadku operacji pobierania:

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