Cookies not being set on iOS using identityserver - ios

I have a mobile app that is using ODIC authorization code flow. Our server implementation is using Identity Server 4.
The mobile app opens a browser window and I can login to a 3rd party provider just fine, it then redirects to /signin-adfs on our identity server, which sets some idsrv.external cookies and returns a 302 to /External/Callback. The browser redirects to /External/Callback but doesn't send any of the idsrv.external cookies with it so Identity Server throws an exception because the result from HttpContext.AuthenticateAsync is not successful.
I'm kind of stuck at this point because I'm not a mobile developer. I deployed and have customized Identity Server slightly in other areas but not this part of the code.
I believe the mobile app is opening a Safari session to do the auth. Is this an issue with the cookies that the browser doesn't like (domain, path, https, secure)? or something else? The cookie size is chunked to 4KB a piece. I'm not sure what could be causing this issue.
To make things even weirder... if the browser is refreshed (/External/Callback) then the request works and the iOS app gets the code and can make the follow up request to get the token.

Was digging through the IS4 source and saw a link to this issue on github. Looks like it was fixed in source but hasn't been released yet. There are some workarounds in the github issue if you need it sooner than the release. The problem is specific to iOS 12.

Related

Azure AD authentication not working as expected for mobile devices

I have built an authentication system for Microsoft Teams tab -( angular application) using Authentication for tabs using Azure Active Directory - Teams and it is working fine on desktop (app and browser) but when I am trying to run on the mobile app and then press Authenticate(seen below in image) button it takes me to the sign-in popup after signing in it returns back to same authenticate page.
Now, when I try it a second time it lands me on the page where I want to but with missing data and also, not as responsive it should be.
The below screenshots taken from the iOS device will help further: I am on Version: 2.4.0
Desktop View:
Major Queries:
Is the Azure AD (https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/auth-tab-aad) authentication will not work for mobile devices?
If I switch to a Single sign-on(https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/auth-aad-sso) , are there any limitations to using it and also, will it support all the platforms ?
Is the Azure AD (https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/auth-tab-aad) authentication will not work for mobile devices?
It should work on mobile devices.
If I switch to a Single sign-on(https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/auth-aad-sso) , are there any limitations to using it and also, will it support all the platforms ?
Single sign-on doesn't solve anything because if it fails you have to fallback to the default auth flow.
Looks like this is an angular issue, not a Microsoft's auth issue.
The problem is interesting because in general it is working but from the second attempt.
I think it might be the issue with synchronization, when some part of the code is running outside of the Angular but is trying to do something with the variables in the Angular's zone.
I don't know how exactly microsoftTeams.getContext and microsoftTeams.authentication.authenticate work but they are async and if they use setInterval/setTimeout they definitely will work outside of your Angular app.
And if they set data into your angular variables you will have the issues like you described.
So that's what happens in my opinion:
You are clicking auth button, everything is fine you are redirected, authenticated and redirected back to your final page.
On that final page your app is trying to save your token into the local angular variable.
Code that is setting the token works outside the Angular and Angular doesn't see this change. So from the angular's perspective nothing has changed, you are still not authenticated.
Your app is redirecting you to your private page, Angular doesn't see token and redirects you back to the auth page.
<Here something happend, for example ChangeDetectorRef.detectChanges, or other sync things>.
You click auth again and you end up authenticated on your private page, but without the apiKey and UserID (which have the same issue as token)
So to fix this you need to notify angular manually by using ChangeDetectorRef.detectChanges or wrap your async code with the NgZone.run.

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

Safari cannot open the page because the address is invalid after successful uber oauth

I'm linking to the uber api authentication endpoints (/authorize and /token) via iOS and after a successful login, it returns "Safari cannot open the page because the address is invalid". I've narrowed this down to an iOS specific problem because the same react-native configuration works for Android.
I've tried a number of solutions.
Clear safari browsing history, web data, iPhone update, etc. Nothing has worked.
I believe URL Schemes under URL Types in info.plist has a pay here, but I'm struggling to wrap my head around what I need to put there.
Any thoughts?
Upon successful authentication, uber should return an access token for the user.

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

HTTP authentication in iOS 7 web apps doesn't respond

My organization had a web app that worked perfectly in iOS 6. You'd visit the website, the website would tell you to add the page to your homescreen, and boom, a nice HTML5 web app was added to the home screen.
Because we're processing sensitive data, the web app used HTTP authentication (via the native WebKit auth dialog) to authenticate user/passes. It worked without a hitch until iOS 7. Now when someone tries to summon the HTTP auth dialog, nothing happens. It's clearly trying to load something, as the spinner in the status bar appears, but no dialog ever pops up, essentially breaking the "app."
Has anyone else run into this? Is this something you'd consider to be a bug on Apple's end? Any workaround?
My company ran into this last fall, starting with iOS 6, and what we have been able to ascertain is that it is a genuine Apple Safari bug as part of its security "enhancements". No real explanation from them for rationale, but here is what we see in the debug and packet sniffers.
In normal operation, the Safari browser will request a page (or an object in the page) from the server on a GET. If that asset is protected with an Access Control List, in our case Apache Basic Auth, and it is the first request on that host in the session, the server will respond with a 401 HTTP response header indicating to the client (the browser) that it needs to request again, this time adding a basic auth header that has authorization credentials. The browser then presents a login dialog to the user, where they can enter user and pass credentials, and either submit or cancel the request. On submit, the client re-requests with those credentials in the auth header.
Assuming the credentials are accepted on the second GET request, the proper asset will be returned on the response, and the document in the browser will proceed with loading the rest of the page (assuming it was a page you requested). If you have embedded assets that reside on a different host, and that host requires authentication for that asset, the process is repeated as the page loads.
Here's where it gets broken. If you embed calls to objects from more than 2 hosts total on the same page, which require basic authentication, the 3rd authentication prompt on that page is suppressed, so the browser spins forever waiting for you to enter credentials on a prompt that you never see. Your Safari browser is now hung up on that stalled authentication prompt, on this and any other tab, even on a reload, and you will not get another prompt unless and until you hard-close your browser or restart your device.
This does not affect Chrome, just Safari, and it is both on an iPhone and an iPad with iOS 6 or later. I have the latest iOS version as of this writing (7.0.6), and the problem is still there.
We had a workaround last year, where we would create an internal page that had an array of each of the embedded hosts, which we would then loop through with an iframe embedding a call to the favicon.ico at that host's location. That worked until recently, where now, perhaps because of the iOS 7 feature of freezing background tabs, the auth prompts are frozen up again.
Here was the JavaScript sample:
hosts=["store","profile","www","secure-store","images","m","modules"];
devhost=location.hostname;
var i=0;
while (hosts[i])
{
newhost=devhost.replace('store.mydomain',hosts[i]+'.mydomain');
document.write("<iframe Xhidden seamless=seamless width=0 height=0 src=http://"+newhost+"/favicon.ico><img height='16' width='20' alt='NOT' title='NOT AUTHENTICATED' src=http://"+newhost+"/favicon.ico> Authenticated on "+newhost+"</a></br></iframe>");
document.write("<img height='16' width='20' alt='NOT' title='NOT AUTHENTICATED' src="+(newhost.indexOf('secure')>0?'https://':'http://')+newhost+"/favicon.ico> Authenticated on "+newhost+"</a></br>");
i++;
}
The second set in the document.write would give a visual indication of which hosts have been authenticated, as their favicon is now displayed. It also lets you know which host might be stalled, as its icon is missing.
Since this workaround stopped working on iOS 7, the only cumbersome solution we have is to pre-open a separate tab for each of the favicons (directly in the URL), enter the auth, go back, go to the next one in the list, and repeat until you have cached all of the auth credentials for all of the hosts used on the page. At that point, you can load the original page since your creds are now cached. Cruddy, and completely unreasonable for an end consumer, but is what we need to do for testing sites that are behind a public CDN, as we need to protect assets on that development site with an ACL.
As of today, we are still figuring out a better workaround. Not an issue on Android, Windows, or any other iOS.
Sure worked better when Jobs was alive.
Hope some of this helps.
I have the exact same problem. Basic authentication worked with previous iOS versions but not with iOS 7 in combination with web apps added to the home screen. I think this may be related to the dialog problem described here.
Standard dialogs are not working at all, such as alert, confirm or prompt.
The login prompt that is shown to authenticate the user is probably blocked (does not work or is not visible) and that is why the web app does not pass through the authentication phase.
I suppose Apple will have to fix this bug in a future release.
Edit: After upgrading to iOS 7.0.3 basic authentication suddenly started to work again also in home screen web app mode. Login prompt is displayed and everything works as expected.

Resources