What am I missing regarding the simple CORS policy? - c#

Making a post call to the API controller and no matter how to set things up, I get this response in the browser console.
Access to XMLHttpRequest at 'http://192.168.68.107:8090/api/Files/submitfile' from origin 'http://192.168.68.100:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have a .Net 6 Core API that I want to use in my local network. I have local IIS setup on a small server that I publish the API to. It deploys and mostly functions correctly. I have the CORS policy setup according to the docs.
var _policyName = "CorsPolicy";
builder.Services.AddCors(opt =>
{
opt.AddPolicy(name: _policyName, builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
}
);
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(_policyName);
app.UseAuthorization();
app.MapControllers();
app.Run();
API functions correctly when I launch Localhost and have my front end axios post call submit to it, but it will not work when I publish to the in house web server I have.
I've setup the axios call correctly. I believe I've setup the CORS policy correctly.
Only thing I can think of is the way I have the controller setup.
I have a controller that takes a FromBody parameter and it works perfectly Cross origin. It's here
[HttpPost, Route("new-category")]
public async Task<IActionResult> AddNewCategory([FromBody] CategoryDto category)
{
try
{
await _uploadService.SaveNewCategory(category.Category);
return Ok();
}
catch (Exception)
{
throw;
}
}
This controller is the culprit. No matter what I try CORS blocks this ..
[HttpPost, Route("submitfile")]
public async Task<IActionResult> SubmitFile([FromForm] FileUploadModel file)
{
try
{
if (file.File.Length <= 0)
return BadRequest("Empty File");
//save file
var fileLocation = await _uploadService.FileUpload(file.File, file.Category);
return Ok();
}
catch (Exception ex)
{
throw;
}
}
Here's the axios method that calls this controller.. which works when running localhost
await axios.post(API + "Files/submitfile", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
The above CORS response is what I get. What am I missing here? How can I resolve this error?
Thank you for taking a look. Greatly appreciate the help

I don't know why that doesn't work, but I had a similar issue until I bypassed the named policy and applied the requirements in the UseCors() method:
app.UseCors(policy => {
policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin();
});

Related

Blazor cannot connect to ASP.NET Core WebApi (CORS)

I have a ASP.NET Core Server running on local IP https://192.168.188.31:44302 with Web API Enpoints.
I can connect to said server with VS Code REST Client.
Now I want to conenct to the Web API with Blazor WebAssembly running on https://192.168.188.31:5555.
My Blozor Code:
#page "/login"
#inject HttpClient Http
[ ... some "HTML"-Code ... ]
#code {
private async Task Authenticate()
{
var loginModel = new LoginModel
{
Mail = "some#mail.com",
Password = "s3cr3T"
};
var requestMessage = new HttpRequestMessage()
{
Method = new HttpMethod("POST"),
RequestUri = ClientB.Classes.Uris.AuthenticateUser(),
Content =
JsonContent.Create(loginModel)
};
var response = await Http.SendAsync(requestMessage);
var responseStatusCode = response.StatusCode;
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("responseBody: " + responseBody);
}
public async void LoginSubmit(EditContext editContext)
{
await Authenticate();
Console.WriteLine("Debug: Valid Submit");
}
}
When I now trigger LoginSubmit I get the following error-message in the developer console of Chrome and Firefox: login:1 Access to fetch at 'https://192.168.188.31:44302/user/authenticate' from origin 'https://192.168.188.31:5555' 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.
I'm new to web development and found that you have to enable CORS on the server-side ASP.NET Core project, so I extended startup.cs with
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<UserDataContext, UserSqliteDataContext>();
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("https://192.168.188.31:44302",
"https://192.168.188.31:5555",
"https://localhost:44302",
"https://localhost:5555")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
services.AddApiVersioning(x =>
{
...
});
services.AddAuthentication(x =>
...
});
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddScoped<IViewerService, ViewerService>();
}
public void Configure(IApplicationBuilder app,
IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
Program.IsDevelopment = env.IsDevelopment();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors(MyAllowSpecificOrigins);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
Log.Initialize();
}
But I still get above error message.
Am I doing something wrong with configuring CORS?
Why is it working as expected with the VS Code REST Client and how am I making the call wrong in the Blazor WASM application?
The issue causing the error message login:1 Access to fetch at 'https://192.168.188.31:44302/user/authenticate' from origin 'https://192.168.188.31:5555' 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. was caused by HttpsRedirection.
To resolve the issue, either deactivate HttpsRedirection by removing the line app.UseHttpsRedirection(); in function Configure or add the proper ports for redirection in function ConfigureServices (recommended way).
In my case, I start my WebAPI at port 44302, so my solution looks like this (you have to adapt it to your port number):
if (Program.IsDevelopment)
{
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
options.HttpsPort = 44302;
});
}
else
{
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
options.HttpsPort = 443;
});
}
Also note that it is sufficient to add the IP address of the requesting API to CORS like this:
services.AddCors(options =>
{
options.AddPolicy(name: specificOrigins,
builder =>
{
builder.WithOrigins("https://192.168.188.31:5555",
"http://192.168.188.31:5444")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
Step 1: Please add following code in your WebAPI's Startup.cs to allow CORS with specific origins:
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
builder.WithOrigins("https://localhost:44351")
.AllowAnyHeader()
.AllowAnyMethod());
});
Step 2: Now change "https://localhost:44351" in above code with your blazor web assembly application's URL. Refer below screen shot:
Step 3: Now add app.UseCors() in your WebAPI's Configure method after app.UseRouting() and before app.UseRouting(). Please refer below screen shot:
I was also facing same issue and it solved my problem. Hope it will also work for you.
Note: No changes required in Blazor web assembly code to fix the above issue.

React .NET Enable CORS - No 'Access-Control-Allow-Origin' header is present on the requested resource

Been attempting to integrate a React front-end with a .NET Framework backend and I am constantly coming into contact with CORS errors. The request I am sending to the server works on Postman. I extracted the code from Postman and put it into my react app (Fetch) and I receive the following error:
Access to fetch at 'http://localhost:33333/Token' from origin 'http://localhost:3000' 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.
However, on my .NET backend I added the following filter:
using System;
using System.Web.Mvc;
namespace TheFifth.Cors
{
public class AllowCrossSiteAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin",
"*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers",
"*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Credentials",
"true");
base.OnActionExecuting(filterContext);
}
}
}
Then referenced the Filter at the top of my Controller
[AllowCrossSite]
public class DA_Object
{
//some code
}
Does anyone know why my .NET backend or my React Frontend is preventing me from communicating across different ports - even though it works on Postman?
Additional Details
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("type", "x");
urlencoded.append("username", "x#x.com");
urlencoded.append("password", "x#");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("http://localhost:33333/api/Token", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
In your startup.cs
in the ConfigureServices method you should have something like this, if you don't have then add it:
services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
//App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.
builder
.AllowAnyOrigin()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
And in your appsettings.json add http://0.0.0.0:80 like this:
"App": {
...
"CorsOrigins": "http://*.mycompany.com,http://0.0.0.0:80",
...}
Another solution is to add a CORS extention in your browser and enable it, but it's not recommended

Post request from Vue application blocked by CORS policy

I'm trying to call my C# web-api from my Vue webapplication but I encounter the following error:
Access to XMLHttpRequest at 'http://www.api.example.com/'
from origin 'http://www.example.com' 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.
The following code snippet shows how I'm calling the rest-api with use of axios.
import axios from 'axios'
const client = axios.create({
baseURL: 'http://www.api.example.com',
json: true,
withCredentials: true
})
export default {
async execute(method, resource, data) {
return client({
method,
url: resource,
data,
headers: {}
}).then(req => {
return req
})
},
myFunc(data) {
return this.execute('post', '/', data)
}
}
The web-api with the POST request method is as follows:
[EnableCors("VueCorsPolicy")]
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
[HttpPost]
public async Task<int> Post([FromBody] Data data)
{
// stuff
}
}
I have also added a CORS to my "ConfigureServices" method in the Startup.cs file.
services.AddCors(options =>
{
options.AddPolicy("VueCorsPolicy", builder =>
{
builder
.WithOrigins("http://www.example.com")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
And lastly I have also added to the "Configure" method in the Startup.cs file:
app.UseCors("VueCorsPolicy");
CORS is a security mechanism, that cannot be overcome by simply modifying your code. The server has to be set so that it allows the requests from your source - so, if you control the server you can do it.
However, there are some solutions that help you during development phase, like cors-anywhere.herokuapp.com.
You should add it before the baseURL in your code, like this:
baseURL: 'https://cors-anywhere.herokuapp.com/http://www.api.example.com'.
This is NOT a solution for production, only for development.
You can host your own cors-anywhere app, more on this: https://www.npmjs.com/package/cors-anywhere
.WithOrigins("http://www.thomasleoblok.dk/") this is where your problem is, it should be .WithOrigins("http://www.example.com") since it is example.com you want to allow to make requests, it you want to allow any site you can change it to .WithOrigins("*")
if you are trying locally you must open the origin localhost, otherwise the BE will always return a cors error as localhost != http://www.thomasleoblok.dk/
for testing I suggest you enable AllowAnyOrigin()
example:
services.AddCors(options =>
{
options.AddPolicy("VueCorsPolicy", builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});

.NET Core 2 WebAPI CORS problems with Angular 4 front end and Windows Auth

Yes I have countless articles and re-arranged add app.UserCors and other pieces of advice but am still stuck.
Using Visual Studio WebAPI Core 2 with Angular 2 web front end.
Using Windows authentication on remote server using IIS 8.5 (actually this doesn't work locally either).
WebAPI startup conf:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SomeContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SomeDB")));
//////// ********************
//////// Setup CORS
//////// ********************
var corsBuilder = new CorsPolicyBuilder();
corsBuilder.AllowAnyHeader();
corsBuilder.AllowAnyMethod();
corsBuilder.WithOrigins("*");
corsBuilder.AllowCredentials();
services.AddCors(options =>
{
options.AddPolicy("AllowAll", corsBuilder.Build());
});
services.AddMvc();
...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("AllowAll"); //<===
app.UseMvc();
...
When I run the WebAPI locally, or deploy it to a remote server, My Angular 4 front end gives me:
For a call to a WebAPI controller - 401 (Unauthorized) (even on controllers that have no [Authorize()] set.
When I try to use my local instance of the Angular app to access the remote WebAPI:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62482' is therefore not allowed access. The response had HTTP status code 401.
I have tried re-arranged the order of adding services in startup.
I have manually added the respone headers in IIS8.5 (they get overwritten whenever I deploy new code).
I have remove all the CORS stuff completely from the WebAPI app.
I SWEAR this all worked at one time. Not sure what changed.
I all runs fine when I deploy both the WebAPI Core 2 app and the Angular web app to the remote server because origins are the same, but that makes local debugging impossible.
*** Angular REPO code per request:
import { Injectable, Inject } from '#angular/core';
import { Http } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { DocumentModel } from '../models/document.model';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/map';
import { map } from 'rxjs/operators/map';
import { IRepository } from './IRepository';
declare var API_URL: string;
#Injectable()
export class DocumentRepository implements IRepository<DocumentModel, number> {
GetByDocument(key: any): Observable<DocumentModel[]> {
throw new Error("Method not implemented.");
}
private httpService: Http;
private apiRootUrl: string;
constructor(http: Http) {
this.httpService = http;
this.apiRootUrl = API_URL;
}
Create(Model: DocumentModel): Observable<any> {
throw new Error("Method not implemented.");
}
Find(key: any): Observable<DocumentModel[]> {
return this.httpService.get(this.apiRootUrl +'documents/mine').map(result => result.json());
}
Get(id: any): Observable<DocumentModel> {
return this.httpService.get(this.apiRootUrl +'documents/' + id).map(result => result.json());
}
}
This works for me :
In Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
//app.UseHttpsRedirection();
app.UseCors(
options => options.AllowAnyOrigin().AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
);
app.UseMvc();
}
and that all, no other mention to Cors.
I use JWT Bearer Token and [Authorize] works as intended.
You can try with Postman first, just to see if your endpoint is working, then move to make an Angular http.get()
This is the angular part
const headers = new HttpHeaders().
set('Accept', 'application/json')
const url = 'http://localhost:5000/api/'
return this.http.get(
url + 'endpoint',
{ headers: headers }
);

Cors requests and MVC5

So I have a view on a controller ...
[AllowAnonymous]
[Route("MyView")]
public ActionResult MyView()
{
// first attempt at solving problem
Response.AddHeader("Access-Control-Allow-Origin", "*");
Response.AddHeader("Access-Control-Allow-Headers", "*");
Response.AddHeader("Access-Control-Allow-Methods", "*");
return PartialView();
}
I tried adding this attribute (2nd attempt) ...
public class AllowCors : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Headers", "*");
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Methods", "*");
base.OnActionExecuting(filterContext);
}
}
As im using owin to initialise my app I figured this might work (3rd attempt) ...
app.Use((context, next) =>
{
if (context.Request.Method == "OPTIONS")
{
context.Response.StatusCode = 200;
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "*" });
return context.Response.WriteAsync("handled");
}
return next.Invoke();
}).UseStageMarker(PipelineStage.PreHandlerExecute);
The problem is that if I just straight up ask for it by putting the url in the browser I get the right headers ...
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:*
Access-Control-Allow-Origin:*
... moving over in to postman to test this, when I issue an OPTIONS call to the same URL I get this in the headers ...
Allow: OPTIONS, TRACE, GET, HEAD, POST
... so how do I get MVC to respond correctly to the OPTIONS http verb so that I can use this view outside the domain of the site?
EDIT
it's worth noting that I have looked around already and found all these and many more ...
The requested resource does not support http method 'OPTIONS'.?
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?
Why does this jQuery AJAX PUT work in Chrome but not FF
How to support HTTP OPTIONS verb in ASP.NET MVC/WebAPI application
... i'm also very familiar with using CORS and making CORS requests in to WebAPI, but for some reason I can't seem to make a CORS request in to MVC without getting this seemingly "dummy" response back.
I think what I need is a means to override / replace the MVC default behaviour to this HttpVerb based request to allow me to embed views in a remote site.
Install these two nuget packages:
Microsoft.AspNet.Cors
Microsoft.Owin.Cors
Then in your Startup.cs add this line inside the Configuration function:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.UseCors(CorsOptions.AllowAll);
}
}
In my demo setup I'm sending a post request from the domain http://example.local (Apache) to the domain http://localhost:6569/ (IIS Express).
Without app.UseCors(CorsOptions.AllowAll); (notice the warning in the console and no CORS headers):
And after adding the packages and adding the line to the Configuration method:
As you can see in the screenshot, the access-control-allow-origin was added in the response headers as expected/

Categories

Resources