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 la creazione e il recupero delle credenziali. In questo flusso, le informazioni della credenziale in fase di creazione o di utilizzo vengono visualizzate direttamente nella richiesta biometrica, insieme a un punto di accesso per altre opzioni. Questa procedura semplificata consente di creare e recuperare le credenziali in modo più efficiente e snello.

Requisiti:

  • I dati biometrici sono stati configurati sul dispositivo dell'utente e l'utente li consente per l'autenticazione nelle applicazioni.
  • Per i flussi di accesso, questa funzionalità è attivata solo per scenari con un solo account, anche se sono disponibili più credenziali (ad esempio passkey e password) per quell'account.

Attivare il tocco singolo nei flussi di creazione delle passkey

I passaggi di creazione di questo metodo corrispondono alla procedura di creazione delle credenziali esistente. In BeginCreatePublicKeyCredentialRequest, utilizza handleCreatePasskeyQuery() per elaborare la richiesta se riguarda una passkey.

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

In handleCreatePasskeyQuery(), includi BiometricPromptData con la classe 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 predefinito è DEVICE_WEAK. Se necessario, imposta la proprietà facoltativa cryptoObject per il tuo caso d'uso.

Attivare il singolo tocco per i flussi delle passkey di accesso

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

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

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

  // ... other logic as needed
}

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

PublicKeyCredentialEntry(
  // other properties...

  biometricPromptData = BiometricPromptData(
    allowedAuthenticators = allowedAuthenticator
  )
)

Gestire la selezione dell'inserimento delle credenziali

Durante la gestione della selezione dell'inserimento delle credenziali per la creazione di passkey o la selezione di passkey durante l'accesso, chiama PendingIntentHandler's retrieveProviderCreateCredentialRequest o retrieveProviderGetCredentialRequest, a seconda dei casi. Questi oggetti di ritorno contengono i metadati necessari per il fornitore. Ad esempio, quando gestisci la 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 va a buon fine, utilizza il codice di errore in biometricPromptResult.authenticationError per prendere decisioni. I codici di errore restituiti nell'ambito di biometricPromptResult.authenticationError.errorCode sono gli stessi codici di errore definiti nella libreria androidx.biometric, ad esempio androidx.biometric.BiometricPrompt.NO_SPACE, androidx.biometric.BiometricPrompt.UNABLE_TO_PROCESS, androidx.biometric.BiometricPrompt.ERROR_TIMEOUT e simili. Il authenticationError conterrà anche un messaggio di errore associato al errorCode che può essere visualizzato in un'interfaccia utente.

Analogamente, estrai i metadati durante il retrieveProviderGetCredentialRequest. Controlla se il flusso biometrico è null. In caso affermativo, configura i tuoi dati biometrici per autenticarti. È simile al modo in cui viene eseguita l'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...