Auth0 Home Blog Docs

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


#1

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";
}

#2

This really should be fixed in all examples: https://github.com/auth0-samples/auth0-aspnetcore-mvc-sample


#3

Agreed. This was on my to-do list, but I just added this to the repo’s issue to better keep track of it. https://github.com/auth0-samples/auth0-aspnetcore-mvc-samples/issues/45


#4

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?


#5

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 (https://bugs.webkit.org/show_bug.cgi?id=188165) 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


#6

Yes, here you go: https://drive.google.com/open?id=1ixV0cWUdR1kxdxGkY1bSGligBZcqHoCU

Here is my Startup.cs ConfigureServices Code: https://pastebin.com/pjYRMmR9

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

Thanks for helping,

Johann


#7

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?


#8

Using dotnet version 2.1.302


#9

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…


#10

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


#11

@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: https://pastebin.com/VmFBAj5u

Thanks,
Johann


#12

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.


#13

@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.