tl;dr:
CLIENT -----------> GATEWAY (https) -----------> APP (http)
/callback
ishttp://
but being redirected tohttps://
in order to protect it / funnel it through the gateway; however, there’s an error processing the callback endpoint in the APP (shown below)
I’ve got a Service Fabric application that’s hosting an asp.net core site which is sitting behind an Application Gateway that I am using to provide TLS for the application as a whole. The gateway provides a place to manage TLS certs and forwards requests on to the underlying application / site via plain http.
Within the site itself, I’ve mostly followed the quickstart guide. For reference, here are the relevant portions of ConfigureServices
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.CookieOptions);
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("Auth0", options =>
{
options.Authority = $"https://{Settings.Auth.Domain}";
options.ClientId = Settings.Auth.ClientId;
options.ClientSecret = Settings.Auth.ClientSecret;
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Clear();
options.Scope.Add("openid");
options.ClaimsIssuer = "Auth0";
options.CallbackPath = PathString.FromUriComponent("/callback");
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = Settings.Auth.RoleClaimType
};
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage.RedirectUri = Settings.Auth.RedirectUri;
return Task.FromResult(0);
},
OnRedirectToIdentityProviderForSignOut = (context) =>
{
var logoutUri = $"https://{Settings.Auth.Domain}/v2/logout?client_id={Settings.Auth.ClientId}";
var postLogoutUri = context.Properties.RedirectUri;
if (!string.IsNullOrEmpty(postLogoutUri))
{
if (postLogoutUri.StartsWith("/"))
{
var request = context.Request;
postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
}
logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
}
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
}
};
});
Note the inclusion of OnRedirectToIdentityProvider
that is used to provide a configuration driven redirect uri - this is, in practice, replacing the http://
protocol with https://
.
Additionally, in an attempt to use forwarded headers, I’ve included this to the Configure
method
var forwardOpts = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor
};
forwardOpts.KnownNetworks.Clear();
forwardOpts.KnownProxies.Clear();
app.UseForwardedHeaders(forwardOpts);
Per the documentation on the Azure Application Gateway the appropriate headers are meant to be included:
Modifications to the request
An application gateway inserts four additional headers to all requests before it forwards the requests to the backend. These headers are x-forwarded-for, x-forwarded-proto, x-forwarded-port, and x-original-host. The format for x-forwarded-for header is a comma-separated list of IP:port.
However, even with this configuration, authentication is still failing. The client is redirected to the appropriate https://
callback endpoint, but is met with a 500.
Are there any ways to work around this, or am I perhaps setting something up incorrectly?
edited for additional information
I’ve also attempted to perform this http://
to https://
redirect using the following code in Configure
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
which I’ve used instead of replacing the RedirectUri
in OnRedirectToIdentityProvider
- but this results in the same exception shown above. This happens both with and without the UseForwardedHeaders
snippet from above.