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:
Visit site, access some protected resource (or trigger the login manually).
The authentication challenge at /Account/Login redirects to Auth0.
User completes all the authentication prompts.
Auth0 sends back the result to the app by returning HTML to the browser that does a POST request.
The OpenIdConnect middleware (at /signin-auth0) validates the response, sets the identity cookie with a samesite=lax policy.
The middleware redirects to the protected resource (or to the home page).
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";
}
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 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:
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:
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.
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.
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?