How can I delete an httpOnly cookie from android webView cookiemanager without deleting all other cookies?
GetCookie does not return HTTPOnly cookies and so I can not set it to expired.
I need cookies from other sites to remain in tact.
Related
I am seeing behavior on a native Android app where the last response that returns a Set-Cookie is not the same cookie used on successive calls to the same domain. The cookie store can return an older copy of that cookie.
The code uses the default CookieHandler and CookieManager with the default InMemoryCookieStore.
The app can receive session cookies from multiple hosts on the same domain, the session cookies are good on any calls to the same domain. The app calls about 4 different hosts, host1.example.com, through host4. Any of these calls can respond with a Set-Cookie header to refresh the SESSION cookie.
The problem I see is the Cookie store will store these cookies in a Map keyed by the full hostname. The domain on the cookie is: .example.com
host3.example.com - SESSION=xyx; path=/; domain=.example.com; secure; HTTPOnly
host2.example.com - SESSION=sde; path=/; domain=.example.com; secure; HTTPOnly
host1.example.com - SESSION=8xd; path=/; domain=.example.com; secure; HTTPOnly
host4.example.com - SESSION=22d; path=/; domain=.example.com; secure; HTTPOnly
When the cookies are requested for a new http request, the cookie store iterates over the map looking for the domain matching the domain on the cookie, which is .example.com. It finds this in the first entry, say host3, then continues on through the list. All other domains that match the cookie are excluded as duplicates and it returns the SESSION=xyx which can be old and expired (There is no expiration set on these cookies.) The last update on the Cookie may have been from host1 so the returned cookie from host3 is not the latest.
What's also odd, is the full host is ignored and only the domain is considered. The request url cam be host1.example.com but it'll still match host3 since matches the domain and is the first in the entry set from the map. I only find that as odd since the full hostname is used as the key but never considered.
I looked through the RCF6265 and didn't see any mention to this specific behavior but the rfc seemed to sound like it should provide the latest cookie from that domain.
Is there a defined behavior for this and is the Android InMemoryCookieStore behaving incorrectly?
I'm currently developing a cordova app with an ADFS authentication through inappbrowser.
This works well so far. But I need to retrieve the session cookie stored in the webview instance and be able to use it in another application with the same mechanism, so the user doesn't need to log in twice, as both apps use the same corporate login.
I've tried recovering the cookie with CookieManager
CookieManager cookieManager = CookieManager.getInstance();
String cookies = cookieManager.getCookie(url);
However, it doesn't list the session cookie. It seems CookieManager doesn't return those cookies without expiration date.
I've been able to successfully terminate the session by running
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeSessionCookies(null);
So I'm sure the session cookie is there, but I'm unable to get/manipulate it.
I use the following code to setup cookies
PersistentCookieJar cookieJar = new PersistentCookieJar(
new SetCookieCache(), new SharedPrefsCookiePersistor(context));
clientBuilder.cookieJar(cookieJar);
Retrofit retrofit = builder.client(
clientBuilder.build()).build();
This is the header I received from server:
Set-Cookie: wordpress_logged_in_6041590398a33ab947560d559f09d479=capad%7C1488467742%7CSttfNHrOkwd67CteCGepJyv3bNU2SeSW0URepOPxCe5%7C5091b3bbcc334e520cec85c4c9b8e26a07a962d3c00c8c709b87f90018370f60; path=/; secure; httponly
Your cookie (Set-Cookie: wordpress_logged_in_[etc]; path=/; secure; httponly) has no expiration set.
This makes it a "session" cookie, which should not be persisted. Your PersistentCookieJar likely follows the correct spec in not persisting any cookies without an expiration.
You can either manually add on an expiration when you receive this cookie (perhaps with an OkHttp interceptor), or create your own version of the PersistentCookieJar that persists all cookies (this is probably not a good idea).
Another option would be to respect the fact that whoever is sending that cookie wants it to be a session cookie.
Background:
I am experiencing a very confusing behaviour with android Webviews in API 21 and up when testing in real devices.
I have a local HTML5 application (inside assets folder) with the following functionality
Login (2 steps authentication).
Show a list of items depending on the authentication.
The problem:
After doing the login requests, the server returns a cookie with the session. This cookie is not stored in the Webview when using real devices with API 21 or up. If I use emulators (Genymotion in this case), the cookies are properly stored.
More information:
The request to do the auth has the following headers:
POST http://myServer/j_spring_security_check HTTP/1.1
Proxy-Connection: keep-alive
Content-Length: 101
access-control-allow-origin: *
accept: application/json
access-control-allow-credentials: true
User-Agent: Framework/1.5.0 (Linux; U; Android 6.0.1; Nexus 5X Build/MMB29Q) App/0.1.1
Origin: file://
content-type: application/x-www-form-urlencoded
Accept-Language: en-US
X-Requested-With: app.package
Host: myServer
With the following response:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=4D169E8656DBEDFFA4D17FE8D436A5BA; Expires=Fri, 19-Feb-2016 14:27:55 GMT; Path=/; HttpOnly
Content-Type: application/json;charset=UTF-8
Content-Length: 43
Date: Fri, 19 Feb 2016 14:17:55 GMT
The cookie is not stored in devices with API 21 or more. Same request/response works fine in the rest of devices + all the emulators
Clarification:
This flags are enabled inside the app:
android.webkit.CookieManager.setAcceptFileSchemeCookies(true);
(Before CookieManager or webview is instantiated, as documentation says)
if(VERSION.SDK_INT >= 21) {
CookieManager.getInstance().setAcceptThirdPartyCookies(this.nativeWebView, true);
}
If after doing the authentication, I access the cookies datastore and
check the "hasCookies" method, I get false.
The two step auth service actually calls 3 different paths from the same endpoints. None of the cookies that the response that generate this services are stored. I don't know if this is relevant or not.
When doing simple authentication (to a different server), cookies are stored properly in all the devices emulators.
I am using Angular 1.5
I am aware that the service is using http instead of https. That will be solved in the future.
I get no error message in the consoles.
Questions:
Is there any internal security measure in the webviews that blocks the storage of the cookies? Why does it work on emulators (that are rooted devices) and not in real devices? This really bugs me.
If the network request is done using window.fetch you may need to add:
fetch('/something', { credentials: 'same-origin' }) // or 'include'
On chromium, window.fetch has the credentials flag set by default to 'omit' and no cookies are stored into the cookie storage. More details of this bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=477523
I have an app engine server that uses webapp2 extras auth mechanism. I have both an Android and an iOS client, and of course the mechanism uses cookies in order to keep the session going.
The problem is, that the when the Android client tries to make a request after logging in - even if it sends the a request with the cookie - the cookie is ignored and the session is not recovered. When I use the iOS client - the session is verified successfully.
This is very bizarre and I can't put my finger on why this happens.
I debugged the session for both cases, and here they are:
iOS session:
Accept: */*
Accept-Language: en-us
Content_Length: 0
Content_Type: application/x-www-form-urlencoded;charset=UTF-8
Cookie: auth="eyJfdXNlciI6WzQ2Nzg2OTY4NTQwOTM4MjQsMSwiV3FmUnFWUmxUME91TllsYnZsMWFxOSIsMTQyMzM1MzI3MCwxNDIzMzUzMjcwLCJMaW9yIFphdGxhdmkiXX0\075|1423353270|c2c7343dbb701f188c18f8b16c0fe06b794ad2d2"
Host: localhost:8081
User-Agent: PeersCards/1.0 CFNetwork/711.1.12 Darwin/14.0.0
X-Appengine-Country: ZZ
INFO 2015-02-08 17:38:55,123 user_api.py:591] Session was recovered
Android session:
Content_Length: 0
Content_Type: application/x-www-form-urlencoded;charset=UTF-8
Cookie: auth=eyJfdXNlciI6WzQ2Nzg2OTY4NTQwOTM4MjQsMSwiZDBCam5Sc1lucElRTjMySWxKQ0NzZyIsMTQyMzQxOTI1MSwxNDIzNDE5MjUxLCJMaW9yIFphdGxhdmkiXX0\075|1423419251|68063593b0262fdb5c6b479457c95eb9fcc7047f
Host: 10.0.0.16:8081
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-N900 Build/KOT49H)
X-Appengine-Country: ZZ
INFO 2015-02-08 18:16:11,215 user_api.py:594] Session is not saved
Any ideas?
I've figured this out.
Apparently, the Android CookieManager was storing the cookie as:
auth=XXXXXX
And AppEngine was expecting:
auth="XXXXX…"
It can also be seen in the input I've placed in the question, though I seriously didn't think that would be the issue.
I've set the "" manually into the cookie in the Android code, and that worked out the problem.