> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/3d-secure/implement-3ds/implement-oob-flow-thales-authentication/enroll-the-authenticator.md).

# Enroll the authenticator

## Overview

Before completing a 3DS challenge during an e‑commerce transaction, the end user must enroll a device authenticator in the issuer application.

The D1 SDK provides a FIDO‑based authenticator for EMV 3‑D Secure (3DS). Enrollment registers the end user’s authenticator on the device for 3DS.

## Enrollment flow

<figure><img src="/files/tdyH7VQh6jElzA4ckvee" alt=""><figcaption><p>High‑level authenticator enrollment flow.</p></figcaption></figure>

## Sequence diagram

The diagram below shows the end‑to‑end message sequence for authenticator enrollment.

### Prerequisites

* The issuer application integrates the D1 SDK and the SDK is initialized.
* The issuer application is logged in to the D1 SDK.
* The end user is registered in the D1 Platform.
* Push notifications are configured in the issuer application.

<figure><img src="/files/huX3SskrPcnZxnpTfCqI" alt=""><figcaption><p>Sequence diagram for authenticator enrollment.</p></figcaption></figure>

{% hint style="danger" %}

* Each device supports a maximum of **one enrolled end user**.
* A single end user may be enrolled on **multiple devices**.
* Certain Android devices may generate an incorrect attestation payload, which can result in enrollment failure. To mitigate this risk, it is **strongly recommended** to enroll using a `BIOMETRIC` authenticator rather than a `PLATFORM` authenticator.
  {% endhint %}

## D1 SDK integration

### Enroll the authenticator

{% tabs %}
{% tab title="Android Java" %}

```java
// Provide an AuthnCallback
D1Authn d1Authn = d1Task.getD1Authn(activity, authnCallback);

// Select the authenticator type
AuthnType preferredAuthnType = AuthnType.BIOMETRIC;

d1Authn.enrollAuthnCredentials(preferredAuthnType, new D1Task.Callback<Void>() {
    @Override
    public void onSuccess(Void unused) {
        // The device is enrolled for 3DS. Continue with the OOB challenge.
    }

    @Override
    public void onError(@NonNull D1Exception e) {
        // Handle the error in your app.
    }
});
```

{% endtab %}

{% tab title="Android Kotlin" %}

```kotlin
fun enrollAuthnCredentials(d1Task: D1Task, activity: FragmentActivity, authnCallback: AuthnCallback) {
    // Implement the interface conforming to the AuthnCallback
    val d1Authn: D1Authn = d1Task.getD1Authn(activity, authnCallback)

    // Select your preferred authenticator type
    val preferredAuthnType: AuthnType = AuthnType.BIOMETRIC

    d1Authn.enrollAuthnCredentials(preferredAuthnType, object : D1Task.Callback<Void?> {
        override fun onSuccess(unused: Void?) {
            // Proceed with subsequent flows, the device is now enrolled for 3D Secure service.
        }

        override fun onError(e: D1Exception) {
            // Refer to D1 SDK Integration – Error Management section.
        }
    })
}
```

{% endtab %}

{% tab title="iOS" %}

```swift
// Conform to AuthnDelegate
let d1Authn = d1Task.d1Authn(self)

// Select the authenticator type
let preferredAuthnType = AuthnType.biometric

d1Authn.enrollAuthnCredentials(preferredAuthnType, completion: { error in
    if let error = error {
        // Handle the error in your app.
    } else {
        // The device is enrolled for 3DS. Continue with the OOB challenge.
    }
})
```

{% endtab %}
{% endtabs %}

Next, proceed to [Handle the OOB challenge](/3d-secure/implement-3ds/implement-oob-flow-thales-authentication/handle-the-oob-challenge.md).

### Unenroll the authenticator

Call `unenrollAuthnCredentials` to remove enrollment on this device. The D1 backend and local device storage delete associated enrollment data. Other devices remain enrolled. If the device is already unenrolled, the call succeeds (idempotent).

{% tabs %}
{% tab title="Android Java" %}

```java
// Provide an AuthnCallback
D1Authn d1Authn = d1Task.getD1Authn(activity, authnCallback);

d1Authn.unenrollAuthnCredentials(new D1Task.Callback<Void>() {
    @Override
    public void onSuccess(Void unused) {
        // The device is unenrolled for 3DS.
    }

    @Override
    public void onError(@NonNull D1Exception e) {
        // Handle the error in your app.
    }
});
```

{% endtab %}

{% tab title="Android Kotlin" %}

```kotlin
fun unenrollAuthnCredentials(d1Task: D1Task, activity: FragmentActivity, authnCallback: AuthnCallback) {
    // Implement the interface conforming to the AuthnCallback
    val d1Authn: D1Authn = d1Task.getD1Authn(activity, authnCallback)

    d1Authn.unenrollAuthnCredentials(object : D1Task.Callback<Void?> {
        override fun onSuccess(unused: Void?) {
            // the device is now unenrolled for 3D Secure service.
        }

        override fun onError(@NonNull e: D1Exception) {
            // Refer to D1 SDK Integration – Error Management section. It may fail due to network connection.
        }
    })
}
```

{% endtab %}

{% tab title="iOS" %}

```swift
// Conform to AuthnDelegate
let d1Authn = d1Task.d1Authn(self)

d1Authn.unenrollAuthnCredentials({ error in
    if let error = error {
        // Handle the error in your app.
    } else {
        // The device is unenrolled for 3DS.
    }
})
```

{% endtab %}
{% endtabs %}

### Customize the prompt message

**Android**\
For [BIOMETRIC](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/latest/android/com/thalesgroup/gemalto/d1/authn/AuthnType.html#BIOMETRIC), you can customize the message shown in the biometric prompt dialog. For [PLATFORM](https://thalesgroup.github.io/d1sdk-docs/d1-sdk/latest/android/com/thalesgroup/gemalto/d1/authn/AuthnType.html#PLATFORM), customizing the prompt message is not supported.

**iOS**\
Customizing the authentication prompt message is not supported.

{% tabs %}
{% tab title="Android Java" %}

```java
public void customizingBiometricPromptMessage(@NonNull D1Task d1Task, @NonNull FragmentActivity activity) throws D1Exception {
    // Select your preferred authenticator type as AuthnType.BIOMETRIC
    AuthnType preferredAuthnType = AuthnType.BIOMETRIC;

    String customMessage = "Please authenticate with biometrics";

    d1Task.getD1Authn(activity, new AuthnCallback() {
        @Override
        public void onTransactionDataConfirmation(@NonNull Map<String, String> map, @NonNull AuthnUserConfirmationCallback authnUserConfirmationCallback) {
            // The 'map' contains the transaction data that is to be authenticated.
            // Application to display the content, prompt end uer either to 'proceed' or to 'deny' the authentication request.
        }

        @NonNull
        @Override
        public String onBiometricPromptMessage() {
            return customMessage;
        }
    });
}
```

{% endtab %}

{% tab title="Android Kotlin" %}

```kotlin
@Throws(D1Exception::class)
fun customizingBiometricPromptMessage(d1Task: D1Task, activity: FragmentActivity) {
    // Select your preferred authenticator type as AuthnType.BIOMETRIC
    val preferredAuthnType = AuthnType.BIOMETRIC

    val customMessage = "Please authenticate with biometrics"

    d1Task.getD1Authn(activity, object : AuthnCallback {
        override fun onTransactionDataConfirmation(map: Map<String, String>, authnUserConfirmationCallback: AuthnUserConfirmationCallback) {
            // The ‘map’ contains the transaction data that is to be authenticated.
            // Application to display the content, prompt end user either to ‘proceed’ or to ‘deny’ the authentication request.
        }

        override fun onBiometricPromptMessage(): String {
            return customMessage
        }
    })
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.payments.thalescloud.io/3d-secure/implement-3ds/implement-oob-flow-thales-authentication/enroll-the-authenticator.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
