Link to home
Start Free TrialLog in
Avatar of Robb Hill
Robb HillFlag for United States of America

asked on

CORS Error on preflight request with .net core api and Angular hosted in Azure.

I am getting the following CORS error:


Access to XMLHttpRequest at 'https://my.netcore.api' from origin 'myAngularWebsite' 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.



This is a .net core 5 api.

This is angular 12 UI.

The .net core app is hosted in a VM on Azure.

The Angular app is hosted in Azure Storage as a Static website and further configured on AzureCDN.


I have the cors rules defined in my startup in the .net API.


What else is there to do.


Whats interesting here as well as this does not happen until after we authenticate through a 3rd party company.  The content though its been authenticated is loading the same angular page. but now blocking content due to this error

Avatar of Robb Hill
Robb Hill
Flag of United States of America image

ASKER

More detail.  We use a product called F5 in our network.

This website has a .net API in between the F5 and the public angular website.

I was able to have our network team remove the blocking on  the header "OPTIONS"" and this worked however I am being told to manage this in code as our network /security team doesnt want this open on the LB.


Please help.  


Here is my startup.cs in .net core api.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ACES.API.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Azure.Storage.Blobs;
using ACES.API.Data;
using ACES.API.Helper;
using Microsoft.AspNetCore.HttpOverrides;

namespace ACES.API
{
    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)
        {
            var roles = new string[1];


            services.AddCors();

            services.AddDbContext<Acesdbcontext>(options =>
                    options.UseSqlServer(Configuration["ConnectionStrings:DevConnection"]),
                ServiceLifetime.Transient);
            services.AddAutoMapper(typeof(Startup));
            services.AddScoped(typeof(IDataRepository<>), typeof(DataRepository<>));
            services.AddScoped(x => new BlobServiceClient(Configuration.GetValue<string>("AzureBlobStorage")));
            services.AddScoped<IBlobService, BlobService>();
            services.AddScoped<CheckAuthToken>(x => new CheckAuthToken(roles));
            services.AddLogging();


            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "GPI.ACES.API", Version = "v1" });
            });


            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)
        {
            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.All
            });

            if (env.IsDevelopment() || (env.IsStaging()))
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "GPI.ACES.API v1"));
            }

            app.UseHttpsRedirection();

            app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}



Open in new window

Robb, I have only just started to move towards .NET myself. But I believe what you are looking for is in the example below. Note that you can use localhost.

https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-6.0
User generated image

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: "MyPolicy",
                builder =>
                {
                    builder.WithOrigins("http://example.com",
                        "http://www.contoso.com",
                        "https://cors1.azurewebsites.net",
                        "https://cors3.azurewebsites.net",
                        "https://localhost:44398",
                        "https://localhost:5001")
                            .WithMethods("PUT", "DELETE", "GET");
                });
});

Open in new window

So that's only put. Get.  And delete.   I think you have to do something to handle OPTIONS.   Also I'm wondering if you need to decorate all of the api calls with something 
That is just the example. I don't have this set up to test right now.  Try it with just WithOrigins in the same documentation.  This is just for testing.

User generated image
I am still having an issue with this.

Here is current startup file.  I feel like I have done everything from the documentation.

So when I load my site it loads up a products page first.
When I login it also loads up the same page first..but I get this error

Origin 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 am allowing all origins that end in my domain.  I am a allowing any header and any type...so not sure Why OPTIONS is failing nor why this header is an issue.

I know my company firewall blocks this request type of OPTIONS but I was told I should handle this in code...I am not sure what  else I can do.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ACES.API.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Azure.Storage.Blobs;
using ACES.API.Data;
using ACES.API.Helper;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Net.Http.Headers;

namespace ACES.API
{
    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)
        {
            var roles = new string[1];


      
            services.AddCors(options =>
            {
                options.AddDefaultPolicy(
                    builder =>
                    {
                        builder.WithOrigins("https://*.graphicpkg.com")
                                                          .AllowAnyHeader()
                                                          .AllowAnyMethod()
                                                          .SetPreflightMaxAge(TimeSpan.FromSeconds(86400));
                    });

            });

           



            services.AddDbContext<Acesdbcontext>(options =>
                    options.UseSqlServer(Configuration["ConnectionStrings:DevConnection"]),
                ServiceLifetime.Transient);
            services.AddAutoMapper(typeof(Startup));
            services.AddScoped(typeof(IDataRepository<>), typeof(DataRepository<>));
            services.AddScoped(x => new BlobServiceClient(Configuration.GetValue<string>("AzureBlobStorage")));
            services.AddScoped<IBlobService, BlobService>();
            services.AddScoped<CheckAuthToken>(x => new CheckAuthToken(roles));
            services.AddLogging();


            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "GPI.ACES.API", Version = "v1" });
            });


            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)
        {
            //app.UseForwardedHeaders(new ForwardedHeadersOptions
            //{
            //    ForwardedHeaders = ForwardedHeaders.All
            //});

            if (env.IsDevelopment() || (env.IsStaging()))
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "GPI.ACES.API v1"));
            }
           

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseCors();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}



Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Robb Hill
Robb Hill
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial