-1

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?

enter image description here

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
        }
    }
Andrew
  • 2,571
  • 2
  • 31
  • 56
  • Q: What do I need to get this working? A: Read this: [Enable Cross-Origin Requests (CORS) in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/cors). Then try this: https://stackoverflow.com/a/44379971/421195 – paulsm4 Sep 01 '21 at 19:13
  • 2
    Does this answer your question? [How to enable CORS in ASP.net Core WebAPI](https://stackoverflow.com/questions/44379560/how-to-enable-cors-in-asp-net-core-webapi) – Batuhan Sep 01 '21 at 19:23
  • The first link Is what I was going through, nowhere does it mention UseMvc() yet the later link does. When I add UseMvc() it states that "it is not supported whilst using endpoint routing" – Andrew Sep 01 '21 at 19:24

1 Answers1

1

I moved the middleware lines below the app.UseCors(...) line and it seems to work now!

app.UseMiddleware<ApiKeyMiddleware>(); // All request will need an ApiKey
app.UseMiddleware<UserTokenMiddleware>(); // All request but the /login and /swagger urls will need a UserToken

I can now actually get to the swagger page, whereas before it was unable to get to the swagger page too. The ordering is something that always seems confusing.

Andrew
  • 2,571
  • 2
  • 31
  • 56