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");
Related
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.
I've been developing a hobby project in Blazor Webassembly ASP.NET Core hosted using the template Identity Server implementation, and have developed some authorization, which looks at the API calls from Blazor Webassembly, and uses the the request header 'Referer' to authorize.
The user has some subscriptions to some Teams they attend, and they can switch between them.
The URL has the Guid of what team page they are currently on, and when the Blazor Webassembly made an API call to the ASP.NET Core Web API, it would then look at the 'Referer' to find the Guid.
Here is the request header 'Referer' value as in hosted with ASP.NET Core
The 'Referer' value would be
https://localhost:5001/Instructor/{some-guid}.
So from the Guid in the 'Referer', I could know what team the user is trying to get information for. F.ex. a list of members on the team.
This was working well, but because I was migrating to ASP.NET Core 6, and wanted to create a JAMStack setup, I moved to a new setup with standalone Blazor Webassembly, and ASP.NET Core Web API setup.
I have the exact same authorization setup, except I have switched to using Auth0 instead of Identityserver (Duende).
I am also using NSwagStudio to create a client for the HTTP Requests for both the old and new project (and the setup is identical).
My problem now is that when I look at the request header 'Referer'. I only get the root address https://localhost:7004/. It does not send the rest of the URL.
Here is the request 'Referer' in migrated project, not hosted with ASP.NET Core
I can see from my research that 'Referer' probably isn't used like this much, because there is no info at all about this header.
Does anyone know if this could be me switching to Auth0, or is there is any change between .NET 5 and .NET 6 I should be aware of.
Or maybe just info about how I can control this.
I add the NSwagClients like this (using the newest NSwag versions):
string webApiBaseAddress = builder.Configuration["webApiBaseAddress"] ?? string.Empty;
builder.Services.AddTransient<AuthorizationMessageHandler>(sp =>
{
// Get required services from DI.
var provider = sp.GetRequiredService<IAccessTokenProvider>();
var naviManager = sp.GetRequiredService<NavigationManager>();
// Create a new "AuthorizationMessageHandler" instance,
// and return it after configuring it.
var handler = new AuthorizationMessageHandler(provider, naviManager);
handler.ConfigureHandler(authorizedUrls: new[] {
// List up URLs which to be attached access token.
naviManager.ToAbsoluteUri($"{webApiBaseAddress}/api/authorized/").AbsoluteUri
});
return handler;
});
builder.Services.AddHttpClient<ITeamClient, TeamClient>(client =>
client.BaseAddress = new Uri(webApiBaseAddress)).AddHttpMessageHandler<AuthorizationMessageHandler>();
I figured it out after spending a lot of days on this.
The problem was that ASP.NET Core Hosted Blazor Webassembly calls the API with the same Origin, so the 'Referrer Policy': 'origin-when-cross-origin' did not restrict the 'Referer' header.
'origin-when-cross-origin' is the standard for 'Referrer Policy', and restricts the 'Referer' header for cross-origin calls.
But when I ran it with Blazor Webassembly and ASP.NET Core Web API each in their own project, they were localhost:7004 and localhost:7170, which are seen as same-site but not same-origin, so it was restricted to only show 'Origin' as the 'Referer' header.
I can't seem to find any way to make the API and Blazor be from the same 'Origin', so I have made my application somewhat less secure for now, by setting <meta name="referrer" content="no-referrer-when-downgrade"> in my index.html file in Blazor Webassembly.
My application does not send user sensitive information in the URL ever, and everything is using HTTPS, so it isn't really that much of a problem if the 'Referer' is read by an external source.
I will be looking at a better solution to tell my API from what Team the caller is trying to access content, to check if the caller also has the policy in the JWT to access it, but for now this will do.
I have a swagger (Swashbuckle) enabled on one of my API controllers.
Server sits on http://192.168.7.119:1001 and Swagger UI is accessed through http://192.168.7.119:1001/swagger.
When connecting locally, everything is fine and I can access Swagger UI on port 1001 as expected.
But when trying connect throug proxy on port 1000 (which redirects 1000 to 1001), I get a well known error:
"Can't read from server. It may not have the appropriate access-control-origin settings".
I have read this:
Unable to access swagger despite cors enabled Asp.NET WebAPI
and tried to set the RootUrl manually in Startup file, within Swagger like this:
.EnableSwagger(c =>
{
c.RootUrl(req => #"http://192.168.7.119:1001";
...
});
CORS settings are set as:
appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
Any hints what am I doing wrong here?
Putting together this two pages from github repos of Swashbuckle the easy way to do what you're asking is:
From Github Make sure that your proxy is sending the X-Forwarded-* headers (Apache does it out of the box while Nginx doesn't seems so. You have to do some changes on the nginx conf.
From Github. Create this HttpRequestMessageExtensions static class with the ComputeHostAsSeenByOriginalClient method and then
.EnableSwagger(c =>
{
c.RootUrl(req => req.ComputeHostAsSeenByOriginalClient());
...
});
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
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.