ddtcorex

30 Sept 2026 · 5 min read

3-D Secure 2 and SCA flows in a Magento checkout

How Cardinal 3DS2 challenge and frictionless flows satisfy SCA inside a Magento checkout without killing conversion

Part 4 of the Checkout & Payments series — prove the payer without losing the sale.

The redirect that eats conversion

The customer clicks Place Order, the bank asks for proof, and the checkout hands the session to someone else. If the proof flow breaks, the order hangs in pending payment, the quote stays active, and the customer pays twice trying again. Strong Customer Authentication under PSD2 made this flow mandatory for most European transactions, and 3-D Secure 2 is how cards comply. This post maps the Cardinal 3DS2 challenge and frictionless flows onto a Magento checkout so the handoff returns cleanly.

Why 3DS2 and SCA matter

SCA requires two of three factors: knowledge, possession, inherence. For cards, the issuing bank decides whether the transaction needs proof and how much friction to apply. A frictionless flow approves silently on risk data. A challenge flow demands interaction: an app prompt, an SMS code, a biometric check. Magento sits in the middle, collecting the browser and order signals the bank scores, then honoring the verdict.

The Magento side most often uses Cardinal Commerce (the CardinalCommerce module behind Braintree and several other integrations) as the 3DS2 provider. Cardinal brokers the device fingerprint, the authentication request, and the challenge iframe, then returns a signed result the gateway command consumes. The merchant never sees the bank credentials; Magento only sees pass, challenge, or reject plus the liability shift flags.

How it works

The flow has four steps, and each has a distinct failure mode.

1. Device data collection. Before authorize, the checkout loads the Cardinal songbird script and collects browser signals: user agent, screen, timezone, plus the order context (amount, currency, billing match). This runs silently while the customer reviews the order. Ad blockers and strict CSP rules are the usual killers here; if the fingerprint never uploads, the bank scores the transaction blind and challenges more often.

2. Authentication request (AReq/Ares). The authorize command sends the fingerprint reference, amount, and account history to Cardinal, which queries the issuer directory. Three outcomes return: frictionless approve (transStatus Y), challenge required (transStatus C), or reject. Magento must persist the threeDSecure reference and the authenticationValue even on frictionless approve, because capture and disputes need them later.

3. Challenge display. On transStatus C, Cardinal returns a challenge URL or embedded flow. Magento opens it in an iframe or redirect, the issuer interacts with the cardholder, and Cardinal posts back a result (RReq) with the final transStatus and the eci flag. This is where session handling matters: the quote is still active, the order may exist in pending_payment state, and the return route must resolve the same payment by increment ID, not by a new quote. Losing the session here orphans the authentication against a quote the customer already left.

4. Authorize with liability data. The gateway command completes authorize only after verifying the signed result, then stores liability_shifted, liability_shift_possible, three_d_secure_version, and the authenticationValue in additional_information. Capture uses the same parent transaction linkage as any gateway flow. A challenge passed but not stored authorizes the money without the liability shift, which is the worst outcome: paid, but the fraud risk stays with the merchant.

Cardinal configuration that matters: environment (sandbox versus production directory server), requestor ID and key per website, challenge window size for the iframe, and the fallback for transStatus N (attempted but not authenticated). Test matrix minimum: frictionless approve, challenge pass, challenge fail, challenge abandon, and timeout. Each path must leave the quote and order in a retry-safe state.

Pitfalls

  • Blocking the Cardinal script with CSP. A strict script-src without the Cardinal domain silently kills device collection. The checkout still works, but frictionless rates collapse and support sees a wave of avoidable challenges. Allowlist the provider domains and monitor the fingerprint upload rate.
  • Creating a new quote on the 3DS return. Redirect-based challenges return to a fresh session or a different store view, and naive return controllers create a new active quote instead of reloading the pending order. Resolve by reserved_order_id or masked ID from the return payload, never by current session cart.
  • Authorizing before verifying the signed result. Trusting the front-end callback without server-side verification of the Cardinal signature lets a manipulated response authorize a rejected authentication. Verify in the command, using the provider SDK, before touching the transaction.
  • Dropping liability fields on capture. Capture and refund handlers that copy only amount and transaction ID lose the eci and authenticationValue the dispute flow needs. Persist the full 3DS result block in additional_information at authorize time and carry it forward.
  • No path for abandoned challenges. Customers close the challenge tab. If the order sits in pending_payment with the quote deactivated and no retry button, the sale is lost and the stock stays reserved. Offer resume from the account order view and expire pending payment orders on a schedule.

Field check on a live store

Take one order stuck in pending payment after 3DS. Check additional_information for the 3DS block: missing three_d_secure_version means device collection never ran; present AReq but missing RReq means the challenge never returned; present RReq with transStatus C unresolved means verification failed. Then replay the same card in sandbox across the five test outcomes and confirm each leaves a retryable state. On one store, a sudden challenge spike traced to a CSP deploy that blocked the fingerprint script the same morning. One allowlist line restored frictionless rates without touching payment code.

Closing

SCA decides the friction, Cardinal brokers the proof, and Magento must preserve identity across the handoff. Collect device data early, verify the signed result server side, store the liability flags, and make every outcome retryable. With authentication settled, the remaining risk is mechanical: the same authenticated intent submitted twice. That is the idempotency problem.

Next in this series:

magento2-payments-idempotency

magento2paymentssecurity