Beware of SameSite cookie policy in ASP.NET Core and upcoming iOS 12
I have recently stumbled across a bug in iOS 12 preview which sort of breaks existing sites which make use of OpenID Connect middleware in ASP.NET Core 2.1.
As iOS is coming closer to release, I decided to install it on my iPad for testing. After trying to access some our company's internal sites I always ended up in a redirect loop - basically AAD > site > AAD > site etc. - unending.
After doing some research and borrowing my friend's MacBook for debugging the browser in iOS - I noticed that the browser was not persisting cookies from our site. After going a bit further, I also tried other sites - Microsoft's https://admin.teams.microsoft.com for example which ended up with the same issue.
After that, I have done some research with the cookie configuration and the result has surfaced - the SameSite policy in Cookie Authentication middleware! The default configuration of Cookie Authentication's cookie is setting it to lax which means that the browser will not accept cookies from the site if it was redirected by POST request to it.
SameSite policy is another measure at the browser's level to fight CSRF attacks. So now since we have the root cause, what can we do about it?
In order for your ASP.NET Core 2.1 application to work with iOS 12, you need to configure CookiePolicyOptions along with the Cookie.SameSite policy as well:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options))
.AddCookie(options => options.Cookie.SameSite = SameSiteMode.None);
// ...
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.None
});
After that, your site is going to work again on iOS 12 again. I went to make some research and found out that other major browsers implement the SameSite cookie policy as well, however I couldn't reproduce the same issue there. Which made me wonder whether they are doing some sort of magic there or something is broken in iOS 12 so I went ahead and submitted a bug report to WebKit. After couple of hours of waiting, Apple engineers reachead out and I provided them with credentials to reproduce the issue.
So far, I haven't heard back from them yet, however this issue is still present in iOS 12 Developer Preview 11 as of now. I am going to update this post if new info becomes available.
Update 28SEP2018:
You can alternatively set the response mode to send the response in the query instead of the post body like so:
.AddOpenIdConnect("AzureAD", options => {
...
// Set response type to code and response type to query
// to avoid the default response_mode=form_post
// which causes issues with WebKit's handling of samesite=lax for the session cookie
options.ResponseType = OpenIdConnectResponseType.Code;
options.ResponseMode = OpenIdConnectResponseMode.Query;
};
Just beware that with this solution you won't receive the user's id_token directly and if you are using ADAL to redeem the authorization code for tokens, you might run into issues.