New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 634311 link

Starred by 3 users

Issue metadata

Status: Fixed
Owner:
Closed: Oct 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 2
Type: Bug-Regression



Sign in to add a comment

Webview with ThirdParty Cookies disabled prevents a Websocket started from inside an Iframe to send the correct cookies

Reported by paulo.sa...@spreadex.com, Aug 4 2016

Issue description

THIS TEMPLATE IS FOR FILING BUGS ON THE ANDROID SYSTEM WEBVIEW. GENERAL WEB BUGS SHOULD BE FILED USING A DIFFERENT TEMPLATE!

Device name: Nexus 5 (and others)
Android version: 6.0.1 (and others)
WebView version (from system settings -> Apps -> Android System WebView): 52.0.2743.91
Application: Cordova application
Application version: 

URLs (if applicable): (using a dummy domain for the purpose of explaining the problem: www.xxxx.com)

Steps to reproduce:
(1) This is a Cordova application where the main frame is on local disk, the webview has Third Party cookie disabled
(2) The main frame contains an IFRAME that references our URL https://www.xxxx.com/login.html
(3) After logging in with an AJAX POST request a cookie is received:
Set-Cookie:ECR=PSDCr6DEnBidUTXnHeC7tg==; domain=.xxxx.com; path=/; secure; HttpOnly
(4) User is redirected to https://www.xxxx.com/index.html where a websocket is opened with the url wss://www.xxxx.com/api/signalr/connect

Expected result: websocket connection request should contain the cookie, as the domain of the websocket matches the domain of the IFRAME document

Actual result: websocket connection request does NOT contain the cookie, as seen with the Chrome Devtools on the remote Android device

This worked correctly in version 51 of the WebView.
Any other HTTP requests send the cookie correctly, ServerSentEvents and Ajax requests all send the cookies correctly.

NOTE: See some more info at the comments here: https://plus.google.com/117263508691705702027/posts/MH6g9EoCiD6

I think the problem was created in V52 with this issue (just because the title of the issue seems related): https://codereview.chromium.org/2102993002/

 

Comment 1 by torne@chromium.org, Aug 4 2016

Status: WontFix (was: Unconfirmed)
That is a third party cookie; you need to enable third party cookies for it to work. The domain of the websocket does not match the domain of the *top level document*, which is what defines whether cookies are first or third party.

The fact that it used to work was a bug.
In that case I believe the third party rule is not enforced correctly for AJAX calls inside IFRAMEs, as they send the 3rd party cookies for a domain different than the top level document.

Comment 3 by torne@chromium.org, Aug 4 2016

Cc: tyoshino@chromium.org mkwst@chromium.org
Components: Blink>Network>WebSockets Internals>Network>Cookies
Status: Untriaged (was: WontFix)
Hm. Actually, the setting is supposed to control whether third party cookies can be *set*, not whether they are sent: once they exist, they are sent anyway I believe?

It does sound like the websocket behaviour is not matching regular requests, in any case, so something is probably wrong here..

tyoshino@, mkwst@, am I being really dumb here and forgetting how cookies are supposed to work, or is this a real bug somewhere?

Comment 4 by mkwst@chromium.org, Aug 4 2016

1. If the user has opted into third-party cookie blocking, then we should not be sending or setting cookies along with cross-origin requests, regardless of whether they're triggered in an iframe or the top-level document or a worker or etc. 

If we're sending cookies along with XHR or `fetch()` or etc. requests that don't match the top-level origin, then we should fix it. Do you have a reproduction I could take a look at?

2. It's not clear from the description what the top-level origin actually is. What is the webview viewing? :)
On the top frame:
> document.location.href
"file:///android_asset/www/default/index.html"

On the child frame:
> document.location.href
"https://www.xxxx.com/login.html"

Comment 6 by torne@chromium.org, Aug 4 2016

So the *user* isn't necessarily doing anything here (since this is WebView, it's controlled by an API by the embedding app), and the API is explicitly documented as preventing third party cookies from being *set* - it doesn't mention whether they are sent with requests or not. I'm actually not sure what the current behaviour in WebView is for regular requests, let alone XHR or WebSockets.

Nonetheless, this use case very much sounds like it *is* third party cookies, and so enabling third party cookies is probably the right thing to do to fix the app, even if there is a bug that we are allowing them to be set/sent when we shouldn't.

I'll see if I can generate a repro later if I have time, unless the reporter can provide one?

Comment 7 by mkwst@chromium.org, Aug 4 2016

Well, I don't honestly know what the flag in WebView does. I'm describing the behavior of the "Block third-party cookies and site data" flag in Chromium's settings, and it's affect on the net stack. Hopefully we can make those mean the same thing without too much pain. :)

That said, I'll note that blocking third-party cookies while still sending them doesn't actually sound like blocking. *shrug*

Comment 8 by torne@chromium.org, Aug 4 2016

I would assume it has the same effect (even if the documentation doesn't say so), but it might not :(
Sorry, I don't think I'll be able to provide a repro, our app requires credentials to replicate the issue.

I worked around the problem by not using websockets on the website and falling back to SSE and long polling when accessed with the WebView.
I'll change our Android app to enable 3rd party cookies, as these transports may be affected in the future.
In my hands both websockets and XHRs receive, or do not receive, cookies identically, depending on the flag setAcceptThirdPartyCookies value.

If you're seeing something different, and want us to debug it, then could you please provide a minimal repro case.
I attach an APK that links to websocket.org and replicates the problem, admittedly not in an ideal way, but should be possible to make my point.

The main page of the app has a link and 2 IFRAMEs.
The link allows you to navigate to the websocket test page and have it as a top domain
The 1st IFRAME allows you to test websockets from within a child frame.
The 2nd IFRAME allows you to test AJAX requests from within a child frame.

If you attach the Chrome remote debugging tools to the device running the app you should see 
- when writing characters on the bing search box (2nd IFRAME) there are cookies sent with every AJAX request.
- when establishing a websocket connection on the first IFRAME there are no cookies sent, but there should be 3 cookies sent with the websocket request
- when clicking the top link and having the websocket test page on the top frame the 3 cookies are sent with the websocket request


pau.apk
739 KB Download
Owner: torne@chromium.org
Status: Assigned (was: Untriaged)
Owner: tobiasjs@chromium.org
We do indeed treat websockets differently (third party cookies are not set, regardless of the value of acceptThirdPartyCookies()). This is because websocket requests are not associated with a RenderFrame, which we (would) use to get the IO thread client. Chrome on the other hand just goes to content_settings.

Comment 15 by torne@chromium.org, Aug 19 2016

OK, so just to clarify what appears to have happened here, and hopefully get some advice from the cookie/websocket experts:

It looks like in older versions of WebView (51 and earlier), WebSocket requests simply ignored the webview third party cookie setting (because it's handled differently to Chrome's setting and is per-webview, as mentioned in #14), and *always* included cookies without considering whether the request was first or third party due to issue 618962.

However, when issue 618962 was fixed by https://codereview.chromium.org/2102993002/ it started respecting whether the request was first or third party, but *still ignores the webview third party cookie setting*, which means that now cookies are never included in a third party context even when this has been explicitly enabled :/


So the old behaviour was technically a privacy/security risk for websocket use cases where third party cookies were supposed to be disabled (as they actually weren't in webview), but the new (M52+) behaviour breaks apps that *rely* on third party cookies in websockets since they're now never sent :(

mkwst, tyoshino, others: any idea what to do here? We don't have a "global" third party cookie setting in WebView, only the one that's per-WebView and referenced by RenderFrame (which websocket connections don't seem to have).

Comment 16 by torne@chromium.org, Aug 19 2016

Labels: -Type-Bug M-54 ReleaseBlock-Stable Type-Bug-Regression
Probably too late to fix this for M53 now unfortunately, but we should definitely look at this for M54 at the latest.
Ping mkwst, tyoshino. Do you have any advice?
Hmm, so, it sounds that we should instantiate a ResourceRequestInfoImpl and associate it with the URLRequest created for the WebSocket in WebSocketStreamRequestImpl() as well as ResourceDispatcherHostImpl::ContinuePendingBeginRequest(), so that AwCookieAccessPolicy::GetShouldAcceptThirdPartyCookies() can retrieve the corresponding AwContentsIoThreadClient instance.

Comment 19 by torne@chromium.org, Sep 26 2016

Cc: tobiasjs@chromium.org
Owner: tyoshino@chromium.org
If it's possible to tie the websocket connection to a frame in that way then it seems like the existing policy would start working, yes; will you be able to do this for M54? It's a bit late now, already in beta :/
[Bulk edit]

This issue is listed as a release block stable for M54 Android.  We'll be cutting our stable candidate in just about two weeks, so time is running out to fix this bug - please prioritize working on it ASAP.

Are you sure this issue shouldn't block the release?  Remove the ReleaseBlock-Stable label.
Unsure if this issue should block the release, or know the issue should block the release but we won't be able to fix it in time?  CC me so that we can discuss.

Thanks!
Owner: yhirano@chromium.org

Comment 22 by torne@chromium.org, Sep 29 2016

Labels: -ReleaseBlock-Stable
Since this regressed in M52 I think it doesn't need to block the release, but we should definitely get it into trunk ASAP so we can test it.
[1] tests that WebSocket respects the global third-party cookie block policy. My understanding is it ignores the per-frame settings, is that correct? Is there any tests that test the per-frame settings for normal requests?

1: LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html

Comment 24 by torne@chromium.org, Sep 30 2016

I don't think anything outside WebView has any expectation that there are per-frame settings, so there won't be any layout tests for it. There's a unit test in webview for the setting itself (https://cs.chromium.org/chromium/src/android_webview/browser/aw_static_cookie_policy_unittest.cc) but I don't think it actually exercises the network stack, just the webview-specific part. Not sure if there's anything else.
bool AwCookieAccessPolicy::GetShouldAcceptThirdPartyCookies(
    const net::URLRequest& request) {
  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request);
  if (!info) {
    return false;
  }
  return GetShouldAcceptThirdPartyCookies(info->GetChildID(),
                                          info->GetRenderFrameID());
}


The URLRequest for WebSocket doesn't have the associated ResourceRequestInfo as it's created from net/websockets. We have the render frame id (content::WebSocketImpl::frame_id_) but we don't have a measure to pass it to AwCookieAccessPolicy.
Status: Started (was: Assigned)
Probably I can create a ResourceRequestInfoImpl and associated it to the request as in #18 but I'm not sure if it's the right thing to do.

But I'm trying to do it, at least.
Project Member

Comment 27 by bugdroid1@chromium.org, Oct 24 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/4a593833d44a457f177f99b2c907bd0f6ae397f7

commit 4a593833d44a457f177f99b2c907bd0f6ae397f7
Author: yhirano <yhirano@chromium.org>
Date: Mon Oct 24 18:58:22 2016

Provide child/frame IDs for WebSocket handshake request

AndroidCookiePolicy needs the child ID and the frame ID of a WebSocket
connection to determine if it allows the connection to attach
third-party cookies. This CL provide the additional information to the
WebSocket handshake net::URLRequest.

BUG= 634311 

Review-Url: https://codereview.chromium.org/2397393002
Cr-Commit-Position: refs/heads/master@{#427109}

[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/android_webview/browser/aw_cookie_access_policy.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerTest.java
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/BUILD.gn
[add] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_handshake_request_info_impl.cc
[add] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_handshake_request_info_impl.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_impl.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_impl.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_manager.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_manager.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/browser/websockets/websocket_manager_unittest.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/public/browser/BUILD.gn
[add] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/content/public/browser/websocket_handshake_request_info.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_channel.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_channel.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_channel_test.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_end_to_end_test.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_event_interface.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_handshake_stream_create_helper_test.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_stream.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_stream.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_stream_create_test_base.cc
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_stream_create_test_base.h
[modify] https://crrev.com/4a593833d44a457f177f99b2c907bd0f6ae397f7/net/websockets/websocket_stream_test.cc

Status: Fixed (was: Started)
Labels: -M-54 M-56

Comment 30 by aluo@chromium.org, Nov 1 2016

Verified on M56 56.0.2906.0 on Galaxy S6 Edge SM-G925T MMB29K

Sign in to add a comment