Reputation: 1734
I have a .Net Core 3.1 application that is hosted in AWS behind an https load balancer. To the outside world it is an https site, but to AWS internally it runs on http behind the balancer.
Because of this the OpenID Connect middleware is redirecting to the HTTP path instead of HTTPS.
Is there anyway to force OpenId Connect to use https pathing?
.AddOpenIdConnect("oidc", options =>
{
var oauthConfig = Configuration.GetSection("OAuthConfiguration").Get<OAuthConfiguration>();
options.Authority = oauthConfig.Authority;
options.ClientId = oauthConfig.ClientId;
options.ClientSecret = oauthConfig.ClientSecret;
options.ResponseType = "code";
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.CallbackPath = "/signin-oidc";
When the authorization request is made this generates this redirect uri
"RedirectUri": "http://demo.mysite.com/signin-oidc"
I cannot hardcore a path into the CallbackPath
because my application runs multitenancy and the URL is different depending upon routing.
Upvotes: 29
Views: 13913
Reputation: 69918
If you host on AWS, Azure or GCP behind a load balancer you can use the X-Forwarded-For
and X-Forwarded-Proto
headers. This is better in my opinion because then you do not need to edit every service individually. In this case you only need X-Forwarded-Proto
.
Example:
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
app.UseForwardedHeaders();
Complete example:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Sources:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
If you cannot configure forwarded headers you can also modify OpenIdConnectEvents
like the answer from @AurelienBOUDOUX. An alternative solution:
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context =>
{
var uri = context.ProtocolMessage.RedirectUri;
// If it's incorrectly http://, replace with https://
if (uri.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
{
context.ProtocolMessage.RedirectUri = uri.Replace("http://", "https://");
}
return Task.CompletedTask;
}
};
Upvotes: 0
Reputation: 45095
Solution
The answer here is to insert middleware that pretends all requests came in as HTTPS. Works for me.
ASP.NET 5 OAuth redirect URI not using HTTPS
Warning
The following doesn't work. When deployed it causes a "Correlation failed" error, presumably because the URL was tampered with.
This is the complete fix for my website. Note that I'm loading my options from config.
.AddGoogle(options =>
{
this.Configuration.Bind("OAuth2:Providers:Google", options);
options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
options.Events.OnRedirectToAuthorizationEndpoint = MakeHttps;
})
Importantly, this event actually performs the redirect, else you'll get a 200 OK and a blank page.
private Task MakeHttps(RedirectContext<OAuthOptions> arg)
{
// When behind a load balancer the redirect URL, which is configured as CallbackPath in the appsettings.json
// is created as HTTP because the HTTPS request is terminated at the NLB and is forwarded in clear text.
// The policy of most OAuth IDPs is to disallow clear HTTP redirect URLs.
if (!arg.RedirectUri.Contains("redirect_uri=https", StringComparison.OrdinalIgnoreCase))
{
arg.RedirectUri = arg.RedirectUri.Replace("redirect_uri=http","redirect_uri=https", StringComparison.OrdinalIgnoreCase);
}
arg.HttpContext.Response.Redirect(arg.RedirectUri);
return Task.CompletedTask;
}
Upvotes: 0
Reputation: 306
You can force the provider to rewrite your callback url in https like this
option.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProvider = context =>
{
var builder = new UriBuilder(context.ProtocolMessage.RedirectUri);
builder.Scheme = "https";
builder.Port = -1;
context.ProtocolMessage.RedirectUri = builder.ToString();
return Task.FromResult(0);
}
}
Upvotes: 23
Reputation: 29198
The redirect URI should be an HTTPS value:
In terms of multitenancy I would try to avoid interfering with the Open Id Connect login process and instead use the same callback path for all users. That is the standard behaviour, and using things like wildcards in redirect URIs can create security vulnerabilities.
Not sure I fully understand understand your requirements related to multitenancy, so if this doesn't work for you, please post some further details on how you want it to work.
.Net Core has events you can override, such as this one, if the redirect URI needs to be calculated at runtime:
options.Events.OnRedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage.RedirectUri = <load balanced value>;
await Task.FromResult(0);
}
Upvotes: 1