Integra la creazione di passkey con un solo tocco e l'accesso con richieste biometriche

Su Android 15, Gestore delle credenziali supporta un flusso con un solo tocco per le credenziali la creazione e il recupero. In questo flusso, le informazioni sulla credenziale creato o in uso viene visualizzato direttamente nel prompt biometrico, insieme con un punto di accesso a più opzioni. Questo processo semplificato crea un processo efficiente e semplificato di creazione e recupero delle credenziali.

Requisiti:

  • La biometria è stata configurata sul dispositivo dell'utente e l'utente li concede l'autenticazione nelle applicazioni.
  • Per i flussi di accesso, questa funzionalità è abilitata solo per gli scenari con un singolo account, anche se sono disponibili più credenziali (come passkey e password) per quell'account.

Attiva i flussi di creazione di passkey con un singolo tocco

I passaggi di creazione di questo metodo corrispondono alla creazione delle credenziali esistenti . All'interno di BeginCreatePublicKeyCredentialRequest, usa handleCreatePasskeyQuery() per elaborare la richiesta se si tratta di una passkey.

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

In handleCreatePasskeyQuery(), includi BiometricPromptData con il corso CreateEntry:

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

I fornitori di credenziali devono impostare esplicitamente la proprietà allowedAuthenticator nell'istanza BiometricPromptData. Se questa proprietà non è impostata, il valore il valore predefinito è DEVICE_WEAK. Se necessario, imposta la proprietà facoltativa cryptoObject per il tuo caso d'uso.

Attiva i flussi di passkey per l'accesso con un solo tocco

Come per il flusso di creazione della passkey, verrà seguita la configurazione esistente per la gestione dell'accesso utente. In BeginGetPublicKeyCredentialOption, usa populatePasskeyData() per raccogliere le informazioni pertinenti sul richiesta di autenticazione:

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

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

  // ... other logic as needed
}

Analogamente a CreateEntry, un'istanza BiometricPromptData è impostata PublicKeyCredentialEntry istanza. Se non impostato esplicitamente,allowedAuthenticator ha come valore predefinito BIOMETRIC_WEAK.

PublicKeyCredentialEntry(
  // other properties...

  biometricPromptData = BiometricPromptData(
    allowedAuthenticators = allowedAuthenticator
  )
)

Gestire la selezione dell'immissione delle credenziali

Mentre gestisci la selezione dell'immissione delle credenziali per la creazione della passkey o selezione della passkey durante l'accesso, chiamare il PendingIntentHandler's retrieveProviderCreateCredentialRequest oppure retrieveProviderGetCredentialRequest, a seconda dei casi. Questi oggetti restituiscono oggetti che contengano i metadati necessari per il provider. Ad esempio, quando gestisci selezione della voce di creazione della passkey, aggiorna il codice come mostrato:

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

Questo esempio contiene informazioni sull'esito del flusso biometrico. Contiene inoltre altre informazioni sulla credenziale. Se il flusso non riesce, utilizza codice di errore in biometricPromptResult.authenticationError per prendere decisioni. I codici di errore restituiti come parte biometricPromptResult.authenticationError.errorCode sono gli stessi codici di errore definita nella libreria androidx.biometric, come androidx.biometric.BiometricPrompt.NO_SPACE, androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS, androidx.biometric.BiometricPrompt.ERROR_TIMEOUT e simili. Il messaggio authenticationError conterrà anche un messaggio di errore associato al messaggio authenticationError che può essere visualizzato in un'interfaccia utente.

Allo stesso modo, estrai i metadati durante l'intervallo retrieveProviderGetCredentialRequest. Controlla se il tuo flusso biometrico è null. Se sì, configura la tua biometria per autenticarsi. Questo è simile all'uso dell'operazione 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...