WKWebview not syncronizing cookies after I log out of a domain, opened on it - ios


I am developing a WKWebview app in swift. Here One needs to login to a specific domain. For this , I am throwing a cookie with logged in information/token.
But the problem occurs when I try to logout and the check if token exists?
And the token still exists even after logout.
Note - I checked on chrome browser on mac, and here it works perfectly.

WKWebView runs all of its networking in a separate process and thus does not ‘see’ your process’s cookie store.
The problem is that the WKWebView does not write back the cookies immediately. I think it does this on its own schedule. For example when a WKWebView is closed or maybe periodically.
In iOS 11 we added WKHTTPCookieStore to give you full access to the web view’s cookie store.
Supported cookie sync with WKWebView on older platforms is tricky. There are two techniques that might work:
You can set a cookie in the headers of the request you pass to
[WKWebView loadRequest:].
You can get and set cookies from within the web view by running
JavaScript code (using -evaluateJavaScript:completionHandler:) that
accesses the JavaScript document.cookie value.
For more reference https://forums.developer.apple.com/thread/95301 additionally some workaround Getting all cookies from WKWebView

Related

Can I get cookies from Safari in a SFSafariViewController?

tl;dr; see the question below
In my app, I have a login that uses SFSafariViewController and ASWebAuthenticationSession that follows the OAuth 2.0 flow (Using the AppAuth library).
The login works and the cookies are shared with Safari as expected. Thanks to the cookie sharing, users are automatically logged-in if they use the Safari app.
However, back in the app, if I launch a SFSafariViewController again, the cookies are missing. This surprises me, because I thought the cookie Store is the same for SFSafariViewController and Safari, and it clearly worked in the direction from SFSafariVC to the Safari app during login.
Is it intended not to work the other way round - from Safari to SFSafariViewController, or is it a bug?
I have not found clear statements in the documentation.
Of course I have not set ephemeral session to true, but according to the documentation it would do the opposite of what I want to achieve:
When not using an ephemeral session, all cookies except session cookies are available to the browser.
I've also found somehow related radars like http://www.openradar.me/33323462 and http://www.openradar.me/radar?id=5036182937272320 or this stackoverflow post: Why is SFSafariWebViewController not sharing cookies with Safari properly? but they do not answer my question.
According to this comment it could work if the cookies have an expiry date (set to a future date). I verified the cookies - they all have a future expiry date.
My question: Am I doing something wrong, or is this expected behaviour, that SFSafariViewController does not get cookies from an earlier SFSafariViewController instance in the same app or from Safari?
REQUIREMENTS
So it seems you want a solution to invoke secured web content from a mobile app, and to avoid an extra login. It is a common requirement and I will be adding some stuff to my blog on this topic over the next month or so.
STATE OF THE INDUSTRY
The problem with the above is that third party cookies, such as those issued by Identity Providers, are often dropped by default these days due to browser security initiatives such as Intelligent Tracking Prevention changes - which is ON by default in Safari:
COOKIE PROPERTIES
Worth checking that your cookies are issued with SameSite=None, which will give you the best options for a third party cookie based solution.
MOBILE FIRST DESIGNS
In an OAuth world, in order to meet the requirements, it is likely to be necessary to send a token from the mobile UI to the web UI, which of course has prerequisites that need to be designed for:
Web UI must use tokens
Web UI must use different strategies for token handling depending on the host
OPTION 1
One option is to use a mobile web view to show the web content - see my code below:
Web UI Code to ask the host for tokens
Mobile UI Code to service these requests
OPTION 2
Another option is to send something representing the token in a query string parameter from the mobile app to the Web UI, in which case you need to ensure that:
No usable tokens are recorded in web server logs
The token has a one time use only
A typical implementation would look like this:
Mobile UI calls an /api/token/encrypt endpoint
API stores a token hash in a database and returns an encrypted value with a short time to live
Token is sent from the Mobile App to the Web UI
Web UI calls an /api/token/decrypt endpoint to get the real token
The API's decrypt implementation deletes the database entry

Configure browser cache in SFSafariViewController using Swift iOS

In my application I am implementing a feature where for some part I need to open my website using SFSafariViewController. For this I don't want the user to login again in the web application as well, so before I open the SFSafariViewController I want to pass some token, mail and other required information. So is this feasible and would allow me to use browser cache.
SFSafariViewController is very limited in what you can configure, as seen by the documentation: https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller. Apple intentionally keeps cookies and safari configuration separate from apps that are using it for security and privacy reasons.
I don't know if this is exactly what you're seeing, but I faced a similar issue where, if a user logged in via SFSafariViewControler, then logged out (not using SFSafariViewController), then logged in again, it wouldn't ask for a login/pass because it was still cached in the browser.
Pretty much the only 2 options for this are:
Have the logout flow take place within SFSafariViewController so that you can clear the cookies that way.
Apple has a new auth flow class ASWebAuthenticationSession (docs here) which has a new property you can set called prefersEphemeralWebBrowserSession which essentially opens the browser in private mode. This keeps any cookies from being stored in the browser. The only downside to this, is the prefersEphemeralWebBrowserSession property is only available in iOS 13+.
If this is the same issue you're facing and you can limit your app to iOS 13+, then I would suggest the ASWebAuthenticationSession route, otherwise you may need to find another solution.

Chrome and Safari on iOS 12.4 doesn't set cookies timeously

In a web page I set a cookie when the page loads then check a condition and immediately redirect to a second page on the same site where I read the cookie. The cookie is not set when I arrive at the second page. The above functionality works on desktop browsers and it worked in iOS 12.3.1 without any changes to the site. After upgrade to 12.4 it stopped working, but still worked on a 12.3.1 device.
Any thoughts?
This is not a comprehensive answer since there are missing pieces in the question.
#1, the issue often appears when the user serves a page from a local file.
Ex: file:///C:/project/index.html.
Cookies require a web server to be running to be set. Meaning at the very least you need to serve it from http://localhost/index.html.
#2, You are setting the path in the cookie. Meaning the cookie is limited to only one path.
// Example:
document.cookie = "key=value; expires=; path=/my/path/"
Here the cookie will only be valid in the declared url path.

Ionic/Angular Cookie issue on iOS

I am using .Net core for backend, and authenticating users using cookies. My ionic application is working perfectly fine on android, where cookies are returned on login and are set automatically and being used for every request.
Trying it out on iOS, the cookies work fine as long as the app has not been closed (meaning both cookies sent from the server are being returned with every request).
If the app is closed and then restarted, I notice only one cookie being sent with the requests. This behavior is very weird since one cookie is being saved and is persistent throughout app restarts, in opposition to the other cookie that is no longer available after the restart. Does anyone have the slightest idea of what might be causing this?
Again, the same code was used for both platforms, and no manual handling for the cookies is being done.

iOS sporadically sends old cookies

I have an application that rotates an auth token cookie values regularly.
Each time the server rotates the token, it will not mark it as "good" until it sees the client has the token (cause the client includes it in the request headers for a resource).
I have a very specific situation ONLY on iOS (10.3) where sporadically it will send a very old cookie when network conditions change (eg: get off the subway). When this condition hits it "forgets" about the most recent cookie value and "starts living in the past" and sends and old value.
** Security note: IP addresses are publicly allocated t-mobile in NYC and token has long been deleted from our DB
Is this a known issue?
Are there any workarounds for cookie handling that is more robust on iOS? localstorage is not ideal cause these cookies are http only.
To clarify ... this is the flow:
Client (iOS Safari) has a cookie called _t with the value old
Client (iOS Safari) makes a request to the server
We issue Set-Cookie and set _t cookie to a new value new (http only, secure cookie)
Client makes another request with the new cookie value new. We flag that the cookie value is good and client has it.
Time passes
Client makes a request with the _t cookie with the value old
Here is my theory of what happened:
From the cookies lifecycle, whenever user authentication state change (login user -> logout user || logout user -> login user), the old cookie would be invalidated and replaced with a new cookie.
But why that happened in the subway and not other places?
1. These days most subways provide free unsecured WiFi to supplement the bad wireless network connectivity while underground.
2. There were some reports on network connectivity issue in 10.3, and
this one in particular is interesting, as the issue was location dependent.
3. I think the combination of (1) and (2) above was causing the app to reauthenticate to the server. Maybe you could pull the logs to check if that is indeed the case?
Possible workaround?
Maybe none. We can't prevent iPhone user from doing iOS upgrade. And most already did.
Also, the security repercussion of not changing cookies after reauthentication is worse.
Update based on the comment as of 05/31/2017:
Given the details as in the comment. We could have better explanation.
In cookie life cycle, when user logout, server-side-invalidation should take place.
The work flow:
1. When the user logout, the authenticated sessionID is deleted from the browser.
2. But that's not enough. The server needs to invalidate that sessionID too. Else there could be security repercussion.
3. It could be that in your case the server didn't invalidate. Thus it still expecting a SessionID which has been deleted from the browser.
This is just one possible explanation. To be exact, more details log file analysis and more experiment would be required.
For example, during that period, at the server log were there any reauthentication took place? Could we test in a controlled environment, if the server-side-invalidation has been implemented properly?
My experience
I also use authentication via IDs that change with each request and are stored in cookies.
I can confirm this behavior and it is still present in iOS 11 (and iOS 11.1 beta 3). In my log files, I can see that sometimes old cookies are randomly stored in Safari. This happens in a standalone webapp when it is closed and reopened.
My Fallback method
I built a fallback method over localStorage. A request with an old cookie will normally mark all data in my database as invalid. If the user agent points to a device with iOS, I do not mark the data as invalid and give the client a second attempt to authenticate itself.
On the client side I check the localStorage and create new cookies with this data. Subsequently, a new authentication takes place. The localStorage is rewritten like the cookies with each request. If authentication fails again, I mark the data as invalid.
Safari View Controller no longer shares cookies with Safari in iOS 11 and up, this change resolved the cookie store corruption issues that plagued iOS. We have not experienced this issue ever since iOS 11 was released.
Maybe that's caused by automatic retries?
Those posts mention that can happen under bad network conditions (like you said, subway):
https://medium.com/#fagnerbrack/the-day-a-bug-was-fixed-only-because-the-ceo-called-in-f653a34079eb
https://blogs.oracle.com/ravello/beware-http-requests-automatic-retries
SQLite database, if you're willing to sacrifice a little security.

Resources