Closed brgrz closed 6 days ago
This looks similar to #57650
Can you include the trace-level ASP.NET Core logs from the ForwardedHeadersMiddleware
?
You might be running into an issue because the middleware verifies that the client claiming to be the proxy has the expected remote IP address as noted in the doc's troubleshooting section.
The request's original remote IP must match an entry in the
KnownProxies
orKnownNetworks
lists before forwarded headers are processed. This limits header spoofing by not accepting forwarders from untrusted proxies. When an unknown proxy is detected, logging indicates the address of the proxy:dbug: Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware[1] Unknown proxy: [::ffff:10.0.0.100]:54321
By default, KnownProxies
and KnownNetworks
only contain [::1]
and 127.0.0.0/8
respectively. I'm a little surprised that this only gets checked when ForwardedHeaders.XForwardedFor
is selected and not ForwardedHeaders.XForwardedProto
, but being able to spoof the scheme does seem like less of a security risk than being able to spoof a remote IP address.
If you know the IP address or subnet of the reverse proxy, I recommend adding it to KnownProxies
or KnownNetworks
. Otherwise, you can clear both lists to skip the check, but you need to beware that any client that can open a connection to your backend server will be able to spoof their IP address.
Another option is to set the ASPNETCORE_FORWARDEDHEADERS_ENABLED
environment variable to true or otherwise set the "ForwardedHeaders_Enabled" IConfiguration
to true.
To forward the scheme from the proxy in non-IIS scenarios, enable the Forwarded Headers Middleware by setting
ASPNETCORE_FORWARDEDHEADERS_ENABLED
totrue
. Warning: This flag uses settings designed for cloud environments and doesn't enable features such as theKnownProxies option
to restrict which IPs forwarders are accepted from.
If you do this, you will no longer need to call Configure<ForwardedHeadersOptions>(...
or app.UseForwardedHeaders();
yourself. WebApplicationBuilder
will set that up for you when it sees the "ForwardedHeaders_Enabled" config.
Hi @brgrz. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
Another option is to set the
ASPNETCORE_FORWARDEDHEADERS_ENABLED
environment variable to true or otherwise set the "ForwardedHeaders_Enabled"IConfiguration
to true.To forward the scheme from the proxy in non-IIS scenarios, enable the Forwarded Headers Middleware by setting
ASPNETCORE_FORWARDEDHEADERS_ENABLED
totrue
. Warning: This flag uses settings designed for cloud environments and doesn't enable features such as theKnownProxies option
to restrict which IPs forwarders are accepted from.
I chose this option and indeed it solved the issue when redirect_uri was made with http scheme. It now includes the correct, https, scheme in redirect_uri.
I wish this was more clearly documented but I know it is hard bc there might be many moving parts in each different hosting configuration and/or cloud provider. I do think this section NGINX configuration and the section you linked to should be placed together in docs and also, very important, maybe differences be pointed out more clearly and also it couldn't hurt if specifically Kubernetes, AKS or ingress were mentioned because atm it stands out that it talks about Azure Linux App Service, Azure Linux VM and when as a reader you see that you immediatelly skip it and look elsewhere, thinking it is not your use case.
If you do this, you will no longer need to call
Configure<ForwardedHeadersOptions>(...
orapp.UseForwardedHeaders();
yourself.WebApplicationBuilder
will set that up for you when it sees the "ForwardedHeaders_Enabled" config.
I can confirm this, I was able to removed those lines and it still works.
While at it, if anyone else stumbles across this issue, after the redirection starts to work you might also run into 502 Bad Gateway at the nginx side with upstream sent too big header while reading response header from upstream issue in the nginx ingress logs. This is another piece of the problem which took some time from me thinking it was application related but it is not. The solution is to configure ingress annotations like so:
## Fixed the ingress issue of "upstream sent too big header while reading response header from upstream" by setting ingress buffer size
nginx.ingress.kubernetes.io/proxy-buffer-size: 256k
refer to the nginx ingress annotations for more info https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md
Is there an existing issue for this?
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
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