I have a Blazor page that makes use of the [Authorize] attribute to trigger challenge with Discord OAuth2 flow.
@page "/mypage"@using Microsoft.AspNetCore.Authorization@attribute [Authorize]@rendermode InteractiveServerThe redirect_uri that is generated for OAuth2 authorisation redirect is using http as the Scheme when the site is sitting behind a TLS terminating load balancer. The general resolution to this issue is to configure X-Forwarded-Proto header at the load balancer and apply UseForwardedHeaders in the WebApplication builder. However, with the Authorize attribute this does not have any affect. In fact the entire pipeline seems to not be executed in the assessment of the Authorize policy and the user is redirected to the OAuth2 authorisation endpoint before any of the pipeline executes.
var builder = WebApplication.CreateBuilder(args);builder.Configuration.AddConfiguration(config);//...builder.Services.Configure<ForwardedHeadersOptions>(options =>{ options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; options.KnownNetworks.Clear(); options.KnownProxies.Clear();});builder.Services .AddAuthentication(DiscordOptions.AuthenticationScheme) .AddCookie() .AddDiscord(x => { x.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; x.ClientId = config.GetValue<string>("Discord:ClientId")!; x.ClientSecret = config.GetValue<string>("Discord:ClientSecret")!; var scopes = config.GetSection("Discord:Scopes").Get<string[]>(); if (scopes is not null) x.WithClaims(scopes); var prompt = config.GetValue<string>("Discord:Prompt"); if (prompt is not null) x.WithPrompt(prompt); });var app = builder.Build();// todo: AuthorizeAttribute challenge seems to be executed before this pipelineapp.Use((ctx, next) =>{ // This is not hit Debugger.Break(); return next();});app.UseForwardedHeaders();if (!app.Environment.IsDevelopment()){ app.UseHttpsRedirection(); app.UseExceptionHandler("/Error", createScopeForErrors: true); app.UseHsts();}app.UseAntiforgery();app.UseStaticFiles();app.MapControllers();app.MapRazorComponents<App>() .AddInteractiveServerRenderMode();await app.Services.GetService<IdentityDbContext>()!.Database.MigrateAsync();app.Run();I've tried adding UseAuthorization and UseAuthentication manually into the pipeline in hope to control the ordering it is applied but this is ignored.
I've verified the configuration of the ForwardedHeader options by hitting on non-AuthorizeAttributed page and debugging through the .NET code. I can see the headers coming in and the HttpContext.Request.Scheme subsequently being changed.
I've debugged the builder to see if the resultant app has more middleware defined than I have provided (maybe as a side effect of Service and Feature registrations?), but can see only my middleware is registered as expected, not any AuthorizeMiddleware.
I can see the pipeline is not being executed at all by adding dummy middleware at the top of the pipeline and I do not see it hit at all when hitting a page with AuthorizeAttribute. In debugging how it is calling the DiscordOptions and DiscordCallbackHandler to build the redirect Uri, I can see there is a pipeline (with AuthorizationMiddleware) being iterated through in the .NET http request handling but it seems to be completely separate Filter popeline, and not my own defined pipeline. The pipeline is indeed being executed for any requests not annotated by the AuthorizeAttribute.