I have a Blazor server application (running .NET 8) which I've put in an Azure Container which in turn is accessed via URL that is routed through HAProxy that also handled TLS termination, this application should have Entra ID authentication.
I have the following code for the authentication bits:
var builder = WebApplication.CreateBuilder(args);
var scopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes");
string[] initialScopes = scopes!.Split(' ');
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph("https://graph.microsoft.com/v1.0", scopes)
.AddInMemoryTokenCaches();
builder.Services.AddHttpContextAccessor();
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
And then in the app part:
var app = builder.Build();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto |
ForwardedHeaders.XForwardedHost
});
The AzureAd section in my appsettings.json looks like this:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "My Company",
"TenantId": "123456-7894-123456789-123456",
"ClientId": "234567-2345-345678912-321256",
"ClientSecret": "AAAAAAAAAAAbbbbbbbbbCCCCCCCdddddd",
"CallbackPath": "/signin-oidc"
},
I have the URL I have to use is something like this https://my.company.internal/theapp
If I navigate to that path I get to the start page and if I hit the login button I get the Entra Id login screen. Upon successful login though it throws a completely different redirect URL back in my face as an error stating that the redirect URL https://theapp_ca.myazurecontainerenv.containerapps.com/signin-oidc
isn't in the valid redirect URL list, which it isn't, but I thought that would've been taken care of by using the ForwardedHeaders.XForwardedHost
so it would redirect me to the https://my.company.internal/theapp/signin-oidc
which would happily accept the sign-in ticket.
It's taken me days now to try to find anything online and the ForwardedHeaders was the only thing I found that pointed me in the right direction (or so I thought).
So, is there a way to get this to work or is it simply impossible to use Entra ID authentication in Azure Container apps using Blazor and HAProxy?
Note, this works fine if I test it on my local dev machine and if I push it to a local docker file, but not on ACA with HaProxy.
For future reference and if someone else stumbles on the same problem.
The forwarded headers needed to be implemented like:
var forwardedHeadersOptions = new ForwardedHeadersOptions {
ForwardedHeaders = ForwardedHeaders.XForwardedHost |
ForwardedHeaders.XForwardedProto };
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);
Make sure this comes right below your Build() or atleast before anything that will make use of these parameters.
I have since added the allowed proxy server IP to it as well for security purposes.
In my specific case, the X-Forwarded-Proto isn't being sent from HA Proxy, so in order to get that to work (until the HA Proxy team fixes it) I'm using this:
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
Not sure if this is of any use to anyone, but it stopped my hairs from turning gray and it's working now. In the near future the last piece of code will be removed once the X-Forwarded-Proto is sent correctly, but for testing purposes right now it stays.