Authentication broken on ASP.Net Core and Safari on iOS 12 / Mojave

UPDATE December 14th: after some reports (thanks @johann!) we discovered that preventing response_mode=form_post wasn’t enough to prevent the issue. See Authentication broken on ASP.Net Core and Safari on iOS 12 / Mojave (take 2) for a different workaround.

This thread will be unlisted now.


A recent change in Webkit has broken authentication in ASP.Net’s Core 2 MVC apps that use the OpenIdConnect and Cookies middleware (like in all of our quickstarts and samples). In particular:

  • The OpenIdConnect middleware by default requests a response_mode=form_post (i.e. the OIDC identity provider will return the response by generating a POST from the browser to the client app).
  • The Cookies middleware uses a samesite=lax policy for the session cookie (which is a good thing, security-wise).
  • WebKit interpretation of spec causes it to block the ASP.Net session cookie set by the middleware right after the callback processing (/signin-auth0).

The flow is:

  1. Visit site, access some protected resource (or trigger the login manually).
  2. The authentication challenge at /Account/Login redirects to Auth0.
  3. User completes all the authentication prompts.
  4. Auth0 sends back the result to the app by returning HTML to the browser that does a POST request.
  5. The OpenIdConnect middleware (at /signin-auth0) validates the response, sets the identity cookie with a samesite=lax policy.
  6. The middleware redirects to the protected resource (or to the home page).
  7. The middleware checks for the identity cookie, which is blocked by WebKit. Since it’s missing, return to step 2.

Note that this problem is not exclusive to Auth0, and will most likely affect any OIDC identity provider that supports response_mode=form_post (part of the OIDC specification).

The workaround until WebKit fixes this behavior is to instruct the OpenIdConnect middleware not to use response_mode=form_post and instead use the OIDC default response mode (and use the authorization code flow instead of the default hybrid flow). To do so:

.AddOpenIdConnect("Auth0", options => {
    // Other configuration options
    [...]
    // Set response type to code and response type to query
    // to avoid the default response_mode=form_post
    // which causes issues with Safari's handling of 
    // the Cookie middleware's default samesite=lax policy
    options.ResponseType = "code";
    options.ResponseMode = "query";
}
3 Likes

This really should be fixed in all examples: GitHub - auth0-samples/auth0-aspnetcore-mvc-samples: Auth0 Integration Samples for ASP.NET Core MVC Web Applications

Agreed. This was on my to-do list, but I just added this to the repo’s issue to better keep track of it. Document and provide workaround for WebKit issues · Issue #45 · auth0-samples/auth0-aspnetcore-mvc-samples · GitHub

1 Like

Using this workaround makes login and SignUp possible but leads to a redirect loop. I am really disappointed by your support. How can you leave a bug like this unfixed in your example implementation?

Using this workaround makes login and SignUp possible but leads to a redirect loop.

Do you mean that configuring the OpenID Connect middleware as shown above still causes a redirect loop? If so, can you provide a sample .HAR file that shows the loop?

I haven’t been able to make the samples fail by using this workaround, so I would be greatly interested in more details on how to reproduce.

I am really disappointed by your support. How can you leave a bug like this unfixed in your example implementation?

This bug was introduced by WebKit in the latest release and affected every implementation of ASP.Net Core OIDC talking to an OIDC provider (not just Auth0). This issue is still being discussed in the WebKit forums (188165 – iOS 12 Safari breaks ASP.NET Core 2.1 OIDC authentication) and it’s not clear yet if this is something that’s going to be fixed in WebKit.
We didn’t port this workaround to the samples yet for two reasons:

  • If we implement this change in all samples, we’d be penalizing every customer that doesn’t need Safari support, because this configuration change adds an extra HTTP request.
  • We haven’t received feedback from customers to confirm that this works for everyone, outside of testing environments.

Once again, if you can provide a .HAR file, or reproduction steps to cause the loop you mention, it would be great.

Thanks,
Nico

1 Like

Yes, here you go: scrapify.eu.auth0.com.har - Google Drive

Here is my Startup.cs ConfigureServices Code: // Get the client secret used for signing the tokens va - Pastebin.com

If you wan’t I can also send you a private link where you can test it yourself.

Thanks for helping,

Johann

Thanks for that @johann.
I just tried the app, and the OIDC middleware is still sending response_mode=form_post, which is what this configuration is supposed to prevent:

options.ResponseType = "code";
options.ResponseMode = "query";

You Startup.cs looks fine. Are you targetting netcoreapp2.1? What version are you using?

1 Like

Using dotnet version 2.1.302

Hi again @johann. I’m having a hard time reproducing the issue. I copied the ConfigureServices method verbatim, only added the MVC services:

services.AddMvc()
  .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

I also installed and configure the exact version of the SDK that you are using, and still can’t get it to do what it does on your running website.

Basically, when redirecting to /authorize, your website is sending a response_mode=form_post in the query string, and this configuration should make this disappear.

Any chance that after adding options.ResponseMode = "query"; you didn’t re-deploy the app?

This is what I’m getting in the /authorize redirection when inspecting it with the Chrome dev tools:

In your app, response_mode=form_post is also being added…

Thanks for doing all this effort. No I definitely redeployed but I didn’t set the Mvc compatibility version. Will try this tomorrow and let you know

@nicolas_sabena I added the MVC compatibility Version and updated some packages but the redirect loop issue still remains: https://i.imgur.com/LpaVooa.png

Here is my .csproj file: my .csproj file - Pastebin.com

Thanks,
Johann

Yes, I didn’t expect the services.AddMvc() bit to change anything, I just was commenting on my test procedure.

In any case, I tried using your .csproj references as well (as I was using the simpler Microsoft.AspNetCore.App reference before) but, again, no luck reproducing. I still don’t get the response_mode=form_post in the /authorize request, which is the ultimate test (I’m mentioning this in case it’s easier for you to check this in Chrome than trying the whole loop reproduction in Safari).

Would it be possible for you to upload a barebones repro project that I can run on my side? Remove any proprietary views/controllers/package references and leave only the minimum stuff to reproduce this and I’ll happily take a look. I’m interested in getting to the bottom of this.

@nicolas_sabena This bug is not our priority right now but I will try to provide a repo which reproduces the bug in 1-2 days.

1 Like

After some back and forth and additional testing, we found out that entering credentials or other POSTs in the authentication flow (like signing up) also triggered the issue. This workaround is thus not foolproof and thus no longer recommended.

See Authentication broken on ASP.Net Core and Safari on iOS 12 / Mojave (take 2) for an updated workaround.

I am also facing some error on my iOS. This is really annoying for all the iOS user. I am facing iTunes error 9. Is there any solution to fix it?

Hey there!

Sorry for such huge delay in response! We’re doing our best in providing you with best developer support experience out there, but sometimes our bandwidth is not enough comparing to the number of incoming questions.

Wanted to reach out to know if you still require further assistance?