> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gr4vy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Secure Fields and 3DS

> Handling 3DS in Secure Fields.

## Overview

Secure Fields supports two distinct 3-D Secure approaches: a **Native** implementation you build and control, and a **Hosted** solution managed by Gr4vy. Both support Dynamic 3-D Secure configuration via Flow rules.

## Choose your approach

| Approach       | Best for                                     | Implementation                                                |
| -------------- | -------------------------------------------- | ------------------------------------------------------------- |
| **Native 3DS** | Custom UI, full control, embedded experience | You build the 3DS challenge UI using Secure Fields components |
| **Hosted 3DS** | Minimal setup, rapid deployment              | Gr4vy provides a fully managed 3DS flow                       |

<Card title="Hosted 3DS Solution" icon="arrow-right" href="/guides/features/3ds/hosted">
  Learn how to use the hosted 3DS solution with Secure Fields.
</Card>

## Native 3DS implementation

### Prerequisites

Native 3DS requires merchant account-level 3-D Secure configuration to be set up. This is different from the per-connection setup and must be enabled before using the native implementation.

<Card title="Merchant account-level configuration" icon="arrow-right" href="/guides/features/3ds/setup#merchant-account-level-configuration-beta">
  Follow the setup guide to configure 3DS at the merchant account level.
</Card>

### How it works

Native 3DS automatically handles all device fingerprinting requirements, including collecting the device's IP address, user agent, and other authentication metadata needed for 3-D Secure compliance. You don't need to manually collect or pass this data—the implementation handles it transparently.

### Limitations & Considerations

When you use native 3DS with Secure Fields, it is important to pass the transaction context (for example, `metadata`, `merchant_initiated`, or `cart_items`) when you create the Checkout Session.
As native 3DS runs before transaction creation, so this context must already be present at session creation time to find the right 3DS profile, as well as take into consideration any flow rules.

Additionally, it's important to note that the system runs 3DS Flow rules at the time of the enrollment check, which is run at the time of submitting Secure Fields. Currently, this Flow rule check doesn't
support anti-fraud checks as these are currently tied to a transactions, though there are plans to add this in the near future.

### Initialization

There are two ways to initialize the native 3-D Secure component:
as a React component or through the vanilla JavaScript API
(in Node or CDN scenarios).

The property `challengeWindowSize` controls the size of the challenge window and
can be set to the following values:

| Value  | Dimensions                          |
| ------ | ----------------------------------- |
| `'01'` | 250px × 400px                       |
| `'02'` | 390px × 400px                       |
| `'03'` | 500px × 600px                       |
| `'04'` | 600px × 400px                       |
| `'05'` | Full container dimensions (default) |

<Info>
  The examples use a `<dialog>` as the container for the 3-D Secure UI,
  but any container can be used.
</Info>

<CodeGroup>
  ```tsx React theme={"system"}
  import { useRef } from 'react';
  import { ThreeDSecure } from '@gr4vy/secure-fields-react';

  function ThreeDSecureWrapper() {
    const containerRef = useRef(null);
    return (
      <dialog ref={containerRef} open={false}>
        <ThreeDSecure
          ref={containerRef}
          // optional, if omitted it defaults internally to "05"
          challengeWindowSize="05"
        />
      </dialog>
    );
  }
  ```

  ```html Node / CDN theme={"system"}
  <dialog id="three-d-secure-container"></dialog>

  <!-- approach 1 -->
  <script>
    secureFields.addThreeDSecure(
      // you can pass a selector for the container
      '#three-d-secure-container',
      // and optionally, a configuration object, if omitted it defaults
      // internally to the value provided here
      { challengeWindowSize: '05' }
    );
  </script>

  <!-- approach 2 -->
  <script>
    // alternatively, you can initialize 3-D Secure also
    // passing the container itself
    const container = document.getElementById('three-d-secure-container');
    // the configuration object (2nd parameter) is optional
    secureFields.addThreeDSecure(container);
  </script>
  ```
</CodeGroup>

### Showing the 3-D Secure UI

With the `3-D Secure start callback`, the 3-D Secure process start can be detected,
allowing the container UI to be displayed.

<CodeGroup>
  ```tsx React theme={"system"}
  // element is the element specified by ref.
  <ThreeDSecure
    onThreeDSStart={({ element }) => element?.showModal()}
    ref={containerRef}
  />
  ```

  ```ts Node / CDN theme={"system"}
  secureFields.addEventListener(
    SecureFields.Events.THREE_DS_START,
    // element is the element specified during initialization,
    // by addThreeDSecure().
    ({ element }) => element.showModal()
  )
  ```
</CodeGroup>

### Receiving the 3-D Secure result

With the `3-D Secure finish callback`, the 3-D Secure process finish can be detected,
allowing any UI element that was shown during the process to be dismissed and the
outcome of the process to be received.

<CodeGroup>
  ```tsx React theme={"system"}
  <ThreeDSecure
    ref={containerRef}
    onThreeDSStart={({ element }) => element?.showModal()}
    onThreeDSFinish={({ element, tokenized, authentication }) => {
      // here you can perform operations based
      // on tokenized or authentication

      element?.close(); // you can also clear any UI container
    }}
  />
  ```

  ```ts Node / CDN theme={"system"}
  secureFields.addEventListener(
    SecureFields.Events.THREE_DS_FINISH,
    ({ element, tokenized, authentication }) => {
      // here you can perform operations based
      // on tokenized or authentication

      element.close(); // you can also clear any UI container
    }
  )
  ```
</CodeGroup>

These are the arguments received by the `3-D Secure finish callback`:

| Argument         | Type          | Description                                                                 |
| ---------------- | ------------- | --------------------------------------------------------------------------- |
| `element`        | `HTMLElement` | The HTML container (for example, dialog) used to display the 3-D Secure UI. |
| `tokenized`      | `boolean`     | Indicates whether the card data was successfully tokenized.                 |
| `authentication` | `Object`      | The result of the 3-D Secure authentication.                                |

The `authentication` object contains the following properties:

| Property             | Type             | Description                                           |
| -------------------- | ---------------- | ----------------------------------------------------- |
| `transaction_status` | `"Y"`            | The transaction was successful                        |
|                      | `"N"`            | The transaction failed.                               |
|                      | `null`           | The transaction status is unknown                     |
| `type`               | `null`           | The flow failed because the card used is not enrolled |
|                      | `"challenge"`    | The flow required the user to perform a challenge     |
|                      | `"frictionless"` | The flow was successful without requiring a challenge |
|                      | `"error"`        | The flow encountered an error during the process      |
| `attempted`          | `boolean`        | Indicates if authentication was attempted             |
| `timed_out`          | `boolean`        | Indicates if the authentication process timed out     |
| `user_cancelled`     | `boolean`        | Indicates if the user cancelled the challenge         |

## After authentication

Once you receive the 3-D Secure authentication result, you can determine whether authentication was attempted and whether it was successful. You can then proceed to create a transaction regardless of the outcome.

The `authentication` object provides the following key signals:

* **`attempted`**: Whether the authentication process was initiated
* **`timed_out`**: Whether the authentication timed out before completing
* **`user_cancelled`**: Whether the user dismissed the challenge
* **`transaction_status`**: The final result (`"Y"` = success, `"N"` = failed, `null` = unknown)

Based on these values, you can decide to proceed with the transaction creation or inform the user accordingly. The authentication result is included in the transaction response and can be used for reporting, compliance, or business logic decisions.

## Testing and validation

To test your Native 3DS implementation, use the 3DS Test Cards in your sandbox environment. These cards allow you to simulate various outcomes, including frictionless authentication, mandatory challenges, and specific failure states.

### Test cards

#### Visa

| Card Number           | Expected 3DS Outcome                                           |
| --------------------- | -------------------------------------------------------------- |
| `4000 0000 0000 0010` | Frictionless Success: Authenticated without user interaction.  |
| `4000 0000 0000 0028` | Challenge Required: Triggers a 3DS challenge UI.               |
| `4000 0000 0000 0044` | Authentication Failed: Simulates a "Not Authenticated" result. |
| `4000 0000 0000 1042` | Rejected: The authentication request was explicitly rejected.  |

#### Mastercard

| Card Number           | Expected 3DS Outcome                                                       |
| --------------------- | -------------------------------------------------------------------------- |
| `5100 0000 0000 0010` | Challenge Required: Triggers a 3DS challenge UI.                           |
| `5200 0000 0000 2052` | Frictionless Success: Authenticated without user interaction.              |
| `5200 0000 0000 1039` | Unavailable: Simulates a scenario where 3DS is not available for the card. |
| `5100 0000 0000 0065` | Suspected Fraud: Frictionless failure due to suspected fraud.              |

#### American Express

| Card Number          | Expected 3DS Outcome                                          |
| -------------------- | ------------------------------------------------------------- |
| `3415 0209 8634 895` | Frictionless Success: Authenticated without user interaction. |
| `3486 3826 7931 507` | Challenge Required: Triggers a 3DS challenge UI.              |
| `3456 9539 9207 589` | Authentication Failed: Frictionless failure.                  |

### Challenge screen inputs

When a challenge is triggered, use the following values to simulate different transaction results.

#### OTP (One-Time Password)

When the challenge screen asks for a code, enter one of the following:

| OTP Code | Resulting Transaction Status | Description                       |
| -------- | ---------------------------- | --------------------------------- |
| `1234`   | Y                            | Success / Authenticated.          |
| `1111`   | N                            | Not Authenticated.                |
| `2222`   | R                            | Rejected.                         |
| `3333`   | U                            | Unavailable / Unable to complete. |

#### Selection options

Some challenges may present a list of options (for example, "Select your favorite city").

**Single-select**

* Paris or Nice: Returns Success (Y).

**Multi-select**

* Paris & Lyon: Returns Success (Y).
* Toulouse & Lyon: Returns Success (Y).

### Best practices for testing

1. Verify UI transitions: Ensure your app correctly transitions from the card entry screen to the 3DS challenge modal and back.
2. Test error states: Use the "Rejected" or "Failed" cards to ensure your app displays helpful messaging to the user when a card cannot be verified.
3. Check authentication outcome: After a successful test, verify that the `authentication` object in your callback reflects the expected result before attempting the final transaction.
