I cant seem to get CORS working with some custom middleware that I have added in a .net core 3.1 web api.
I have found the issues to be middleware that I have implemented, if I comment out the middleware lines then it works but when I put them in it fails:
app.UseMiddleware<ApiKeyMiddleware>(); // All request will need an ApiKey
app.UseMiddleware<UserTokenMiddleware>(); // All request but the /login and /swagger urls will need a UserToken
What do I need to do to get this working?
My code is as follows in the Startup.cs file
public class Startup
{
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.AddDbContext<ReminderContext>(options =>
{
options.UseSqlServer(this.Configuration.GetConnectionString("Reminder"));
});
services.AddCors();
services.AddControllers().AddJsonOptions(opt =>
{
// Added this to support enum strings coming into the api, without it they won't work
opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
services.AddSwaggerGen();
services.AddMediatR(typeof(Startup), typeof(LoginHandler));
// Using AddScoped means that the instance will be the same object for the whole request
// This is good and means the unit of work will exist for the full requests wherever it is used
// Unit of work
services.AddScoped<IUnitOfWork, UnitOfWork>();
// Add Repositories here
services.AddScoped<IUserRepository, UserRepository>();
// Add Business here
services.AddScoped<ILoginBusiness, LoginBusiness>();
services.AddScoped<IUserBusiness, UserBusiness>();
services.AddScoped<IBirthdayBusiness, BirthdayBusiness>();
services.AddSingleton<IPasswordUtility, PasswordUtility>();
}
// 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();
}
// Middleware to intercept requests and check the ApiKey and UserToken
app.UseMiddleware<ApiKeyMiddleware>(); // All request will need an ApiKey
app.UseMiddleware<UserTokenMiddleware>(); // All request but the /login and /swagger urls will need a UserTokena
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
//c.RoutePrefix = string.Empty;
});
app.UseHttpsRedirection();
app.UseRouting();
//var corsUrls = Configuration.GetSection("Cors").Get<string[]>();
app.UseCors(builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
//app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
The ApiKeyMiddleware looks like this:
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, IConfiguration configuration)
{
// Check headers that a header had been passed and it is value
if (!context.Request.Headers.Keys.Contains("ApiKey") ||
context.Request.Headers["ApiKey"] != configuration["Security:ApiKey"])
{
context.Response.StatusCode = 400; //Bad Request
await context.Response.WriteAsync("Invalid request");
return;
}
await _next.Invoke(context); // call next middleware
}
}