DarkUrse
DarkUrse

Reputation: 2278

azure removes Access-Control-Allow-Origin header returned from my app service

I have two services running on Azure :

All the web service does is query the app service for the following endpoint : my-app-service.azurewebsites.net/.well-known/openid-configuration

My app service is setup to allow CORS requests coming from my web service at the code level via the IdentityServer4 dll and as mentioned in many websites I DID ensure CORS settings were neither overridden by web.config or azure CORS management page.

These are my HTTP request headers :

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Host:my-app-service.azurewebsites.net
Origin:http://my-web-service.azurewebsites.net
Pragma:no-cache
Referer:http://my-web-service.azurewebsites.net/

And these are my HTTP response headers

Content-Encoding:gzip
Content-Type:application/json
Date:Fri, 05 Jan 2018 17:22:53 GMT
Server:Kestrel
Set-Cookie:ARRAffinity=da4c4ff244aae03ae3c7548f243f7c2b5c22567a56a76a62aaebc44acc7f0ba8;Path=/;HttpOnly;Domain=Host:my-app-service.azurewebsites.net
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Powered-By:ASP.NET

As you can see, none of the Access-Control-* headers are present. I have added a custom middleware to the asp.net core app pipeline to trace the response headers and I can clearly see them present.

So somewhere Azure is stripping off my headers and I have no more clues where to look now.


Update #1

I forgot to specify that if everything runs on localhost, it works fine. But it does not on Azure.

Update #2

My identity server 4 code

[...]
using Microsoft.IdentityModel.Tokens;
using IdentityServer4.EntityFramework.Mappers;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4;

namespace My.IdentityServer4
{
    public class Startup
    {
        private const string DEFAULT_DEVELOPMENT_AUTHORITY = "http://localhost:5000/";

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            // [... add db context. identity framework, default token provider]
            services.AddMvc();

            // Cors ( not required, identity server 4 manages it internally )
            //services.AddCors(options =>
            //    options.AddPolicy("AllowAllOrigins", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()));

            string connectionString = Configuration.GetConnectionString("SQLServer");
            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

            // configure identity server with in-memory stores, keys, clients and scopes
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddAspNetIdentity<ApplicationUser>()
                // this adds the config data from DB (clients, resources)
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                // this adds the operational data from DB (codes, tokens, consents)
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));

                    // this enables automatic token cleanup. this is optional.
                    options.EnableTokenCleanup = true;
                    options.TokenCleanupInterval = 30;
                });

            services.AddAuthentication()
                .AddOpenIdConnect("oidc", "OpenID Connect", options =>
                {
                    //TODO: enable HTTPS for production
                    options.RequireHttpsMetadata = false;
                    options.Authority = DEFAULT_DEVELOPMENT_AUTHORITY;
                    options.ClientId = "app"; // implicit
                    options.SaveTokens = true;
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        NameClaimType = "name",
                        RoleClaimType = "role"
                    };
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            // [... Some stuff before not useful for this snippet]

            // For debug purposes, print out request and response headers
            app.UseMiddleware<LogHeadersMiddleware>();

            app.UseStaticFiles();

            // Cors ( not required, identity server 4 manages it internally )
            //app.UseCors("AllowAllOrigins");

            app.UseIdentityServer();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }



    public class LogHeadersMiddleware
    {
        private readonly RequestDelegate next;
        private readonly ILogger<LogHeadersMiddleware> logger;

        public LogHeadersMiddleware(RequestDelegate next, ILogger<LogHeadersMiddleware> logger)
        {
            this.next = next;
            this.logger = logger;
        }

        public async Task Invoke(HttpContext context)
        {
            await this.next.Invoke(context);

            logger.LogInformation(
                $"------------------------\r\n" +
                $"*** Request headers ****\r\n" +
                string.Join("\r\n", context.Request.Headers.OrderBy(x => x.Key)) + "\r\n" +
                $"*** Response headers ***\r\n" +
                string.Join("\r\n", context.Response.Headers.OrderBy(x => x.Key)) + "\r\n" +
                $"------------------------\r\n");

        }
    }
}

Update #3 - CORS on Azure service app is not set

No CORS configured on Azure

Any hints ? Thanks

Upvotes: 2

Views: 2629

Answers (2)

DarkUrse
DarkUrse

Reputation: 2278

@NoName found the answer to my issue on this thread.

In a nutshell, https has to be enabled on Azure in order to work.

A warning from Azure in the logs would have been appreciated though. I wouldn't have lost days on this :S

Upvotes: 2

Tom Sun
Tom Sun

Reputation: 24569

CORS on Azure service app is not set.

Actually, Azure website is supposed to manage CORS for you. You just need to set the CORS on the Azure service App. I also find a similar SO thread about it.

The good thing is that you can completely disable this middleware and manage CORS by your own means, you just have to remove every single allowed origin (including *) from the CORS settings blade in the portal.

enter image description here

Upvotes: 1

Related Questions