Cross-Origin Request Blocked even though it responds with 200 ok status code - reactjs

Folks I'm developing a fullstack React.js - ASP.NET Core 5 application. The backend is done (fully tested). Of course it includes a CORS policy to allow request from the client side, but when I'm trying to send a request from react using axios, axios throws a network error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://localhost:5001/api/customers. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.
I see the server sends correct responses (I can even debugged the server) but axios stills failing. I only tried to solved it by including a proxy in package.json:
"proxy": "https://localhost:5001"
I'm going to include my app.js request code and startup.cs code, since it contains the CORS Policy:
Client
const fetchCustomers = async () => {
const customers = await axios.get(customersApiUrl);
console.log(customers);
setCustomers(customers);
setIsLoading(false);
};
Server
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://localhost:3000/");
builder.AllowAnyHeader();
builder.AllowAnyMethod();
});
});
services.AddControllers();
services.AddDbContextPool<TwinEnginesDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Standard")));
services.AddScoped<ICustomerTypeRepository, CustomerTypeRepository>();
services.AddScoped<ICustomerTypeService, CustomerTypeService>();
services.AddScoped<ICustomerRepository, CustomerRepository>();
services.AddScoped<ICustomerService, CustomerService>();
services.AddAutoMapper(Assembly.GetExecutingAssembly());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Edited: I'm including the CustomersController.cs code plus the details from the HTTP request.
CustomersController.cs
[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
private readonly ICustomerService _customerService;
private readonly ICustomerTypeService _typeService;
private readonly IMapper _mapper;
public CustomersController(ICustomerService customerService, ICustomerTypeService typeService, IMapper mapper)
{
this._customerService = customerService ?? throw new ArgumentNullException(nameof(customerService));
this._typeService = typeService ?? throw new ArgumentNullException(nameof(typeService));
this._mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}
// [EnableCors("MyAllowSpecificOrigins")]
[HttpGet("")]
public async Task<ActionResult<IEnumerable<CustomerDTO>>> GetCustomers()
{
var customers = await _customerService.GetAllAsync();
var response = _mapper.Map<IEnumerable<CustomerDTO>>(customers);
return Ok(response);
}
}
Request image:
Any ideas, thoughts? I really need your help folks, this is a technical assignment for a dev job.

Try to use the setting without the
slash at the end: builder.WithOrigins("http://localhost:3000");
After the change please do a clean and rebuild the project, as it might be a thing.
Also, you don't need a proxy setting on the JS side.
P.S. A mode for the request might not be set properly on the Axios side. In case the solution above doesn't work try to use:
axios(requestURL, { mode: 'cors' })

Try to add this attribute to your controllers
[EnableCors(MyAllowSpecificOrigins)]

Related

CORS, header field content-type is not allowed in preflight response, .NET React [duplicate]

This question already has answers here:
CORS in .NET Core
(10 answers)
Closed 2 months ago.
I know there's plenty of questions here about CORS but I can't make it work and I've been stuck for few days by now.
I'm working on a little React ts app and implementing API calls to a basic .NET webAPI.
I already implemented the get in the app, now I'm stuck on POST.
Here's the error: Access to XMLHttpRequest at 'https://localhost:7122/api/Products/' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
Here's React POST code
function postData(post: { id: number; pName: string; pDesc: string; }) {
axios.post(uri, { post })
.then(res => {
console.log(res);
console.log(res.data);
})
.catch((error) => {
console.log(error);
})
}
And here's .NET controller implementation
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private readonly ProductContext _context;
public ProductsController(ProductContext context)
{
_context = context;
}
[HttpPost]
public async Task<ActionResult<ProductDTO>> PostTodoItem(ProductDTO todoDTO)
{
var todoItem = new Product
{
Description = todoDTO.Description,
Name = todoDTO.Name
};
_context.Products.Add(todoItem);
await _context.SaveChangesAsync();
/*return todoDTO;*/
return Ok();
}
}
Here's my Program.cs where I should apply useCors() policy
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<ProductContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "MyCorsPolicy",
policy =>
{
policy.WithOrigins("https://localhost:7122", "https://localhost:3000")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseCors("MyCorsPolicy");
app.MapControllers();
app.Run();
And my simple DTO
public class ProductDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
}
Right now I'm only trying to get an Ok() response. The preflight OPTIONS request is accepted correctly but then something goes wrong with the response. No problem with Swagger or Postman, I can POST correctly from there.
I browsed for few days by now here and in .NET docs, but the proposed solutions do not work.
I did install a Chrome plugin and while testing it, it says POST should work too.
As I get it, this problem should be solved already using useCors() policy in .NET, but as shown it still persist. What am I missing?
I'm quite new to web development as can be seen, so if any other info is needed please forgive me and let me know, thanks.
Replace https://localhost:3000 in your policy with http://localhost:3000 which is what your origin is.

React JS services request ASP.Net Core Getting 404 (Not Found) Error

I can't continue the flow due to the error in the Startup.cs file on the ASP.NET Core side in the service post operations I made using axios on the React.JS side.
When I have only one Singleton object in Startup.cs it doesn't get any errors and post/get operations work correctly. For example like this,
services.AddSingleton();
However, when I wanted to post/get multiple different pages, I couldn't update the Startup.cs file and did it right. As an example, when I write as follows, none of my requests are working.
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
I want all requests made by the client (React.JS) to work. How can I edit my Startup.cs file to receive all my service requests?
When I make a request on the coupon page, I get the following error.
https://localhost:5001/api/coupons/test 404 (Not Found)
ASP.NET Core
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMvc();
services.AddSingleton<VendorRegistrationService>();
services.AddSingleton<CalculateShippingService>();
services.AddSingleton<CouponsService>();
services.AddCors(o => o.AddPolicy("ReactPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
//.AllowCredentials();
}));
}
VendorRegistrationController.cs
Produces("application/json")]
[Route("api/[controller]")]
[ApiController]
[EnableCors("ReactPolicy")]
public class VendorRegistrationController : ControllerBase
{
private readonly ILogger<VendorRegistrationController> _logger;
public readonly VendorRegistrationService vendorRegistrationService;
private static List<VendorRegistration> vendorRegistrationList = new List<VendorRegistration>();
public VendorRegistrationController(VendorRegistrationService vendorRegistrationService, ILogger<VendorRegistrationController> logger)
{
this.vendorRegistrationService = vendorRegistrationService;
_logger = logger;
}
[Route("test")]
[HttpPost]
public VendorRegistration Index([FromBody] VendorRegistration vendorRegistration)
{
vendorRegistrationService.Create(vendorRegistration);
return vendorRegistration;
}
ReactJS - RegistrationForm.tsx
const handleFormSubmit = async (values: any): Promise<any> => {
const response = axios.post('https://localhost:5001/api/vendorregistration/test',
values).then(res=>{
console.log('res=>',res);
}).catch(function(error) {
console.log(error);
})
};
UPDATED
#Panagiotis Kanavos I updated the development after your comment. The service call for VendorRegistration is currently running. However, when I make a service request for the Coupon, I keep getting the 404 (Not Found) error.
POST https://localhost:5001/api/coupons/test 404 (Not Found)
CouponsController.cs
[Route("test")]
[HttpPost]
public Coupons PostTest([FromBody] Coupons coupons)
{
couponsService.Create(coupons);
return coupons;
}
VendorRegistrationController.cs
[Route("test")]
[HttpPost]
public VendorRegistration PostTest([FromBody] VendorRegistration vendorRegistration)
{
vendorRegistrationService.Create(vendorRegistration);
return vendorRegistration;
}

Pass JWT token from angular HttpClient to access secure .NET Core Web API

I need to call secure Web API from Angular 9 application by presenting the token. I am using Angular with .NET CORE 3.1 Web API. I have managed to generate Azure B2C token but stuck to call secure web api as I got CORS error.
Angular component calling Web API end-point
testAPI1(){
console.log("calling test API ...");
const myheaders = new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8',
'Authorization': this.authService.accessToken
});
this.http.get('https://localhost:5001/txn/v1/Dashboard/GetMessage', {headers: myheaders})
.subscribe((data)=>{
console.warn(data);
})
}
Auth Service
#Injectable()
export class AuthService implements OnInit{
constructor(
private oauthService: OAuthService,
private router: Router
){// other code}
public get accessToken() {
return this.oauthService.getAccessToken();
}
Web API controller & endpoint
[Authorize]
[Route("txn/v1/[controller]/[action]")]
[EnableCors("CorsPolicy")]
[ApiController]
public class DashboardController : ControllerBase
{
[HttpGet]
public ActionResult<HelloMessage> GetMessage()
{
var result = new HelloMessage()
{
GivenName = "james",
ReturnMessage = "Dashboard# Hello, Welcome to Digital tech"
};
return result;
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//JWT Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(jwtConfig =>
{
jwtConfig.Audience = Configuration["AzureAdB2C:ResourceId"];
jwtConfig.Authority = $"{Configuration["AzureAdB2C:Instance"]}{Configuration["AzureAdB2C:TanantId"]}";
jwtConfig.RequireHttpsMetadata = false;
jwtConfig.SaveToken = true;
jwtConfig.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer =true,
ValidateAudience = true,
ValidateLifetime = true
};
});
//CORS policy
services.AddCors(options =>
options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin()));
error
Policies for CORS can be a bit finicky. So I would recommend maybe trying for a pretty open CORS policy (Which isn't too dangerous given you are using header authentication and not a cookie).
So your configure services method should look like so :
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
And then your Configure method should be something like :
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors( options => options.WithOrigins("http://example.com").AllowAnyMethod() );
app.UseMvc();
}
Note that the order inside the Configure method is important. The call to CORS must be relatively early on, if not the first middleware in your pipeline.
If that works, then work backwards to slowly add policies and see which one breaks. CORS can be really finicky so it works better to allow everything in a basic example and then add thing slowly in.
More reading here : https://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/

Access to fetch from origin has been blocked by CORS policy, server api already supports middleware

I'm trying to get my ReactJS app (on an AWS S3 machine) PUT request working with my Server API (on an AWS Windows EC2 machine). Seems I am being tripped up by the preflight message that is being sent out. I've been searching on how to handle this and came across these two stackoverflow posts:
Enable OPTIONS header for CORS on .NET Core Web API
How to handle OPTION header in dot net core web api
I've ensured IIS accepts the OPTIONS verb and have added the middleware described. I can see the OPTIONS preflight handling being called through the logging but for some reason I am still getting the CORS error. Listed the main sections of the code below, any help would be really appreciated.
ReactJS PUT request
var myHeaders = new Headers();
myHeaders.append('Accept', 'application/json');
myHeaders.append('Content-Type', 'application/json-patch+json');
var rawObject = {
Name: this.state.recipeEdit.name,
Type: this.state.recipeTypeEdit,
Description: this.state.recipeEdit.description,
Ingredients: this.state.recipeIngredients,
Steps: this.state.recipeSteps,
};
var requestOptions = {
method: 'PUT',
headers: myHeaders,
body: JSON.stringify(rawObject),
redirect: 'follow',
};
fetch(this.state.url, requestOptions)
.then((response) => response.json())
.then((data) => {
this.setState({ recipeDetail: data });
});
Middleware Class
public class OptionsMiddleware
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly RequestDelegate _next;
public OptionsMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
return BeginInvoke(context);
}
private Task BeginInvoke(HttpContext context)
{
if (context.Request.Method == "OPTIONS")
{
log.Error("Handling the OPTIONS preflight message");
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["Origin"] });
context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
context.Response.StatusCode = 200;
return context.Response.WriteAsync("OK");
}
log.Error("Invoking message");
return _next.Invoke(context);
}
}
public static class OptionsMiddlewareExtentions
{
public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
{
return builder.UseMiddleware<OptionsMiddleware>();
}
}
CORS Configuration in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
log.Error("Entered ConfigureServices");
try
{
#if DEBUG
services.AddCors();
#else
services.AddCors(o => o.AddPolicy("MyCorsPolicy", builder =>
{
builder.SetIsOriginAllowed((host) => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));
#endif
services.AddControllersWithViews().AddNewtonsoftJson();
services.AddControllersWithViews(options =>
{
options.InputFormatters.Insert(0, GetJsonPatchInputFormatter());
});
services.AddMvc(options => options.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddMvc(options => options.Filters.Add(typeof(homebakeExceptionFilter)));
#if USE_SQLITE
log.Error("Using SQLITE");
services.AddDbContext<SqliteDbContext>(options =>
{
options.UseSqlite("Data Source=./homebake.db");
});
#else
services.AddDbContext<AppDbContext>(options =>
{
options.UseInMemoryDatabase("homebakeapp-api-in-memory");
});
#endif
log.Error("Adding services");
services.AddScoped<IIngredientRepository, IngredientRepository>();
services.AddScoped<IRecipeStepRepository, RecipeStepRepository>();
services.AddScoped<IRecipeRepository, RecipeRepository>();
services.AddScoped<IIngredientService, IngredientService>();
services.AddScoped<IRecipeStepService, RecipeStepService>();
services.AddScoped<IRecipeService, RecipeService>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
log.Error("Adding auto mapper");
services.AddAutoMapper(typeof(Startup));
}
catch (System.Exception ex)
{
log.Error(ex.Message);
if (ex.InnerException != null )
log.Error(ex.InnerException);
}
}
private static NewtonsoftJsonPatchInputFormatter GetJsonPatchInputFormatter()
{
var builder = new ServiceCollection()
.AddLogging()
.AddMvc()
.AddNewtonsoftJson()
.Services.BuildServiceProvider();
return builder
.GetRequiredService<IOptions<MvcOptions>>()
.Value
.InputFormatters
.OfType<NewtonsoftJsonPatchInputFormatter>()
.First();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddLog4Net();
log.Error("Entered Configure");
app.UseOptions();
#if DEBUG
app.UseCors(options => options.WithOrigins("http://localhost:3000").AllowAnyMethod().AllowAnyHeader());
#else
log.Error("Using cors policy");
app.UseCors("MyCorsPolicy");
#endif
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
//app.use
app.UseHttpsRedirection();
log.Error("Using MVC");
app.UseMvc();
}
I have seen this error when the server-side CORS settings are set using both the web.config and in the code, like in your middleware, which at runtime results in duplicates and cause this type of behavior. Also, you may want to add the following to your web.config and see if it helps. This will ensure your CORS settings are only set by the code.
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Headers" />
<remove name="Access-Control-Allow-Methods" />
<remove name="Access-Control-Allow-Origin" />
</customHeaders>
</httpProtocol>
In the end the issue was to do with IIS configuration. After more searching I found the solution here:
How do I enable HTTP PUT and DELETE for ASP.NET MVC in IIS?
Essentially I had to update the ExtensionlessUrlHandler-Integrated-4.0 setting to accept the PUT and DELETE verbs (access it from the Handler Mappings option in IIS) and also disable both the WebDav module and handler. After that the requests went through and were processed correctly. I'm also still running the Middleware code as detailed above in case anyone else ever comes across this issue.
What made me look at the IIS configuration was that I got the multiple entries for Access-Control-Allow-Origin if I added it to my web.config file, if so, how could it be missing when not included there. Big thanks to #Masoud Safi for al the help he gave on this too.

Enabling CORS in asp.net core

I created a simple api in .net core and trying to access that from react app, I get a CORS error. I enabled cors by following CORS with default policy and middleware section on
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1
still I get cors error in my react app. not exactly sure where I am getting it wrong.
.net core api
namespace React_NalONE_API
{
public class Startup
{
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
// options.AddPolicy(name: MyAllowSpecificOrigins,
// builder =>
// {
// builder.WithOrigins("http://localhost/*",
// "https://localhost/*");
// });
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("http://localhost/*",
"https://localhost/*");
});
});
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireCors(MyAllowSpecificOrigins);
});
}
}
}
React app
componentDidMount () {
console.log("The component is now mounted")
this.setState({loading : true})
fetch('https://localhost:44391/agency')
.then(data => data.json())
.then(data => this.setState({data, loading : false}))
}
error
Access to fetch at 'https://localhost:44391/agency' 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.
Your help is much appreciated
Thanks
R
From the document, you could know that:
Note: The specified URL must not contain a trailing slash (/). If the
URL terminates with /, the comparison returns false and no header is
returned.
For your requirement,it seems you want to allow CORS requests from all origins with any scheme (http or https),I suggest that you could use AllowAnyOrigin:
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.AllowAnyOrigin();
});
});
Reference:
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1#cors-with-named-policy-and-middleware
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1#set-the-allowed-origins
Another way is to change like below:
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("https://localhost:44391",
"http://localhost:44391");
});
});

Resources