skip to Main Content

I’m working on a project using an ASP.NET Web API as the backend, and a create-react-app webpage as the frontend, and I can’t get them to communicate anymore. No matter what I try, I constantly get CORS errors. They didn’t seem to occur in live (i.e. with the API and Website both on IIS) but in development they refuse to work. It used to work a few days ago, but after making some changes to get it to work on IIS, it refuses to work locally using Kestrel anymore.

Every time I try to use a request from the React side (I’m using Axios.request for HTTP requests) I get Access to XMLHttpRequest at 'https://localhost:7046/api/<insert route here>' from origin 'http://localhost:3000' 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 tried using CORS Unblock from the Chrome Web Store in Microsoft Edge but this just changes it to Response to preflight request doesn't pass access control check: It does not have HTTP ok status. I know the route should be working as the exact same thing works using Postman, but in browser it just fails.

Program.cs:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using NLog;
using NLog.Web;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.EntityFrameworkCore;
using System.Configuration;

namespace MyNewAPI
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
            logger.Debug("API starting...");
            try
            {
                var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

                var builder = WebApplication.CreateBuilder(args);
                builder.Services.AddCors(options =>
                {
                    options.AddPolicy(name: "_myAllowSpecificOrigins",
                        policy =>
                        {
                            policy.WithOrigins("http://localhost:3000")
                                .WithMethods("PUT", "DELETE", "GET");
                        });
                });
                // Add services to the container.
                builder.Services.AddSqlServer<Context1>(builder.Configuration.GetConnectionString("DefaultConnection"), o => o.CommandTimeout(3600));
                builder.Services.AddSqlServer<Context2>(builder.Configuration.GetConnectionString("AbelConnection"), o => o.CommandTimeout(3600));
                builder.Services.AddMySql<MySqlContext>(builder.Configuration.GetConnectionString("MilogConnection"), ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("MilogConnection")));
                builder.Services.Configure<DatabaseSettings>(builder.Configuration.GetSection("MongoConnection"));
                builder.Services.AddSingleton<VMFarmService>();
                builder.Services.AddControllers();
                // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                builder.Services.AddEndpointsApiExplorer();
                builder.Services.AddSwaggerGen();

                builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = builder.Configuration["Jwt:Issuer"],
                        ValidAudience = builder.Configuration["Jwt:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"]))
                    };
                });

                builder.Logging.ClearProviders();
                builder.Host.UseNLog();


                var app = builder.Build();

                // Configure the HTTP request pipeline.
                if (app.Environment.IsDevelopment())
                {
                    app.UseSwagger();
                    app.UseSwaggerUI();
                }
                app.UseRouting();
                //app.UseHttpsRedirection();

                app.UseCors();
                app.UseAuthentication();

                app.UseAuthorization();


                app.MapControllers();

                app.Run();
            }
            catch (Exception exception)
            {
                // NLog: catch setup errors
                logger.Error(exception, "Stopped program because of exception:");
                throw;
            }
            finally
            {
                // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
                NLog.LogManager.Shutdown();
            }
        }
    }
}

Axios request in react:

import axios from 'axios';

const MyAPI = {

  async getToken() {
    const data = JSON.stringify({
      clientKey: process.env.REACT_APP_API_KEY,
      clientSecret: process.env.REACT_APP_API_SECRET
    });

    const config = {
      method: "post",
      maxBodyLength: Infinity,
      withCredentials: false,
      url: process.env.REACT_APP_API_BASE_URL + "/api/Authorize/token",
      headers: {
        "Content-Type": "application/json"
      },
      data: data
    };

    const response = await axios.request(config);
    return response.data.token;
  },
}

export default MyAPI;

EDIT:

For testing I changed the builder Cors section to the below (I know this is insecure, figure this should let anything through then I can tighten it down before moving off my dev environment):

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

                var builder = WebApplication.CreateBuilder(args);
                builder.Services.AddCors(options =>
                {
                    options.AddPolicy(name: MyAllowSpecificOrigins,
                                      policy =>
                                      {
                                          policy.AllowAnyOrigin()
                                          .AllowAnyMethod()
                                          .AllowAnyHeader();
                                      });
                });

I also added MyAllowSpecificOrigins to app.UseCors()but it made no difference.

3

Answers


  1. Chosen as BEST ANSWER

    thanks for the answers.

    Turns out all along the issue was due to user error. I'd entered the wrong value in the [EnableCors("_myAllowSpecificOrigins")] sections in my controllers meaning it was trying to load a policy that didn't exist!

    Just in case anyone else runs into the same issue I did, make sure that in the speech marks in the above line that it matches the name of your policy in Program.cs.


  2. You need to specify the name of the Policy in the app.UseCors. There are 2 overloads also for this method : string policyName and Action configurePolicy

    You can either change you app.UseCors() to

    app.UseCors("_myAllowSpecificOrigins") 
    

    or you can apply the cors policy builder

    app.UseCors(x => x.WithOrigins("http://localhost:3000")
                   .AllowAnyMethod()
                   .AllowAnyHeader());
    

    You can when the code moves to prod remove the Cors configuration or have a setting that can be changed when in development or in Production

    if(isDev)
     app.UseCors("_myAllowSpecificOrigins") 
    
    Login or Signup to reply.
  3. Based on your scenario and configuration, please set following property to true within your launchsettings.json file in order to respond preflight request accordingly.

     "windowsAuthentication": true,
     "anonymousAuthentication": true,
    

    Define Request Header:

      headers: {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": "*"
          },   
    

    Note: Or you can set like this "Access-Control-Allow-Origin": "http://localhost:3000"

    Configure CORS:

    var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
        builder.Services.AddCors(options =>
        {
            options.AddPolicy(name:MyAllowSpecificOrigins,
                builder =>
                {
                    builder.WithOrigins("http://localhost:3000")
                    .WithMethods("PUT", "DELETE", "GET");
                });
        });
    

    Use Middleware Reference:

    app.UseCors("MyAllowSpecificOrigins")
    

    Note: Please refer to this official document for CORS middleware configuration

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search