19

In my asp.net core web api, I've configured Cors as per the article from MS documentation. The web api app is using windows authentication (Anonymous Authentication is Not enabled). Cor's policy is created and middle ware is added as below in the startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.WithOrigins("http://localhost:4200")
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
            );
    });

    services.AddMvc().AddJsonOptions(options => {
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{         
    //Enable CORS policy 
    app.UseCors("CorsPolicy");
    app.UseMvc();
}

Also applied the policy per controller level

[EnableCors("CorsPolicy"), Route("api/[controller]")]
public class LocationController : BaseController<Location>
{
  //code
}

Options request is getting Unauthorized. The request & response looks like

enter image description here

I have seen similar questions and tried almost every solution but the options request is still failing.

ekad
  • 14,436
  • 26
  • 44
  • 46
rumi
  • 3,293
  • 12
  • 68
  • 109
  • Not sure if this will help, but I ran into an issue allowing CORS requests to access and API I had built. I tried everything under the sun, but it turned out that OPTIONS requests were being denied by IIS. – phishfordead May 03 '18 at 15:11
  • Have you disabled anonymous authentication in IIS or iisSettings? – Kyle B May 04 '18 at 13:10
  • How are you configuring your authentication? – Rob May 11 '18 at 06:30
  • I'm configuring via web project property settings in visual studio – rumi May 11 '18 at 08:44
  • 1
    @KyleB I've disabled anonymous authentication in web project settings via visual studio – rumi May 11 '18 at 08:46

7 Answers7

10

You may want to read this thread: https://github.com/aspnet/CORS/issues/60. You can mix anonymous and NTLM so that your CORS preflights aren't denied (since they don't include windows credentials). IIS handles NTLM authentication before it even gets to the middleware so this is probably an IIS thing. You may need to allow anonymous CORs preflight checks.

Kyle B
  • 2,328
  • 1
  • 23
  • 39
  • 2
    Setting both `windowsAuthentication:true` and `anonymousauthentican:true` worked. –  May 22 '21 at 02:07
10

1) Set Allow Windows, and anonymous Authentication flag to true in launchSettings.json file (Development settings file).

Anonymous Authentication: is needed to allow Pre flight option request.

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iis": 
      ...
}

2) Add Cors Policy in Configure service method.

public void ConfigureServices(IServiceCollection services)
{
         
        ...
          services.AddCors(options =>
              {
                  options.AddPolicy("MyCustomCorsPolicyName",
                              builder => builder.WithOrigins("http://YourDomainName/")
                                      .AllowAnyMethod()
                                      .AllowAnyHeader()
                                      .AllowCredentials()
                              );
              });
          services.AddAuthentication(IISDefaults.AuthenticationScheme);
          services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);      
}
   

3: Adds a CORS middleware to your web application pipeline to allow cross domain requests.

public void Configure(IApplicationBuilder app)
{
   ....
   app.UseCors("MyCustomCorsPolicyName");
   app.UseMvc();
}

4) Add Authorize Attribute on top of your controller to Force, client to send credentials

[Authorize]
public class MyAPIController : ControllerBase
{
...
}

5) In JQuery or any client that you are using set withCredentials property flag to true

$.ajax({
                type: "POST",
                datatype: "json",  
                url: "YourApiUrl",              
                xhrFields: {
                    withCredentials: true
                }

This worked for me in my development environment using .net core 2.2, IIS Express with Windows Authentication.

Niraj Patel
  • 111
  • 1
  • 6
  • "Anonymous Authentication: is needed to allow Pre flight option request." This was the key that solved this for me, after hours of struggling. A small but important fact that is not mentioned in the docs, which I followed to the letter and it still would not work. – M-Peror Apr 20 '22 at 13:07
1

Using IIS CORS Module solved the problem superbly. Below URL is for reference.

Working with Windows Authentication While this is by no means the only scenario solved by the CORS module, it was important enough to warrant calling out. Previously, if you tried to make a cross-domain request to an application that used Windows Authentication, your preflight request would fail since the browser did not send credentials with the preflight request. There was no way to work around this without enabling anonymous authentication in your application. Since the CORS module kicks in before authentication, it makes it possible to handle a pre-flight request without compromising on the security model of your application. Here's an example of what your web.config might look like.

https://blogs.iis.net/iisteam/getting-started-with-the-iis-cors-module

Sample Code:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- To customize the asp.net core module uncomment and edit the following section. 
         For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
         <system.web>
        <authentication mode="Windows"/>
    </system.web>
  <system.webServer>
  <cors enabled="true" failUnlistedOrigins="true">
            <add origin="http://localhost:60096" allowCredentials="true" >
            <allowHeaders allowAllRequestedHeaders="true">
                    <add header="Header1" />
                </allowHeaders>
            </add>
        </cors>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\Project.Api.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>
AJP
  • 31
  • 4
0

This is very similar to CORS enabled but response for preflight has invalid HTTP status code 404 when POSTing JSON and provided solution working for me(I had 401 error on POST requests). Also NTLM and Negotiate should not be configured both(Negotiate V/s NTLM).

0

It looks like you want pass credential or along with request.

Please Check this link for add credential / allow user credential.

Be careful when allowing cross-origin credentials. A website at another domain can send a logged-in user's credentials to the app on the user's behalf without the user's knowledge. The CORS specification also states that setting origins to "*" (all origins) is invalid if the Access-Control-Allow-Credentials header is present.

Asav Vora
  • 61
  • 6
0

After a couple hours figuring it out, here is a COMPLETE solution (front-end to back-end):

My problem: When I enabled the windows authentication on my web API, I could not do fetch calls from my react app to my .NET Core 3.1 web API, CORS was freaking out. With Anonymous authentication it worked, but not when windows authentication is enabled.

1.launchSettings.json

this will be used only for your dev environnment, make sure windows auth is also enabled in IIS on your prod server.

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": {
      "applicationUrl": "http://localhost:58747",
      "sslPort": 0
    }
  },
 {... more settings if any}
}

2.Startup.cs:

CORS policy is enabled here. The order of methods is important here. Also, you don't need to set those in a web.config

public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", //give it the name you want
                           builder =>
                           {
                               builder.WithOrigins( "http://localhost:3000", //dev site
                                                    "production web site"
                                                   .AllowAnyHeader()
                                                   .AllowAnyMethod()
                                                   .AllowCredentials();
                           });
        });

        //database services here

        services.AddControllers();
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        // global policy same name as in the ConfigureServices()
        app.UseCors("CorsPolicy");

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

3.Controller(s):

using Microsoft.AspNetCore.Cors;
... your other usings

namespace ProjectTest.Controllers
{
    [ApiController]
    [EnableCors("CorsPolicy")] //THIS HERE needs to be the same name as set in your startup.cs
    [Route("[controller]")]
    public class FooController:Controller
    {
        [HttpGet("getTest")]
        public JsonResult GetTest()
        {
            return Json("bar");
        }
    }
}

4.React Component fetch call example:

The "credential: 'include'" is the secret

    await fetch('http://localhost:3000/Foo/getTest', {
        method: 'GET',
        credentials: 'include'
    }).then(resp => resp.json());
Homeslyce
  • 258
  • 3
  • 11
0

Just a note CORS middleware doesn't work in IIS see this thread here

  1. Install CORS module in IIS
  2. Transform your web.config (btw I'm using .net core 3.1)
  3. Add a web.release.config on the root of your app
  4. Follow this XML code
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

  <system.web xdt:Transform="Insert">
    <authentication mode="Windows"/>
  </system.web>

  <system.webServer xdt:Transform="Insert">
    <cors enabled="true" failUnlistedOrigins="true" >
      <add origin="your origin" allowCredentials="true" >
        <allowHeaders allowAllRequestedHeaders="true">
          <add header="your header" />
        </allowHeaders>
      </add>
    </cors>
  </system.webServer>

</configuration>
  1. Deploy your app in IIS
Markus Zeller
  • 8,516
  • 2
  • 29
  • 35