5

I'm managing several e-commerce websites, they are all custom build and they all accept credit card payments via bank redirection (website redirects the client to bank's payment page, bank redirects client back to site after payment has been processed).

Once Chrome 80 was released, I noticed a common trend among all e-commerce websites, when the user has paid and is redirected from the bank back to the e-commerce site, all session cookies are missing. Thus the client is not recognized as the client who initiated the payment.

I'll try to illustrate the problem:

  • example.tld - user receives a session cookie
  • example.tld - user logs in with a valid email address
  • example.tld - user places order
  • example.tld - redirect user to mybank.tld
  • mybank.tld - user enter cc details, payment is successful
  • mybank.tld - redirect user to example.tld
  • example.tld - unknown user, no cookies! redirect user to error page

This problem ONLY happens with Chrome 80, all other browsers work fine (Firefox, Safari, Edge, mobile browsers like Samsung Internet, etc). Older versions of Chrome also work fine (<=79).

This problem happens in ALL the e-commerce websites that I manage, the only consistent thing between them is Chrome 80.

Of course all e-commerce sites are PCI certified, use TLSv1.2 and the session cookie is defined with "domain", "secure" (true) and "httpOnly" (true) parameters set. Expires is set to "Session".

Is this some kind of new security feature that clears all current sessions/cookies when Chrome detects visits to a bank?

PS: my issue is not related to the SameSite problems others have, because I am not using crosssite scripting, iframes or anything like that.

  • Would it be possible to give the bank a return URL that includes a session token in the URL itself rather than relying on cookies? – Stephen Ostermiller Apr 2 at 18:23
  • Unfortunately that is not possible for two reasons. The bank does not allow us to add anything to the two return URLs, one is /bank-success/ and the other is /bank-fail/. The second problem is with the bank POST request to /bank-success/, we may add an order ID only, which is not enough to be a session ID and would also lower overall security. – Jimbo Apr 3 at 9:58
1

At first glance the problem does not appear related to SameSite restrictions in the new Chrome v80. Apparently, that is exactly what causes the problem.

When the user is in the bank payment portal and has successfully paid, he is redirected back to the ecommerce site by a POST request to the "ok" URL. This POST request is seen as a crosssite request, thus Chrome removes the session cookies.

bank portal -> POST request -> ecommerce = lost cookies

The only solution is to enforce SameSite=None for all Chrom[e|ium] based browsers OR for all browsers except iOS/iPhone pre v13.

Note the bold "OR" in the above sentence. If you decide to set SameSite=None, you will brake some iOS/iPhone devices due to an Apple bug that incorrectly thinks that None is Strict.

A quick and dirty solution for Apache, is to use the following htaccess rule:

Header always edit Set-Cookie (.*) "$1; SameSite=None"

At the bottom of the [apple bug report] there is a more complete htaccess rule that avoids incompatible apple devices:

<If "%{HTTP_USER_AGENT} !~ /(iPhone; CPU iPhone OS 1[0-2]|iPad; CPU OS 1[0-2]|iPod touch; CPU iPhone OS 1[0-2]|Macintosh; Intel Mac OS X.*Version\x2F1[0-2].*Safari|Macintosh;.*Mac OS X 10_14.* AppleWebKit.*Version\x2F1[0-3].*Safari)/i">
    Header always edit Set-Cookie (.*) "$1; SameSite=None"
</If>

In the two htaccess rules above, there is one important detail that I need to mention. SameSite=None only works with Secure cookies. If your cookie already sets Secure then no further steps need to be taken. If your cookies don't set Secure, then you need to append it to the above rules: SameSite=None;Secure

More details here:

| improve this answer | |
  • I'm not sure I completely understand. Is this a correct interpretation? Chrome 80 has a new cookie policy. In addition to not allowing cookies to be set for 3rd-party requests, it also doesn't send any 1st-party cookies for a 3rd-party request. Because the bank is triggering a POST request to your site, the request is treated as a 3rd-party request and cookies are not included with that request. You can get around this by marking your first-party cookies as "SameSite=None" such that they get sent back on all 3rd-party requests. – Stephen Ostermiller Apr 3 at 13:21
  • Because the bank is using a POST request for the return URL, that request is being treated as a 3rd-party request and cookies are not sent. This is done to prevent cross site scripting and cross site forgery requests. See the table about half way down this page From Chrome's documentation it appears that they will send cookies if the checkout process at the bank takes less than 2 minutes (POST+LAX mitigation). Another workaround could be to have the bank use a GET request. – Stephen Ostermiller Apr 3 at 13:31
  • Couldn't you also get around this by forcing the user to click again? If somebody comes back from the bank and doesn't have a session cookie, couldn't you have a link that says "click here"? When the user clicks it, the request would be a first-party request and the cookies would magically re-appear. – Stephen Ostermiller Apr 3 at 13:34
  • Chrome's mistake, is that my session cookie was NOT set by the bank or a 3rd party, its set by the ecommerce application (1st-party cookie). But Chrome intervenes and removes it when the user makes the POST request. It would be more logical to block NEW cookies, not existing 1st-party cookies (so that the bank can't set its own session cookie for my econnerce sites). About the 2 minute POST+Lax mitigation, its not very solid, most elderly take 10+ minutes to pay. Unfortunately, our bank processor only supports POST because they submit an encrypted JSON object. – Jimbo Apr 3 at 14:42
  • Chrome prevents you from seeing the 1st-party cookie when a 3rd-party site sends a visitor to your site with a POST request. The cookie isn't "deleted," it just isn't sent with that particular request. This is intentionally done to prevent cross site forgery requests, it isn't a "mistake". But it will break your site unless you or your bank change something. – Stephen Ostermiller Apr 3 at 16:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.