Skip to content

OIDC middleware will not use forwarded headers in challenge construction #58455

Closed
@brgrz

Description

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Having ASP.NET Core application running in a container on Azure Kubernetes Services cluster behind an ingress-nginx with this program.cs

...
			var authOptions = builder.Configuration.GetRequiredOptions<Auth0Options>(Auth0Options.ConfigKey);

			builder.Services
				.AddAuthentication(cfg =>
				{
					cfg.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
					cfg.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
				})
				.AddCookie()
				.AddOpenIdConnect(cfg =>
				{
					cfg.Authority = authOptions.Authority;
					cfg.ClientId = authOptions.ClientId;
					cfg.ClientSecret = authOptions.ClientSecret;
					cfg.ResponseType = "code";
					cfg.UsePkce = true;
					cfg.SaveTokens = true;

					cfg.Scope.Clear();
					foreach (var scope in authOptions.Scopes.Split(" ", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
					{
						cfg.Scope.Add(scope);
					}
				});

			builder.Services.Configure<ForwardedHeadersOptions>(options =>
			{
				options.ForwardedHeaders =
					ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
			});

			var app = builder.Build();

			app.UseForwardedHeaders(new ForwardedHeadersOptions
			{
				ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor
			});

			// mind the order

			// #1
			app.UseAuthentication();

			// #2
			app.Use(async (context, next) =>
			{
				if (context.User.Identity is null || !context.User.Identity.IsAuthenticated)
				{
					// here I verify that correct x-forwarded-* headers are currently present
					Log.Information("Headers: {Headers}", context.Request.Headers);

					await context.ChallengeAsync();
					return;
				}

				await next();
			});

			// #3
			app.UseAuthorization();

			...

I observe that when ChallengeAsync() is called and the redirect is made to Auth0 Identity Provider the redirect_uri inserted into the request URL will lose the https scheme and use http.

Headers:
["[Accept, text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7]", "[Host, hangfire.dev.domain.com]", "[User-Agent, Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0]", "[Accept-Encoding, gzip, deflate, br, zstd]", "[Accept-Language, en]", "[Upgrade-Insecure-Requests, 1]", "[X-Request-ID, a2eae22eec38ed62a5a35cf4bcd0a449]", "[X-Real-IP, ****]", "[X-Forwarded-For, ****]", "[X-Forwarded-Host, hangfire.dev.domain.com]", "[X-Forwarded-Port, 443]", "[X-Forwarded-Proto, https]", "[X-Forwarded-Scheme, https]", "[X-Scheme, https]", "[sec-ch-ua, "Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"]", "[sec-ch-ua-mobile, ?0]", "[sec-ch-ua-platform, "Windows"]", "[DNT, 1]", "[sec-fetch-site, none]", "[sec-fetch-mode, navigate]", "[sec-fetch-user, ?1]", "[sec-fetch-dest, document]", "[priority, u=0, i]"]

https://dev-*.eu.auth0.com/authorize?client_id=v3fq3h4wtaYs71R1q3w0QffYiB4CuqA5&redirect_uri=http%3A%2F%2Fhangfire.dev.domain.com%2Fsignin-oidc&response_type=code&scope=openid%20profile%20email&code_challenge=a7Zle0HiuPZd_RPoSUFjwFKI&code_challenge_method=S256&response_mode=form_post&nonce=638646732839944170&state=XG-uoQem9jrNi028&x-client-SKU=ID_NET8_0&x-client-ver=8.1.2.0

The result is that Auth0 denies the request because URL with a http scheme has not been added into the Allowed redirect URLs with Auth0 (correctly so and won't be added).

The nginx ingress correctly provides the x-forwarded-* headers and those are present in the current context/request. So the app knows that the original request was made to the https scheme and terminated by the nginx proxy which also correctly forwarded this information on.

I found this SO question with an answer that offers a workaround but imo this shouldn't need a workaround, this is a bug within the OIDC flow in ASP.NET Core.

Expected Behavior

The ASP.NET Core OIDC auth provider should construct the redirect_uri query parameter for the OIDC IdP call with the correct/original scheme even though the app is running within the http scheme BUT it is behind a proxy which handles SSL termination (and also enforces https).

Steps To Reproduce

Take a sample ASP.NET Core project and copy the provided code into Program.cs and you'll also need an application registered with one of the OIDC providers (Azure Entra, Auth0, Okta, Keycloak).

Exceptions (if any)

No response

.NET Version

8.0.403

Anything else?

No response

Metadata

Assignees

No one assigned

    Labels

    Needs: Author FeedbackThe author of this issue needs to respond in order for us to continue investigating this issue.area-security

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions