2

I'm working on a single-page web application. It has ASP.NET Core 3 back end and Angular 9 front end. I run the back end in Visual Studio, on IIS Express, at http://localhost:59280. The front end runs in Visual Studio Code, using ng serve, at http://localhost:4200. Previously I didn't need to turn on CORS in the back-end, because I only tested the app in Chrome, and adding the --disable-web-security command-line argument was enough to turn off the Same Origin Policy. On the live server there is no need for CORS, the above cross-origin situation only occurs on my dev machine.

Now I'd like to debug the frontend in Firefox, but since it's not possible to turn off the Same Origin Policy for Firefox, I have to turn on CORS in the back end. Unfortunately, it doesn't work, because I use Windows Authentication, and it stops the by-default unauthenticated CORS preflight request. This could be solved if I could let HTTP OPTIONS requests be processed without Windows Authentication. I thought this could be done by adding something like this to web.config:

<system.webServer>
  <security>
    <authentication>
      <anonymousAuthentication enabled="true" />
    </authentication>
    <authorization>
      <add accessType="Allow" verbs="OPTIONS" users="*" />
    </authorization>
  </security>
</system.webServer>

...but I got an error message: "This configuration section cannot be used at this path. This happens when the section is locked at a parent level." Apparently web.config is in conflict with launchSettings.json, which seems to control authentication when the back end is run on IIS Express in Visual Studio, using these two lines:

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    ...

I don't know how I could turn off Windows Authentication separately for HTTP OPTIONS requests, using only launchSettings.json.

Is there a way to turn off Windows Authentication separately for HTTP OPTIONS requests, in an ASP.NET Core 3 application?

kol
  • 27,881
  • 12
  • 83
  • 120
  • 1
    You could try to put app.UserCors before app.UseAuthentication and also add a middleware that returns immediately in case of options: https://stackoverflow.com/a/31754050/1882699 – Martin Staufcik Apr 28 '20 at 08:45
  • UserCors is at the right place. I tried the middleware idea, and now the OPTIONS request returns 200 OK, not 401 Unauthorized. But this didn't help, because the POST is not sent after the OPTIONS... – kol Apr 28 '20 at 09:08
  • Hmm... If I return 204 No Content and the headers listed in the above MDN page (Access-Control-Allow-Methods: POST etc.) then the POST is sent, but gets 401 Unauthorized. At least this was real progress, thanks! – kol Apr 28 '20 at 09:28
  • Does this answer your question? [How to authorize CORS preflight request on IIS with Windows Authentication](https://stackoverflow.com/questions/49450854/how-to-authorize-cors-preflight-request-on-iis-with-windows-authentication) – Lex Li Mar 19 '21 at 15:35

1 Answers1

5

1) The above web.config settings work, I only had to unlock the "anonymousAuthentication" section in applicationhost.config in the .vs directory: <section name="anonymousAuthentication" overrideModeDefault="Allow" />. The value of the "anonymousAuthentication" parameter in launchSettings.json doesn't matter.

2) Following @MartinStaufcik's suggestion, I added a middleware at the beginning of StartUp.Configure(), which responds to the preflight request (MDN):

app.Use(async (context, next) => {
  if (context.Request.Method == "OPTIONS") {
    context.Response.StatusCode = 204;
    context.Response.Headers.Add("Access-Control-Allow-Origin", context.Request.Headers["Origin"]);
    context.Response.Headers.Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
    return;
  }
  await next();
});

3) I also had to add { withCredentials: true } to the arguments of HttpClient.post() in the Angular 9 front end. Without this, the OPTIONS request got 204, but the subsequent POST got 401.

kol
  • 27,881
  • 12
  • 83
  • 120