6

I have a .Net Core WebAPI service for which I have enabled CORS (with the code below), in the properties of the project I have disabled anonymous authentication and enabled Windows authentication. The POST and PUT endpoints work with anonymous auth enabled but fail when its disabled. I get

OPTIONS http://localhost:64113/api/ 401 (Unauthorized)

Code to enable CORS

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

Angular code

    public XXX(data: any): Observable<Response> {
    return this.http.put(this.baseUrl, data,
        { withCredentials: true });
}

Has anyone got any experience of this?

Thanks

2 Answers2

6

I had the same problem. Finally got solution that worked for me. So you could try follow this pattern:

  1. Enable CORS middleware(which you've already done) by doing this:

    services.AddCors(options ={
      ...
      //describe your options here
      ...    
    });
    
  2. Enable Windows Authentication & Anonymous Authentication for IIS/IIS Express(depends what you use).

  3. Add web.config to your project's root folder with forwardWindowsAuthToken="true" flag. In my example it looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <system.webServer>
       <handlers>
         <remove name="aspNetCore"/>
         <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
       </handlers>
       <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true"/>
      </system.webServer>
    </configuration>  
    
  4. Apply [Authorize] attribute to your controllers/actions. And that's it. Now you're able to send POST & PUT requests as well as get user's identity simply by accessing User.Identity.Name property
Simon Hänisch
  • 4,740
  • 2
  • 30
  • 42
Eugene S.
  • 83
  • 1
  • 8
0

For those using .NET Core 3.1 and above, 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