[Webkit-unassigned] [Bug 232440] New: Service Worker break sameSite=lax cookied

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Thu Oct 28 10:18:25 PDT 2021


https://bugs.webkit.org/show_bug.cgi?id=232440

            Bug ID: 232440
           Summary: Service Worker break sameSite=lax cookied
           Product: WebKit
           Version: Safari 15
          Hardware: All
                OS: All
            Status: NEW
          Severity: Blocker
          Priority: P2
         Component: Service Workers
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: erik.witt at baqend.com

Hi there!

We found a severe bug that prevents cookies with the sameSite=lax option to be sent to the server when on navigation request when the page uses a simple Service Worker.

The short version of the issue is:
* A site uses a session cookie with option sameSite=lax which is set and send through by the HTML request/response
* User navigates away from the page and then comes back to it
* Session cookie is not sent to the server (even though it is still there in the browser) causing the server to assign a new session cookie for the now unknown user
* This only happens when the request is fetched by a Service Worker

There are serious consequences of this, e.g. with 3rd party payment providers involved, this can lead to an aborted checkout at the summary step (since the session is lost), i.e. Safari users are unable to buy stuff in some online shops.

------- This is the long version of what we found, including the setup to reproduce and a workaround in the Service Worker -------

We have build a simple test page that sets a few different cookies to show the different sameSite options: https://clone-test.app.baqend.com/v1/code/swTest

The page shows a number at the top, which is the "session id" generated by the server that is also send as a cookie to the client. If the browser sends that cookie back when reloading, the "session id" on the page does not change. The page also has a few links for the different scenarios that can be tested with it. The last element on the page show the currently active Service Worker, wich should state "None" unless you clicked one of the scenario links.


# Scenario I (no Service Worker, everything is fine)

1. Go to the page https://clone-test.app.baqend.com/v1/code/swTest and remember the "session id" at the top
2. Reload the page and see that the "session id" is still the same
3. In the same tab, go to google.com
4. Click on the back navigation of the browser and see that the "session id" is still the same

Everything good in this scenario as you see. The only thing that we noticed (an which might be related to the issue - hard to say) is this: The sameSite=strict cookie is not sent to the server when returning from google (as is probably the intended behaviour even though Chrome will send it). But after returning from Google and reloading the page (ctrl+r), the cookie is still not sent to the server which is a bit strange. Only when you hit the first link on the page "Test link to navigate page" the cookie is sent to the server. After the navigation even the reloads send the strict cookie.

# Scenario II (simple Service Worker, now things break!)

1. Go to the page https://clone-test.app.baqend.com/v1/code/swTest and remember the "session id" at the top
2. Click the second link on the page to install the Service Worker "Install SW that is just fetches incoming request"
3. Reload the page a few times and see that the "session id" does not change, even when the Service Worker is active and fetching the HTML request. You should see on the page that there is a Service Worker now. "Current Service Worker https://clone-test.app.baqend.com/simpleSW.js"
4. In the same tab, go to google.com
5. Click on the back navigation of the browser and see that the "session id" has changed!

After returning from google.com, the HTML request does not send the session id cookie. In fact out of the 4 cookies that are present in the browser, only two cookies are sent (one with sameSite=none and one without sameSite option set). The ones with sameSite=strict and sameSite=lax are not sent!

Even when reloading the page, the sameSite=lax cookie is not sent resulting in an ever changing "session id". Again, only when you klick the first link an do a navigation on the page, the sameSite=lax cookie is again sent to the server and the "session id" will stay the same on reloads afterwards.

The Service Worker that was installed looks like this and could not be simpler. Not that the request going into the Service Worker has the option `credentials: include` set.
```
self.addEventListener('fetch', (event) => {
  event.respondWith(fetch(event.request));
});
```

# Scenario III (the Service Worker that fixes the issue)

1. Go to the page https://clone-test.app.baqend.com/v1/code/swTest and remember the "session id" at the top
2. If you still have a Service Worker installed click the fourth link "https://clone-test.app.baqend.com/v1/code/swTest?unregisterSW=1" and reload the page to uninstall it.
3. Click the third link on the page to install the Service Worker "Install SW copies the request before fetching"
4. Reload the page a few times and see that the "session id" does not change, even when the Service Worker is active and fetching the HTML request. You should see on the page that there is a Service Worker now. "Current Service Worker https://clone-test.app.baqend.com/copySW.js"
5. In the same tab, go to google.com
6. Click on the back navigation of the browser and see that the "session id" is still the same. It works again!

The Service Worker is just slightly different. It creates a new request with the same url and the option to include credentials (even though the incoming request had this option set already):
```
self.addEventListener('fetch', (event) => {

  const newRequest = new Request(event.request.url, { credentials: 'include' });

  event.respondWith(fetch(newRequest));
});

```
With this Service Worker the sameSite=lax request is sent and even the sameSite=strict cookie is sent to the Server when returning from Google (which was not the case without the Service Worker.



I hope the explanations where clear enough to follow since it is quite a complicated issue. Looking forward to your feedback and questions.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20211028/3b00d60a/attachment.htm>


More information about the webkit-unassigned mailing list