I have two services running on Azure :
- a web service ( angular app / expressjs )
- an app service ( aspnet core app )
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
Any hints ? Thanks