C# .NET Web API CORS-Errors - c#

I've tried for days now and I can't get it to work.
I have a local web app and a local, separately running .NET 6.0 WebAPI which is supposed to accept post requests.
The web app which sends the fetch requests runs on localhost:3000
and the WebAPI runs on localhost:44379
My CORS-Policy is setup in the Program.cs file as follows:
appsettings.json:
"AllowedHosts": "*",
"cors": {
"rules": [
{
"origin": "*",
"allow": true
}
]
}
Program.cs:
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigin",
builder => builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowAnyOrigin()
);
});
And then I use them before running the app, I also made sure to call the cors policy after the routing calls and before the Authorization calls:
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("AllowMyOrigin");
app.UseAuthorization();
app.UseMiddleware<ApiKeyMiddleware>();
app.MapControllers();
app.Run();
I still get the cors error, also with enabled browser addons which should disable the issues on the browser.
I can't seem to figure out what is missing and would appreciate help

So it turned out my CORS-Configurations were already properly set up.
As jdweng noted in the comments, the 400 response with the type: "cors" might have just been a false error in order to confuse hackers as some servers may do that.
This meant I switched focus on checking back on my Request-Headers and Payload and was able to identify an issue with the DateTime conversion of one of the Attributes of the JSON-Payload.
After fixing this, the requests came through and I also didn't get any CORS-Errors.
So in case you run into a similar issue and are already very sure about the proper setup for the CORS-options, be sure to debug your Fetch/Axios Request and implement proper error handling on the backend to see if the input model is valid and catch the errors to send back more detailed errors.

Related

HTTP PUT, DELETE methods returning 405 when CORS is enabled in .NET 6

I'm having an issue with CORS in a .NET 6 Web API project. Development started in .NET 5, but was upgraded to .NET 6 later.
CORS was originally enabled using a named policy with AllowAnyHeaders() and AllowAnyMethods() as was explained in this Microsoft Docs article and this article on CodeMaze.
It worked perfectly fine on my local machine during development. However, when it was deployed to the testing server, only GET and POST works. PUT and DELETE do not work.
The PUT and DELETE requests in Postman for any PUT or DELETE method in any endpoint for any controller shows a 405 Method Not Allowed response. The Header's Allow field shows GET, HEAD, OPTIONS, TRACE.
However, changing PUT to OPTIONS still gives a 405 response, but the Allow field has DELETE, GET, PUT.
The Blazor WASM client shows the following in the console when attempting to edit or delete:
Access to fetch at 'http://ip-address:port/api/v1/EndpointName/92b956cd-2290-4270-8df5-056355cab846' from origin 'http://servername:port' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Since then I have read the MDN article explaining CORS and tried numerous solutions from various articles and Stack Overflow posts.
Origins work with .AllowAnyOrigins(), .WithOrigins("*"), and .WithOrigins(list hosts and ports).
Headers work with .AllowAnyHeader() and .WithHeaders("*"). Even after removing .WithExposedHeaders("X-Pagination") this header still shows and still works.
.AllowAnyMethod(), .WithMethods("PUT", "DELETE"), .WithMethods("*") all yield the same result described above.
The current code in the Startup.cs file is shown below:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
options.AddDefaultPolicy(
policy =>
{
policy.WithOrigins(Configuration["AllowedCORS"]);
policy.AllowAnyMethod();
policy.AllowAnyHeader();
policy.WithExposedHeaders("X-Pagination");
//policy.WithHeaders("*");
//policy.WithMethods("PUT", "DELETE");
//policy.WithMethods("*");
}));
services.AddControllers();
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
...
}
Your assistance in resolving this issue is greatly appreciated.
According to my experience when the iis server does not allow delete and put while not having the same problem in dev machine, the problem is not related to CORS config and you should check two point to find the problem:
First ExtensionlessUrlHandler-Integrated-4.0 :
Go to Handler Mappings in your IIS Manager. Find ExtensionlessUrlHandler-Integrated-4.0, double click it. Click Request Restrictions... button and on Verbs tab, add both DELETE and PUT
Second WebDAVModule Should also allow the verbs: Check here

Do I really need CORS here with Swagger?

I developed an API to give public access to some company data, which is of no value to hackers. It's public data that can be sourced from other websites.
I developed the project using default Visual Studio ASP.Net Core API templates. One thing I noticed it's using CORS and I don't know how it got in here to be honest.
However, the default Policy is set as any domain, any method and any header:
builder.Services.AddCors(p =>
p.AddPolicy("corsapp", builder =>
{
builder.WithOrigins("*").AllowAnyMethod().AllowAnyHeader();
}));
Do I even need CORS, if I am only allowing the API to run from a single origin, which already has HTTPS?
What benefit, when the API works as is?
Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//do I really need this!?!
builder.Services.AddCors(p => p.AddPolicy("corsapp", builder =>
{
builder.WithOrigins("*").AllowAnyMethod().AllowAnyHeader();
}));
var startup = new Startup(builder.Configuration);
startup.ConfigureServices(builder.Services);
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
startup.Configure(app);
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
//why!?!
app.UseCors("corsapp");
app.UseAuthorization();
app.MapControllers();
app.Run();
UPDATE
I've re-worded my OP based on Rahul's excellent video about CORS from Chen's answer below. However, I am still confused if I should configure CORS here to give a specific single origin as I am more worried someone after me may not configure this Policy correctly if the API is required in more than two places.
Thanks
You would need to know if your program provides API responses to client applications loaded from other domains to determine if you need to enable CORS.
For example, there are two cases where no action is needed for CORS support:
Swagger UI is hosted on the same server as the application itself (same host and port).
The application is located behind a proxy that enables the required CORS headers. This may already be covered within your organization.
You can get a better understanding and use of CORS through this link and this official documentation.

How to solve "Failed to bind to address http://127.0.0.1:5000: address already in use."

I created a Asp.Net Core app with Visual Studio and used the publish option of VS to publish my app on my Azure account.
After publishing it, I used the link to access my website but I get a "HTTP Error 500.30 - ASP.NET Core app failed to start"
I went to the console in Azure to manually start my app and have more detail about the issue and I got this.
Not really sure how to solve this issue with my port
Below is the code from program.cs
var connectionString = builder.Configuration.GetConnectionString("LocalConnection");
builder.Services.AddDbContext<LotharDataBaseContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Through your screenshot, I saw Kestrel, so I think, the webapp you created should be on linux platform. The port occupancy on your screenshot is expected behavior, it shouldn't be the root cause. Since the site is already running, and you manually command it to start again, this error should appear.
I suggest you provide your Program.cs file first, we need to look at UseUrls, or the code for UseKestrel.
How to check the logs when start webapp:
open you kudu site, url should be https://your_app_name.scm.azurewebsites.net
open newui, https://your_app_name.scm.azurewebsites.net/newui
steps:
In this default_docker.log file, we will get useful message.
Steps you can try:
Try to add .UseIIS, and we know your platform is linux.
Kestrel address binding errors in azure app service
Remove .UseUrls(), and re-deploy your webapp.
In my case, i was using the azure sql database so changing the connection string of database to use tcp protocol and 1433 as port, resolved this problem.
e-g
Server=tcp:<ServerName>.database.windows.net,1433;Initial Catalog=<DatabaseName>

Why do I get CORS errors even though I'm allowing all origins?

So I 've made a web app using Vue, and I'm using ASP.NET Web App (.NET 5) for the backend.
When I run the Web API locally on localhost:44393 it works just great making POST & GET requests from the client that's running locally.
I then go to click "Publish" to send the files over to where I'm hosting.
At this point I change the URL that the client uses to make requests to https://api.mywebsite.com which is the same website as the one that was running locally since I published it now.
(it makes these requests using fetch so it would be fetch("https://api.mywebsite.com/TheController/AddServer" for instance)
This is where it gets weird because when I make a post request to register or sign in, it works just fine, but as soon as I go to "Add post" which is a form that posts to a different endpoint on the API, I get this error.
Access to fetch at 'https://api.mywebsite.com/TheController/AddPost'
from origin 'https://mywebsite.com' has been blocked by CORS
policy: No 'Access-Control-Allow-Origin' header is present on the
requested resource. If an opaque response serves your needs, set the
request's mode to 'no-cors' to fetch the resource with CORS disabled.
And that doesn't happen when I run the web API locally. Why is it that it only occurs after I publish the files to my host and use the actual domain?
(I tried making the same request from the client when it's running locally too but it gives the exact same exception)
I switched out the domain name in the question to mywebsite.com because I don't want to share it.
Here is my ConfigurationServices
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("https://mywebsite.com",
"http://localhost:8080",
"https://mywebsite.com/add")
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
...
And the Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "mcraftserverapi v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
});
}
you have to remove
builder.WithOrigins("https://mywebsite.com",
"http://localhost:8080"
)
or
.AllowAnyOrigin()
you can't use them together

Angular app running localhost calling dotnet app on different port gets no-referrer-when-downgrade. Due to withCredentials?

I setup a new Angular app with Angular CLI and it runs on http://localhost:4200
I call webservices that I develop with dotnet core which runs on http://localhost:5000
I allowed CORS for the localhost setup. I am sure it worked in the past but now I get a
no-referrer-when-downgrade
error message in chrome.
It somehow has to do with withCredentials: true
If I put false then it works fine.
How can I pass credentials on http calls to a different port on the same localhost domain?
You might try to upgrade your .NET Core application to HTTPS.
The no-referrer-when-downgrade message indicates that the default referrer policy is in place as described here.
no-referrer-when-downgrade (default)
This is the default behavior if no policy is specified, or if the
provided value is invalid. The origin, path, and querystring of the
URL are sent as a referrer when the protocol security level stays the
same (HTTP→HTTP, HTTPS→HTTPS) or improves (HTTP→HTTPS), but isn't sent
to less secure destinations (HTTPS→HTTP).
Just for a test you might try to set the referrer policy for development environment to a different value (this code uses NWebsec.AspNetCore.Middleware):
if (env.IsDevelopment())
{
app.UseReferrerPolicy(opts => opts.UnsafeUrl());
}
It turned out it was no no-referrer-when-downgrade issue but a CORS issue.
I was missing the AllowCredentials() in the CORS policy
public void ConfigureServices(IServiceCollection services)
{
// add cors
services.AddCors(options =>
{
options.AddPolicy(name: "MyCorsPolicy",
builder => builder.SetIsOriginAllowed(s => s.Contains("localhost"))
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}

Categories