CORS error in dev environment; works OK locally - c#

I am trying to make an api call from a vue application to a .net core web api. Locally this works, when we then run it on our first dev environment we get this when it trys to make the request
Access to XMLHttpRequest at
'https://bla-api/api/foc?page=1&pageSize=10&sortBy=&sortDirection=ASC'
from origin 'https://bla-api' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I have added the following to the C#' Startup file in the ConfigureServices method. To just get it working I wanted to provide the *(wildcard), so let anyone call this. So presume that the named policy AllowAnyOrigin would do this!?
readonly string _SpecificOrigins = "AllowSpecificOrigins";
services.AddCors(options =>
{
options.AddPolicy(_SpecificOrigins,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
})
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
then also added this in the Configure method
app.UseCors(_SpecificOrigins);
app.UseMvc();
What am I missing? I also try and make a fiddler request to the api and it breaks.
Any help would be greatly appreciated

This was a red herring, the web api was not even deployed correctly, it was being deployued as a kestrel exe but was deployed as an azure web app. Adding a web.config pointing to the main api project resolved the issue. I did not write the deployment so that no needs looking at next. Presume the above question is fine then, cheers for the help

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

Access to remote URL has been blocked by CORS policy

I get below error. I already setup the server side with cors:
Access to XMLHttpRequest at 'https://www.learningcontainer.com/wp-
content/uploads/2020/04/sample-text-file.txt' from origin 'https://localhost:44325' has been
blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value
'https://learningcontainer.com' that is not equal to the supplied origin.
This configuration:
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
builder.WithOrigins("https://www.learningcontainer.com") #* .AllowAnyOrigin() *#
.AllowAnyMethod()
.AllowAnyHeader());
});
should be done on a Server, and not yours but the server of the external API ( https://www.learningcontainer.com). You do nothing in that regard, except call end points on that Web Api.
Workaround solution:
AS CORS is a security feature of JavaScript enforced by the browser, you can circumvent it by calling your Server code from which you perform the call to this Web Api end point, and then returns it back to your WebAssembly front-end. You should use HttpClient to access the url from above.
WebAssembly front end calls a controller's method on your server(hosted) by using HttpClient. Then you call the url from the hosted server app using HttpClient. When the Web Api (url) end point returns a value, you pass it on to the WebAssembly Blazor front end.

Consume third party API with Blazor WebAssembly [duplicate]

I have a blazor web assembly which fetches from an external API built on ASP.NET Core which I do not have access to. I can perform get requests, but cannot perform post requests. I get the following error when I do.
Access to fetch at 'http://external:9000/User/Create' from origin 'http://localhost:56138' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
The author of the api confirms he enabled cors to allow any header in his startup and also suggested I do the same but this did not fix the issue. I confirmed from the debugger I am sending the right data format the endpoint requires and I am also running on http scheme same as the web service.
This is the client configuration in program.cs
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://external:9000/") });
builder.Services.AddCors(policy =>
{
policy.AddPolicy("_myAllowSpecificOrigins", builder => builder.WithOrigins("http://external:9000/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
This is how I post
var dataJson = JsonConvert.SerializeObject(application);
var stringContent = new StringContent(dataJson, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync($"User/Create", stringContent);
I have read this is a common problem with blazor assembly, I'm not entirely sure of what I read. I am currently trying to move the project to blazor server to see if it would work, but I would prefer it on web assembly.
builder.Services.AddCors(policy =>
{
policy.AddPolicy("_myAllowSpecificOrigins", builder => builder.WithOrigins("http://external:9000/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
This configuration should be done on a Server, and not yours but the server of the external API. You do nothing in that regard, except call end points on that Web Api.
The author of the api confirms they enabled cors to allow any header in his startup
If so, ask them for the code for confirmation...
and also suggested I do the same but this did not fix the issue.
You do nothing of the sort.
Workaround solution:
AS CORS is a security feature of JavaScript enforced by the browser, you can circumvent it by calling your Server code from which you perform the call to this Web Api end point, and then returns it back to your WebAssembly front-end. Use asynchronous code as much as you can.
Update as per comment
Are you saying I should have two projects, the server and the client under one solution? The server calls the calls the external api, then passes it to the client. Is this what your last suggestion is?
If you're using WebAssembly Blazor App hosted wherein the hosting server contains Web Api controllers, then you should expose end points that can be called from your WebAssembly front-end. The code in these end points should perform the HTTP calls to the external Web Api, and pass back to the WebAssembly calling methods the data received from the external Web Api.
Note: If you don't have such controllers ( they are created by default by Visual Studio), you may add them yourself to the server project.
If you already have created a Web Api project instead of those controllers, then expose the necessary end points from your Web Api project. Note that it makes no difference whether your Web Api project resides in the same solution of the WebAssembly front-end, as long as you provide the correct Url.
If you're using WebAssembly Blazor App stand alone; that is, the default installation does not create a Server project, you'll need to create a Web Api project and use it, unless you've already created one.
You are working with localhost so you should use this configuration to your Server:
builder.Services.AddCors(policy =>
{
policy.AddPolicy("_myAllowSpecificOrigins", builder =>
builder.WithOrigins("http://localhost:56138/")
.SetIsOriginAllowed((host) => true) // this for using localhost address
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
//
app.UseCors("_myAllowSpecificOrigins");

Cannot enable CORS in ASP.NET Core 2.0

I am trying to enable CORS on an ASP.NET Core MVC application. I am very frustrated.
I've already tried several snippets and none worked for me. This was my last attempt.
Startup.cs, "ConfigureServices" method.
services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader().AllowCredentials()));
Startup.cs, "Configure" method.
app.UseCors("AllowAll");
app.UseMvcWithDefaultRoute();
In my Controller I used this
[EnableCors("AllowAll")]
public class TestController : Controller
{
[Route("cors")]
public string Test()
{
return "Ok";
}
}
I am getting CORS issues on both Firefox and Chrome.
There is one important thing to know in order to make CORS work:
Access-Control-Allow-Origin
From the documentation at MSDN,
If the response doesn't include the Access-Control-Allow-Origin
header, the cross-origin request fails. Specifically, the browser
disallows the request. Even if the server returns a successful
response, the browser doesn't make the response available to the
client app.
If this header is present then generally your config should work.
You can verify this using fiddler.
There is one option to "Disable Same Origin" policy from the chrome and firefox. Please refer this blog for checking how to disable it.
But please note that this would make your browser vulnerable, this may be advisable to get it working during development, but not recommended at all for production scenarios.

TryGetFormCredentials returns null on cross-domain request

I've set up OAuth authentication in a project that uses WebAPI, and I had it working 100% fine.
Then I moved the front end app into a separate project in the solution. So now when I run the app, it's obviously on a different url (localhost:64049) to the API & Authentication Server (which are in the same project, server from localhost:63265).
To get CORS working, I believe I need to add this line to GrantResourceOwnerCredentials
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
However, when I run it, the TryGetFormCredentials in ValidateClientAuthentication is not returning the clientId.
If I send the request from Fiddler/Postman, it still works.
What am I missing?
Managed to fix it by enabling CORS on the app in Startup.cs:
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
I had to remove the other Response Headers, though.

Categories