Fixing issues with
SameSite cookies and 3-D Secure checkout flows
3-D Secure is a verification service for card payments taken online. From the point of view of a user or site, the flow generally looks like this:
- User enters their payment details on the site’s checkout;
- Site embeds or redirects to the appropriate page to verify that payment method (dependent on the user’s card, e.g. Visa, Amex, etc.);
- Third-party does its verification (via SMS or similar);
- Third-party returns the status to the main site, generally via a
The 3-D Secure interface may be displayed to the user in a number of different
ways: an iframe in the page, a pop-up, or a full page redirect. The common
pattern with all of these is a cross-site
POST request initiated at the end of
the 3-D Secure verification back to the original site. This is what causes a
challenge with the recent updates to apply a
SameSite=Lax by default behaviour
to cookies without a
SameSite value. In other words, cookies without a
SameSite attribute will not be included on the 3-D Secure
This means that final
POST request may appear to your server as a new session,
meaning your site may attempt to set new cookies for the user or treat them as
if they were not logged in.
There are a number of options to fix this based on your site's archicture.
Do not require cookies on the returning
Generally, the cookies on your site for maintaining the user's session are only
intended for first-party use. You do not want them sent on cross-site requests
as this loses the security benefits of implementing
SameSite=Lax by default,
e.g. it makes Cross-Site Request Forgery attacks easier.
Check if you are able to process the returning
POST request without the need
for any of your session cookies. For example, if the 3-D Secure challenge was
included in an
iframe then you may only need to display a status message
within the frame while sending a
postmessage() call to your top-level window
to complete the transaction.
If the returning
POST request is a top-level navigation / redirect and you
would like to display session-specific content to the user, then you may want to
- Process the incoming
POSTrequest without cookies recording any results you need in the back-end
- Respond with a
303redirect to an internal page for the result of the transaction, e.g.
- The subsequent
GETrequest is considered a "safe" method and will include any
This means that the redirected request will include your sites first-party cookies and can be used to display session-specific content.
Create short-lived, cross-site cookies for the returning
If you do need cookies on the returning
POST request, they need to be marked
SameSite=None; Secure attributes. You should not make your default
session cookies available to third-parties, so instead consider creating a
short-lived cookie that stores a token that allows you to link the incoming
POST request to the associated user or transaction on your back-end.
This flow might look like:
- Create a short-lived (e.g. 15 minutes) cookie that will enable you to identify
Set-Cookie: transaction-token=abc123abc; SameSite=None; Secure; Max-Age=900
- Check the
Refererheader on the returning
POSTrequest to ensure it matches the expected source.
- Use the token to initialise the existing session.
- Mark the token as used in your back-end to ensure it is not used again.