# How 3D Secure Authentication Works in the Adyen Salesforce Commerce Cloud Cartridge

> Learn how the Adyen SFCC cartridge handles 3D Secure 1 and 3D Secure 2 authentication for secure online payments. Understand the complete verification process.

- Repository: [Adyen/adyen-salesforce-commerce-cloud](https://github.com/adyen/adyen-salesforce-commerce-cloud)
- Tags: how-to-guide
- Published: 2026-02-23

---

**The Adyen Salesforce Commerce Cloud cartridge implements both 3D Secure 1 (redirect-based) and 3D Secure 2 (native) authentication flows by injecting 3DS2 data into payment requests, processing action-based responses from Adyen's API, and completing verification through dedicated controller endpoints that finalize transactions based on the authentication result.**

The adyen/adyen-salesforce-commerce-cloud repository provides a comprehensive integration for Salesforce Commerce Cloud (SFCC) that handles complex payment authentication protocols. Understanding how 3D Secure authentication is implemented within this cartridge is essential for developers customizing payment flows or troubleshooting authentication failures in SFRA (Storefront Reference Architecture) implementations.

## 3D Secure Authentication Flow Overview

The cartridge supports both **3D Secure 1** (full-page redirect) and **3D Secure 2** (native frictionless/challenge) flows. The implementation follows a three-stage server-side process:

1. **Build the payment request** – Injects 3DS2 authentication data into the Adyen Checkout request
2. **Handle the Adyen response** – Processes action-based responses (redirect for 3DS1, native for 3DS2)
3. **Complete the authentication** – Finalizes the transaction after shopper verification via `/payments/details` calls

## Stage 1: Building the Payment Request with 3DS2 Data

When a shopper clicks **Place Order**, the cartridge constructs a Checkout request in `adyenCheckout.createPaymentRequest`. After building the basic request object, the system calls `AdyenHelper.add3DS2Data` to inject the 3D Secure 2 payload.

### Injecting 3DS2 Payload in adyenHelper.js

The `add3DS2Data` function in [`src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js) adds the mandatory authentication fields that signal Adyen to use native 3DS2 when available:

```javascript
// adyenHelper.add3DS2Data – inserts the mandatory fields
jsonObject.authenticationData = {
  threeDSRequestData: {
    nativeThreeDS: 'preferred',   // ask Adyen to use native 3‑DS 2 if possible
  },
};
jsonObject.channel = 'web';
jsonObject.origin = `${request.getHttpProtocol()}://${request.getHttpHost()}`;
return jsonObject;

```

This configuration prioritizes 3D Secure 2 while maintaining fallback compatibility with 3D Secure 1 for issuers that do not support the newer protocol.

### Creating the Checkout Request

In [`src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/payments/adyenCheckout.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/payments/adyenCheckout.js), the `createPaymentRequest` function orchestrates the request building:

```javascript
let paymentRequest = AdyenHelper.createAdyenRequestObject(...);
AdyenHelper.setPaymentInstrumentFields(paymentInstrument, paymentRequest);
paymentRequest = AdyenHelper.add3DS2Data(paymentRequest); // ← 3‑DS 2 injection
// ...additional data, risk data, etc.
return doPaymentsCall(order, paymentInstrument, paymentRequest);

```

## Stage 2: Handling the Adyen Response

After sending the request to Adyen's `/payments` endpoint via `adyenCheckout.doPaymentsCall`, the cartridge examines the response for authentication actions stored in `paymentResult.action`.

### Processing Redirect Actions for 3DS1

If Adyen returns an `action.type === 'redirect'`, the cartridge stores the action JSON on the payment instrument:

```javascript
// Stored in paymentInstrument.custom.adyenAction
// This triggers the redirect to Adyen's hosted 3DS1 page

```

This redirect action indicates the transaction requires 3D Secure 1 authentication through an external hosted page, typically when the issuer does not support 3DS2 or when the transaction risk profile requires it.

### Handling Native 3DS2 Challenges

For `action.type === 'threeDS2'`, the cartridge similarly stores the action in `paymentInstrument.custom.adyenAction`. However, instead of a full page redirect, the SFRA front-end component (`AdyenComponent`) renders the 3D Secure 2 challenge automatically within an iframe or modal, providing a frictionless user experience.

## Stage 3: Completing the Authentication

The final stage differs based on whether the flow used 3D Secure 1 or 3D Secure 2, but both ultimately call `doPaymentsDetailsCall` to finalize the transaction.

### Finalizing 3DS1 Redirects

After the shopper authenticates on Adyen's hosted page, Adyen redirects back to the storefront with a `redirectResult` query parameter. The `redirect3ds1Response` controller in [`src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/payments/redirect3ds1Response.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/payments/redirect3ds1Response.js) handles this:

```javascript
function redirect(req, res, next) {
  try {
    const redirectResult = req.httpParameterMap.get('redirectResult').stringValue;
    const jsonRequest = { details: { redirectResult } };
    const result = adyenCheckout.doPaymentsDetailsCall(jsonRequest);

    if (result.resultCode === constants.RESULTCODES.AUTHORISED) {
      res.redirect(URLUtils.url('PaymentInstruments-List'));
    } else {
      res.redirect(URLUtils.url('PaymentInstruments-AddPayment', 'isAuthorised', 'false'));
    }
  } catch (error) {
    // error handling omitted for brevity
  }
  return next();
}

```

This function extracts the redirect result, calls `doPaymentsDetailsCall` to verify the authentication with Adyen, and redirects the shopper to either the saved cards list (on `AUTHORISED` status) or back to the add-payment page (on failure).

### Resolving 3DS2 Challenges

For 3D Secure 2, the stored `adyenAction` is consumed by the front-end JavaScript component. Once the shopper completes the challenge, the component posts the details back to the `/payments/details` endpoint. The `showConfirmation` script processes this:

```javascript
// showConfirmation.js – after the /payments call returns an action
if (paymentResult.action && paymentResult.action.type === 'threeDS2') {
  // Store the action on the payment instrument (already done server‑side)
  // The SFRA front‑end component reads paymentInstrument.custom.adyenAction
  // and renders the 3‑DS 2 challenge automatically.
}

```

The server-side logic then calls `doPaymentsDetailsCall` to finalize the transaction, using the same result handling logic as the 3DS1 flow to determine the final redirect destination.

## Key Implementation Files

The 3D Secure authentication implementation spans several critical files within the `src/cartridges/int_adyen_SFRA/cartridge/adyen/` directory:

| File | Role | Direct Link |
|------|------|-------------|
| [`adyenHelper.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/adyenHelper.js) – `add3DS2Data` | Injects native 3‑DS 2 fields into the Checkout request. | [adyenHelper.js](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js) |
| [`adyenCheckout.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/adyenCheckout.js) – `createPaymentRequest` | Builds the full payment payload and calls `add3DS2Data`. | [adyenCheckout.js](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/payments/adyenCheckout.js) |
| [`redirect3ds1Response.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/redirect3ds1Response.js) | Handles the `redirectResult` from a 3‑DS 1 flow and finalises the order. | [redirect3ds1Response.js](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/payments/redirect3ds1Response.js) |
| [`showConfirmation.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/showConfirmation.js) / [`handlePayment.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/handlePayment.js) | Consumes the `adyenAction` for a 3‑DS 2 challenge and drives the UI component. | [showConfirmation.js](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/scripts/showConfirmation/showConfirmation.js) |
| [`controllers/Adyen.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/controllers/Adyen.js) (comments) | Documents the overall payment‑status‑after‑redirect flow. | [Adyen controller](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/controllers/Adyen.js) |

## Summary

- The Adyen SFCC cartridge supports both **3D Secure 1** (redirect-based) and **3D Secure 2** (native frictionless/challenge) authentication methods through a unified implementation.
- **3DS2 data injection** occurs in [`adyenHelper.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/adyenHelper.js) via `add3DS2Data`, which sets `nativeThreeDS: 'preferred'` to prioritize modern authentication protocols.
- **Action handling** differentiates flows: `redirect` actions trigger 3DS1 external authentication, while `threeDS2` actions enable native challenge rendering via the front-end component.
- **Completion logic** unifies both flows through `doPaymentsDetailsCall`, with [`redirect3ds1Response.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/redirect3ds1Response.js) handling 3DS1 returns and [`showConfirmation.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/showConfirmation.js) managing 3DS2 resolutions.
- All authentication state persists in `paymentInstrument.custom.adyenAction`, enabling seamless handoff between server-side logic and client-side challenge rendering.

## Frequently Asked Questions

### What is the difference between 3D Secure 1 and 3D Secure 2 in the Adyen SFCC cartridge?

3D Secure 1 uses a full-page redirect to an Adyen-hosted authentication page, handled by [`redirect3ds1Response.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/redirect3ds1Response.js), while 3D Secure 2 uses a native challenge rendered within an iframe or modal via the front-end `AdyenComponent`, managed through [`showConfirmation.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/showConfirmation.js). The cartridge prioritizes 3DS2 by setting `nativeThreeDS: 'preferred'` in the payment request, falling back to 3DS1 only when the issuer does not support the newer protocol.

### How does the cartridge decide whether to use 3D Secure 1 or 3D Secure 2?

The decision is primarily driven by Adyen's risk engine and issuer capabilities, but the cartridge signals its preference through `AdyenHelper.add3DS2Data`, which injects `authenticationData` with `nativeThreeDS: 'preferred'`. If the issuer supports 3DS2, Adyen returns a `threeDS2` action; otherwise, it returns a `redirect` action for 3DS1. Both actions are stored in `paymentInstrument.custom.adyenAction` for processing.

### Where is the 3D Secure authentication state stored during the checkout process?

The authentication action—whether a redirect URL for 3DS1 or challenge data for 3DS2—is stored in the `paymentInstrument.custom.adyenAction` custom attribute. This server-side storage enables the front-end component to retrieve the action and render the appropriate challenge or redirect, while also allowing server-side scripts like [`redirect3ds1Response.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/redirect3ds1Response.js) to access the original transaction context when processing return redirects.

### What happens if a 3D Secure 1 authentication fails or is cancelled?

When the shopper returns from the 3DS1 redirect without successful authentication, the `redirect3ds1Response` controller extracts the `redirectResult` parameter and calls `doPaymentsDetailsCall` to verify the status with Adyen. If the result code is not `AUTHORISED` (defined in `constants.RESULTCODES`), the controller redirects the shopper to `PaymentInstruments-AddPayment` with `isAuthorised=false`, allowing the merchant to display an error message and prompt for alternative payment methods or retry the transaction.