Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Overview
About Stripe payments
    Overview
    Currencies
    Declines
    Payouts
    Recurring payments
    3D Secure authentication
      Authenticate with 3D Secure
      SCA exemptions
      Standalone 3D Secure
      Import 3D Secure results
      Writing queries
    Refund and cancel payments
    Balances and settlement time
    Receipts
    Handle webhook events
    SCA readiness
Upgrade your integration
Payments analytics
Online payments
OverviewFind your use caseManaged Payments
Use Payment Links
Build a checkout page
Build an advanced integration
Build an in-app integration
Payment Methods
Add payment methods
Manage payment methods
Faster checkout with Link
Payment interfaces
Payment Links
Checkout
Web Elements
In-app Elements
Payment scenarios
Custom payment flows
Flexible acquiring
Orchestration
In-person payments
Terminal
Other Stripe products
Financial Connections
Crypto
Climate
HomePaymentsAbout Stripe payments3D Secure authentication

Authenticate with 3D Secure

Integrate 3D Secure (3DS) into your checkout flow.

Copy page

Caution

Major card brands no longer support 3D Secure 1. If your implementation uses 3D Secure 1, update it to use the Payment Intents and Setup Intents APIs. Using those APIs:

  • Supports 3D Secure 2 (3DS2).
  • Takes advantage of Dynamic 3D Secure.
  • Complies with European Strong Customer Authentication regulations.

You can integrate 3D Secure (3DS) authentication into your checkout flow on multiple platforms, including Web, iOS, Android, and React Native. This integration runs 3D Secure 2 (3DS2) when supported by the customer’s bank and falls back to 3D Secure 1 otherwise. To use Stripe’s 3DS service with other processors, contact support.

Checkout page

The customer enters their card details.

Loading symbol

The customer’s bank assesses the transaction and can complete 3D Secure at this step.

Authentication modal

If required by their bank, the customer completes an additional authentication step.

Control the 3DS flow

Stripe automatically triggers 3DS when required by regulations such as Strong Customer Authentication in Europe, industry guidelines such as the Credit Card Security Guidelines in Japan, if requested by an issuer with a soft decline code, or when certain Stripe optimisations apply.

You can also use Radar rules or the API to control when to prompt users to complete 3DS authentication, making a determination for each user based on the desired parameters. However, not all transactions support 3DS, for example wallets or off-session payments.

When a payment triggers 3DS, Stripe requires the user to perform authentication to complete the payment if 3DS authentication is available for a card. Depending on what front end you use, this might require you to display the 3DS Flow.

In a typical Payment Intent API flow that triggers 3DS:

  1. The user enters their payment information, which confirms a PaymentIntent, SetupIntent, or attaches a PaymentMethod to a Customer.
  2. Stripe assesses if the transaction supports and requires 3DS based on regulatory mandates, Radar rules, manual API requests, issuer soft declines, and other criteria.
  3. If 3DS is:
    • Not required: For example, because of an exemption, Stripe attempts the charge. The PaymentIntent transitions to a status of processing. If requested by the issuer with a soft decline, we automatically reattempt and continue as if required.
    • Not supported: The PaymentIntent transitions to a status of requires_payment_method. Depending on the reason 3DS was triggered, it might be permissible to continue to the authorisation step for the charge. In that case, the PaymentIntent transitions to a status of processing.
    • Required: Stripe starts the 3DS authentication flow by contacting the card issuer’s 3D Secure Access Control Server (ACS) and starting the 3DS flow.
  4. When Stripe receives 3DS flow information from the issuer, we attempt authentication. The PaymentIntent transitions to a status of requires_action:
    • See below for how to display the required 3DS action. Issuers might request different 3DS flow action types, which might not always result in visibly displaying a 3DS challenge (for example, a frictionless flow).
    • If the issuer doesn’t support 3DS at all or has an outage, Stripe might attempt to complete the payment without authentication if permissible.
    • Data for 3DS authentication requests is typically provided by the customer at the time of the transaction. To reduce friction and the possibility of failed authentication, we might complete these requests with data we infer from other sources such as data collected from your customer during the payment flow, records related to your customer’s past transactions with you, or relevant information available from the customer’s card or issuers.
    • If Stripe already has access to all the required 3DS data elements, our optimised 3DS server might attempt to complete the authentication request for you while confirming the PaymentIntent. This can result in the PaymentIntent directly transitioning to a status of processing if the 3DS flow succeeds, or to a status of requires_action if additional steps or data elements are required to complete the 3DS flow.
  5. Depending on the 3DS authentication result:
    • Authenticated: Stripe attempts the charge and the PaymentIntent transitions to a status of processing.
    • Failure: The PaymentIntent transitions to a status of requires_payment_method, indicating that you need to try a different payment method, or you can retry 3DS by reconfirming.
    • Other scenarios: Depending on the reason the payment triggered 3DS, it might be permissible to continue authorisation for the charge in edge cases. For example, a result of attempt_acknowledged leads to a charge and the PaymentIntent transitions to a status of processing.
      • An exception is when creating Indian e-mandates for recurring payments. Anything but an authenticated result is treated as failure.
  6. The PaymentIntent transitions to one of the following statuses, depending on the outcome of the payment: succeeded, requires_capture, or requires_payment_method.

To track whether 3DS was supported and attempted on a card payment, read the three_d_secure property on the card information in the Charge’s payment_method_details. Stripe populates the three_d_secure property when the customer attempts to authenticate the card – three_d_secure.result indicates the authentication outcome.

Use Radar rules in the Dashboard

Stripe provides default Radar rules to dynamically request 3DS when creating or confirming a PaymentIntent or SetupIntent. You can configure these rules in your Dashboard.

If you have Radar for Fraud Teams, you can add custom 3DS rules.

Manually request 3DS with the API

The default method to trigger 3DS is using Radar to dynamically request 3D Secure based on risk level and other requirements. Triggering 3DS manually is for advanced users integrating Stripe with their own fraud engine.

To trigger 3DS manually, set payment_method_options[card][request_three_d_secure] to any or challenge depending on what you want to optimise for when either creating or confirming a PaymentIntent or SetupIntent, or creating a Checkout Session. This process is the same for one-time payments or when setting up a payment method for future payments. When you provide this parameter, Stripe attempts to perform 3DS and overrides any dynamic 3D Secure Radar rules on the PaymentIntent, SetupIntent, or Checkout Session.

Command Line
cURL
curl https://api.stripe.com/v1/payment_intents \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d amount=1000 \ -d currency=usd \ -d "payment_method_options[card][request_three_d_secure]"=any

When to provide this parameter depends on when your fraud engine detects risk. For example, if your fraud engine only inspects card details, you know whether to request 3DS before you create the PaymentIntent or SetupIntent. If your fraud engine inspects both card and transaction details, provide the parameter during confirmation – when you have more information. Then pass the resulting PaymentIntent or SetupIntent to your client to complete the process.

Explore the request_three_d_secure parameter’s usage for each case in the API reference:

  • Create a PaymentIntent
  • Confirm a PaymentIntent
  • Create a SetupIntent
  • Confirm a SetupIntent
  • Create a Checkout Session

Set request_three_d_secure to any to manually request 3DS with a preference for a frictionless flow, increasing the likelihood of the authentication being completed without any additional input from the customer.

Set request_three_d_secure to challenge to request 3DS with a preference for a challenge flow, where the customer must respond to a prompt for active authentication.

Stripe can’t guarantee your preference because the issuer determines the ultimate authentication flow. You can find out what the ultimate authentication flow was by inspecting the authentication_flow on the three_d_secure property of the Charge or SetupAttempt. To learn more about 3DS flows, read our guide.

Caution

Stripe only requires your customer to perform authentication to complete the payment successfully if 3DS authentication is available for a card. If it’s not available for the given card or if an error occurred during the authentication process, the payment proceeds normally.

Stripe’s SCA rules run automatically, regardless of whether you manually request 3DS. Any 3DS prompts from you are additional and not required for SCA.

Display the 3DS flow

Stripe automatically displays the authentication UI in a pop-up modal when calling confirmCardPayment and handleCardAction. You can also redirect to the bank’s website or use an iframe.

Stripe.js collects basic device information during 3DS2 authentication and sends it to the issuing bank for their risk analysis.

Redirect to the bank website

To redirect your customer to the 3DS authentication page, pass a return_url to the PaymentIntent when confirming on the server or on the client.

After confirmation, if a PaymentIntent has a requires_action status, inspect the PaymentIntent’s next_action. If it contains redirect_to_url, that means 3DS is required.

next_action: { type: 'redirect_to_url', redirect_to_url: { url: 'https://hooks.stripe.com/...', return_url: 'https://mysite.com' } }

In the browser, redirect the customer to the url in the redirect_to_url hash to complete authentication.

var action = intent.next_action; if (action && action.type === 'redirect_to_url') { window.location = action.redirect_to_url.url; }

When the customer finishes the authentication process, the redirect sends them back to the return_url you specified when you created or confirmed the PaymentIntent. The redirect also adds payment_intent and payment_intent_client_secret URL query parameters that your application can use to identify the PaymentIntent associated with the purchase.

Display in an iframe

You can’t customise the authentication UI on the web to match your website’s design – the bank that issued the card controls the fonts and colours.

However, you can choose how and where to show the 3D Secure UI. Most businesses show it in a modal window above their payment page. If you have your own modal component, you can place the 3DS frame inside it. You can also show the authentication content inline with your payment form.

Confirm the PaymentIntent Server-side

When your customer is ready to complete their purchase, you confirm the PaymentIntent to begin the process of collecting their payment.

If you want to control how to display 3DS, provide a return_url, which is where the 3DS <iframe> is redirected when authentication is complete. If your site uses a content security policy, check that it allows iframes from https://js.stripe.com, https://hooks.stripe.com, and the origin of the URL you passed to return_url.

If you’re confirming from the front end, use the confirmCardPayment method in Stripe.js. For example, if you’re gathering card information using Stripe Elements:

stripe.confirmCardPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: {card: cardElement}, return_url: 'https://example.com/return_url' }, // Disable the default next action handling. {handleActions: false} ).then(function(result) { // Handle result.error or result.paymentIntent // More details in Step 2. });

If you confirm from your server, provide a return_url. Depending on your integration, you might want to pass other information to confirm as well.

Command Line
cURL
curl https://api.stripe.com/v1/payment_intents/{{PAYMENT_INTENT_ID}}/confirm \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ --data-urlencode return_url="https://example.com/return_url"

Check the PaymentIntent status Server-side

Next, inspect the status property property of the confirmed PaymentIntent to determine whether the payment completed successfully. The following list describes possible status values and their significance:

StatusDescription
requires_payment_methodThe request failed with a 402 HTTP status code, meaning that the payment was unsuccessful. Check the last_payment_error property and try again, collecting new payment information from the customer if necessary.
requires_captureThe request completed without authentication. You can continue to capture the funds.
requires_actionAn additional step such as 3DS is required to complete the payment. Ask the customer to return to your application to complete payment.
succeededThe payment completed, creating a Charge with the supplied payment method. No further steps are required.

On versions of the API before 2019-02-11, requires_payment_method appears as requires_source and requires_action appears as requires_source_action.

Render the 3DS iframe Client-side

When the value of the status property is requires_action, you need to complete an additional step before processing the payment. For a card payment that requires 3DS, the PaymentIntent’s status shows as requires_action and its next_action property appears as redirect_to_url. The redirect_to_url payload contains a URL that opens in an iframe to display 3DS:

var iframe = document.createElement('iframe'); iframe.src = paymentIntent.next_action.redirect_to_url.url; iframe.width = 600; iframe.height = 400; yourContainer.appendChild(iframe);

For 3DS2, card issuers are required to support showing the 3DS content at sizes of 250x400, 390x400, 500x600, 600x400, and full screen (dimensions are width by height). You might enhance the 3DS UI by opening the iframe at exactly one of those sizes.

Caution

You can’t use the sandbox attribute on the 3DS iframe. In live mode, the card issuer controls some content inside this iframe. Some issuers’ implementations fail if they’re sandboxed, and the payment won’t succeed.

Handle the redirect Client-side

After the customer completes 3DS, the iframe redirects to the return_url you provided when confirming the PaymentIntent. That page needs to postMessage to your top-level page to inform it that 3DS authentication is complete. Your top-level page then needs to determine whether the payment succeeded or requires further action from your customer.

For example, you might have your return_url page execute:

window.top.postMessage('3DS-authentication-complete');

Your top payment page needs to listen for this postMessage to know when authentication has finished. You then need to retrieve the updated PaymentIntent and check the status of the payment. If the authentication failed, the PaymentIntent’s status is requires_payment_method. If the payment completed successfully, the status is succeeded. If you use separate authorise and capture, the status is requires_capture instead.

function on3DSComplete() { // Hide the 3DS UI yourContainer.remove(); // Check the PaymentIntent stripe.retrievePaymentIntent('{{PAYMENT_INTENT_CLIENT_SECRET}}') .then(function(result) { if (result.error) { // PaymentIntent client secret was invalid } else { if (result.paymentIntent.status === 'succeeded') { // Show your customer that the payment has succeeded } else if (result.paymentIntent.status === 'requires_payment_method') { // Authentication failed, prompt the customer to enter another payment method } } }); } window.addEventListener('message', function(ev) { if (ev.data === '3DS-authentication-complete') { on3DSComplete(); } }, false);

Test the 3DS flow

Use a Stripe test card with any CVC, postal code, and future expiry date to trigger 3DS authentication challenge flows while in a sandbox.

When you build an integration with your test API keys, the authentication process displays a mock authentication page. On that page, you can either authorise or cancel the payment. Authorising the payment simulates successful authentication and redirects you to the specified return URL. Clicking the Failure button simulates an unsuccessful attempt at authentication.

Number3DS usageDescription
RequiredThe payment must always complete 3DS2 authentication to be successful. By default, your Radar rules request 3DS authentication for this card.
RequiredThis card requires 3DS2 authentication for off-session payments unless you set it up for future payments. After you set it up, off-session payments no longer require authentication.
Required3DS authentication is required, but payments will be declined with a card_declined failure code after authentication. By default, your Radar rules request 3DS authentication for this card.
Supported3DS authentication can still be performed, but isn’t required. By default, your Radar rules won’t request 3DS authentication for this card.
SupportedThis card supports 3DS, but it isn’t enrolled in 3DS. This means that if your Radar rules request 3DS, the customer won’t go through additional authentication. By default, your Radar rules won’t request 3DS authentication for this card.
Not supportedThis card doesn’t support 3DS and you can’t invoke it. The PaymentIntent proceeds without performing authentication.

All other Visa and Mastercard test cards don’t require authentication from the customer’s card issuer.

You can write custom Radar rules in a test environment to trigger authentication on test cards. Learn more about testing your Radar rules.

Disputes and liability shift

The liability shift rule applies to payments successfully authenticated using 3D Secure. In some cases, liability shift applies with equivalent cryptograms, such as Apple Pay or Google Pay. If a cardholder disputes a 3DS payment as fraudulent, the liability typically shifts from you to the card issuer.

If a card doesn’t support 3DS or an error occurs during the authentication process, the payment proceeds normally. When this occurs, liability doesn’t generally shift to the issuer, because a successful 3DS authentication hasn’t taken place.

In practice, this means you typically won’t receive disputes marked as fraudulent if the payment is covered by the liability shift rule, but you might still receive an Early Fraud Warning. You might still receive a low percentage of fraudulent disputes, and we list a few cases below where the liability shift rule might not apply.

You might receive a dispute enquiry on a successfully authenticated payment using 3DS. This type of dispute doesn’t precipitate a chargeback because it’s only a request for information.

If you receive an enquiry for a 3D-Secure-authenticated charge, you must respond. If you don’t, the cardholder’s bank can initiate a financial chargeback known as a “no-reply” chargeback that could invalidate the liability shift. To prevent no-reply chargebacks on 3DS charges, submit sufficient information about the charge. Include information about what was ordered, how it was delivered, and who it was delivered to (whether it was physical or electronic goods, or services).

Note

If a customer disputes a payment for any other reason (for example, product not received), then the standard dispute process applies. Make informed decisions about your business management, especially in handling and completely avoiding disputes.

Liability shift might also occur when the card network requires 3DS, but it isn’t available for the card or issuer. This can happen if the issuer’s 3DS server is down or if the issuer doesn’t support it, despite the card network requiring support. During the payment process, the cardholder isn’t prompted to complete 3DS authentication, because the card isn’t enrolled. Although the cardholder didn’t complete 3DS authentication, liability can still shift to the issuer.

Stripe returns the requested Electronic Commerce Indicator (ECI) in the electronic_commerce_indicator of the 3DS authentication outcome. This indicator can aid in determining whether a charge should adhere to the liability shift rule. As 3DS occurs subsequent to the initial payment intent response, you typically get this from a charge.succeeded event that’s sent to one of your configured webhook endpoints or other event destinations. A requested ECI might be degraded in the issuer response, which we don’t reveal.

Sometimes payments that are successfully authenticated using 3DS don’t fall under liability shift. This is rare and can happen, for example, if you have an excessive level of fraud on your account and are enrolled in a fraud monitoring programme. Certain networks have also exempted some industries from liability shift. For example, Visa doesn’t support liability shift for businesses engaging in wire transfer or money orders, non-financial institutions offering foreign or non-fiat currency, or stored-value card purchase or load.

In rare cases, liability shift might get downgraded post-authorisation, or the card networks’ dispute rejection system might fail to catch liability shift for a transaction. In these cases, if you counter the dispute, Stripe automatically adds the requested ECI and the 3DS authentication outcome for the payment to your evidence details, but we encourage you to include additional details to improve your odds of winning the dispute.

Custom Radar rules for 3DS and liability shift

If you have Radar for Fraud Teams, you can customise your rules to control when to request 3DS and how to handle each specific authentication outcome and liability shift. Stripe’s Strong Customer Authentication (SCA) rules run automatically and independently of custom Radar rules, and block unauthenticated payments unless exempted.

See also

  • Import 3DS results
  • Authentication analytics
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access programme.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc
Related Guides
Strong Customer Authentication (SCA) readiness
Prevent disputes and fraud
Products Used
Payments
Radar