Configure browser cache in SFSafariViewController using Swift iOS - 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.

Related

Google Oauth2 Consent Screen "Allow" button disabled for DELPHI app

Can someone please help me why the button "Allow" in the screen below is disabled? WE are using a Delphi application in order to have user single sign on with google using the TWebBrowser built in delphi to start the process. Here is what our payload looks like: (Is there a way to bypass this check? maybe send other parameters to the url request? or other ideas how can we authenticate google using the client_id..etc. )
We have been reading similar posts in Stackoverflow, but no solutions.
Thanks
https://accounts.google.com/o/oauth2/auth?
client_id=1000217514248-pqeu5oqj3easr************************&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob
&response_type=code&
state=995F6663-D8FE-4***************&
scope=openid+email
&code_challenge=0C336C62-1B4E-49F7-*************&
login_hint=test%40test.be
&hd=test.be&
as=S-737348098%3A1615472*****6&flowName=GeneralOAuthFlow
You need to make sure that you are opening the browser window on the users installed browser.
You cant open the consent screen from any type of embeded browser or iframe . You need to open a new window in the users installed browser
I had that same problem before. Google is detecting an old and insecure browser and will not allow the authorization to proceed.
I ended up creating a TCustomAuthenticator descendent class for this. This should work on older versions of Delphi.
It implements a OAuth2 Authenticator:
Allows authorization via externel browser
Uses PKCE flow for added security
Generates new tokens when they expire (using the refresh token)
In the repository there's a Demo app too.
Feel free to use it if you like:
https://github.com/imperyal/delphi-google-oauth2
We stopped using embedded browsers...we used the common Google services in order to have the pop up from default browser in order to login. The current DELPHI version uses Internet Explorer 11 as internal browser, i believe that New versions of delphi have Edge as internal browser which this will not have the disabled button on.

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

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


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

Limitations on SFAuthenticationSession

Apple's documentation for the SFAuthenticationSession say it allows sharing a login "along with cookies and website data". My question is whether there is any limitation to the cookies, and what the 'data' entails exactly.
I have seen a case where cookies set in one instance of SFAuthenticationSession do not appear to be present (or available) in another instance. Do only certain cookies get passed this way?
(If anyone knows of any tools to check the exact cookies present in a SFAuthenticationSession instance, please let me know. I tried Web Inspector but it just says "No Inspectable Applications". I am able to get Web Inspector to work with Safari. Note I don't think that Javascript will work since I want to see cookies for all domains.)

Enable session cookies for iframe in page in WkWebView / mobile Safari

I have a website that is iframed into a 3rd party webpage, which is itself embedded in a WkWebView in an iOS app. Mobile Safari and the WkWebView reject the session (http-only) cookies being sent for my website, breaking basically everything. The work-around in mobile Safari is to either enable all cookies in settings (yuck) or instruct users to visit my site directly (so it counts as a "site I visited", as far as Safari is concerned); neither of these is particularly palatable. I have found no work-arounds for the WkWebView.
This question is two-part:
1) I am thinking of implementing a redirect service in my website, that takes a destination URL as a parameter, and simply redirects the user to that URL on page load. The 3rd party site can then link to my redirect page with the URL set to send users right back, with the hope that this will count as "visiting" my domain, enabling cookies to be loaded.
Alternatively, the 3rd party site could open a new tab to my site, that closes immediately on load. I expect that this would be a less optimal user experience, however, and so would prefer not to go this route.
Best of all would be for the "POST to a hidden iframe" trick (3rd party page POSTs to my domain in a hidden iframe), but as SO questions indicate that trick no longer works.
Are either of these viable solutions, or has Apple blocked these methods of getting the session cookies set as well? Is there a better solution that I have not considered?
2) Is there a way to set the cookie acceptance policy with WkWebViews like could be done with UiWebViews? My searches of StackOverflow suggest not, but the answers I read could be based on older versions of iOS (the app requires iOS 9+).
If there is no app-code solution for WkWebViews, would the solutions for mobile Safari also work with WkWebViews?
I just had a similar issue. I have a WkWebView which loads my web app that has an iframe loading a login screen from a specific server. The login page would complain that the iframe did not allow cookies.
When I would load the login page directly in the web view, it would work and it would also curiously start working as well when I tested it afterwards again inside the iframe.
The best explanation I found for this is, cookies are only allowed to be saved in the iframe if the web view has directly loaded the domain of the iframe at least once. Knowing this, I was able to implement a workaround.
By simply pinging the login page once with the webview, I use the WKNavigationDelegate to wait until I start receiving some data from the server. Once this happens, I make the web view load my page that contains the iframe. Now the iframe is able to consistently load the login screen.

Resources