Integrate single tap sign up and sign-in with biometric prompts

Credential Manager handles biometric prompt functionality and integrates it into the credential creation and sign-in processes, eliminating the need for providers to manage biometric prompts. As a result, credential providers only need to focus on the results of the create and get flows, augmented with the biometric flow result. This simplified process creates a more efficient and streamlined credential creation and retrieval process.

Create a single tap sign-up passkey flow

Within your BeginCreatePublicKeyCredentialRequest, use handleCreatePasskeyQuery() to process the request if it is for a passkey. This method's creation steps match the existing credential creation process.

In your handleCreatePasskeyQuery(), instantiate BiometricPromptData as a part of the constructor:

Kotlin


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


Java


CreateEntry createEntry = new CreateEntry(
  // Additional properties...
  new BiometricPromptData(
    null, // cryptoObject
    allowedAuthenticator // allowedAuthenticators
  )
);

As a provider, we recommend that you set the allowedAuthenticator property. If not set, it will default to DEVICE_WEAK. Set the optional cryptoObject property if needed for your use case.

Create a single tap sign-in passkey flow

Similar to the passkey creation flow, this will follow the existing setup for handling user sign-in. Under the BeginGetPublicKeyCredentialOption, use populatePasskeyData() to gather the relevant information about the authentication request:

Kotlin


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

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

  // ... other logic as needed
}

Java


if (request instanceof BeginGetPublicKeyCredentialOption) {
  // ... other logic

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

  // ... other logic as needed
}

Similar toCreateEntry, the allowedAuthenticator property should be recommended by the provider, and will default to BIOMETRIC_WEAK if not set. Update your PublicKeyCredentialEntry as shown in this example:

Kotlin


PublicKeyCredentialEntry(
  // other properties...

  biometricPromptData = BiometricPromptData(
    allowedAuthenticators = allowedAuthenticator
  )
)

Java


PublicKeyCredentialEntry entry = new PublicKeyCredentialEntry(
  // other properties...
  new BiometricPromptData(
    allowedAuthenticator // allowedAuthenticators
  )
);

Handle credential entry selection

While handling the credential entry selection for passkey creation or passkey selection during sign in, call the PendingIntentHandler's retrieveProviderCreateCredentialRequest, or retrieveProviderGetCredentialRequest, as appropriate. These will return objects that contain the metadata needed for the provider. For example, while handling passkey creation entry selection, update your code as shown:

Kotlin


val request = PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)
if (request == null) {
  Log.i(TAG, "request is null")
  setUpFailureResponseAndFinish("Unable to extract request from intent")
  return
}
// Other logic...

val biometricPromptResult = request.BiometricPromptResult

// Add your logic based on what needs to be done
// after getting biometrics 

// Add data details...

// Add other logic...


if (request != null && request.callingRequest is CreatePublicKeyCredentialRequest) {
  val publicKeyRequest: CreatePublicKeyCredentialRequest = 
    request.callingRequest as CreatePublicKeyCredentialRequest

  if (biometricPromptResult.isSuccessful) {
    createPasskey(
    publicKeyRequest.requestJson,
    request.callingAppInfo,
    publicKeyRequest.clientDataHash,
    accountId
  )
  }else{
    //return with error reason
}

  // Other logic...
}

Java


ProviderCreateCredentialRequest request = 
    PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent);

if (request == null) {
  Log.i(TAG, "request is null");
  setUpFailureResponseAndFinish("Unable to extract request from intent");
  return;
}


// Other logic…

BiometricPromptResult biometricPromptResult = request.BiometricPromptResult

// Add your logic for what needs to be done after getting biometric data...

// Add other logic...

if (request != null && 
    request.callingRequest instanceof CreatePublicKeyCredentialRequest) {
  CreatePublicKeyCredentialRequest publicKeyRequest = 
      (CreatePublicKeyCredentialRequest) request.callingRequest;

  if (biometricPromptResult.isSuccessful) {
    successToActivityFinalization(
      publicKeyRequest.requestJson, 
      request.callingAppInfo,
      publicKeyRequest.clientDataHash,
      accountId
    );
    return;
  }

  createPasskey(
    publicKeyRequest.requestJson, 
    request.callingAppInfo, 
    publicKeyRequest.clientDataHash, 
    accountId
  );
  // Other logic...
}

This example contains information about the biometric flow's success. It also contains other information about the credential. If the flow fails, use the error code to make decisions. With this flow established, you can add custom UI screens or pass the information through Credential Manager, and handle the biometrics metadata during credential selection during passkey sign-in. Password and custom credential authentication schemes follow similar flows.