openiddict / openiddict-core

Flexible and versatile OAuth 2.0/OpenID Connect stack for .NET
https://openiddict.com/
Apache License 2.0
4.42k stars 516 forks source link

Multi-tier deployment: reverse-proxy support? #2084

Closed EyeAmRoot closed 4 months ago

EyeAmRoot commented 4 months ago

Confirm you've already contributed to this project or that you sponsor it

Version

5.5.0

Question

Hello,

Our application and associated infrastructure uses a multi tier deployment (web layer/app layer/db layer) and openiddict is part of our code that is deployed on our app servers (since it needs db access).

We’ve configured a reverse proxy on the web tier that redirects the requests to the app servers. There is also an outbound rule for each application in OIDC setup. The reason for this is that openiddict produces return urls based on where the request is coming from (in this case it is our web fqdn), so the outbound rule is added to rewrite the return address to the original client application fqdn.

This works for our prototype installation, but it is very hard to scale it (having to write outbound rules for every application).

Sample of our outbound rule (IIS syntax): match: ^https://webserver-fqdn/openid-connect-client-app1/(.*)
rewrite it with: https://application-fqdn1/openid-connect-client-app1/{R:1}

A sample use case: 1- User opens a browser and navigates to: https://application-fqdn1/openid-connect-client-app1 2- User clicks login and redirected to the web server: https://web-server-fqdn/OIDC.Provider/connect/authorize?response_type=... 3- Web server proxies the request to the openiddict provider installed on app server: https://app-server-fqdn/OIDC.Provider/connect/authorize?response_type=code... 4- After user enters correct credentials, the user is redirected to https://web-server-fqdn/openid-connect-client-app1/callback?code=xZ.... 5- Outbound rule changes this to https://application-fqdn1/openid-connect-client-app1/callback?code=xZ....

Is there a setting in openiddict to redirect (in step 4) to the application-fqdn1 rather than the web-server-fqdn?

Are there samples/documents on how to use openiddict on a multi tier environment?

Do you know of a way that we can get away using only one outbound rule? (sort of similar example in how Jenkins documents, how to setup IIS, here): https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-with-jenkins/reverse-proxy-configuration-iis/)

Any help is appreciated.

Thank you.

kevinchalet commented 4 months ago

Hey @EyeAmRoot,

Thanks for sponsoring the project, much appreciated! ❤️

Is there a setting in openiddict to redirect (in step 4) to the application-fqdn1 rather than the web-server-fqdn?

No: OpenIddict deliberately doesn't offer such a setting and exclusively relies on the information extracted from the HttpRequest object: if the request details aren't correct (e.g HttpRequest.Scheme is http instead of https even if the original request used TLS), you'll get bad results such as the scenario you're describing.

This works for our prototype installation, but it is very hard to scale it (having to write outbound rules for every application).

Typical reverse proxy scenarios generally don't need URL rewriting at all (inbound or outbound): what you need to configure correctly in this case is the "forwarded headers" middleware shipping with ASP.NET Core (and enabled by default when using IIS): its mission is to restore the original request details from the standard Forwarded header (or X-Forwarded-For/X-Forwarded-Host/X-Forwarded-Proto, that are the de facto standard headers).

In this case, the original host is not restored so HttpRequest.Host doesn't reflect the "external" host, which is why you're not getting correct URLs via OpenIddict.

I'd suggest reading https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-8.0 to learn more about this feature. You'll want to double-check the KnownNetworks and KnownProxies are correctly configured, it's a common source of pain.

If you're still stuck after reading the official docs, feel free to reach out and I'll post additional details :smiley:

Cheers.

kevinchalet commented 4 months ago

@EyeAmRoot did you have a chance to test that? 😃

EyeAmRoot commented 4 months ago

Hi Kevin,

Thank you for your reply.

Yes, I've been trying to make this work with little success. The openiddict server is part of a code base that is targeting .Net framework 4.8, I've added the middleware changes and found an extension in an online article to use for the missing UseForwardedHeaders method. However the return url is still pointing to the web fqdn.

I have few more things to check and will ask for help if I can't make it to work.

Thank you.

kevinchalet commented 4 months ago

Hey,

I have few more things to check and will ask for help if I can't make it to work.

Please don't hesitate, I'm here to help 😃

Cheers.

kevinchalet commented 4 months ago

Doing some housecleaning, but as always, feel free to reopen if you need additional assistance.

EyeAmRoot commented 2 months ago

Hi Kevin,

We eventually got this working doing following two things:

Adding this here in case others have the same issue.

kevinchalet commented 2 months ago

Hey @EyeAmRoot,

Glad to hear that! Thanks for sharing that, I'm sure it will be useful to other users :smiley:

All the best.

rob-king-volpara commented 1 month ago

For anyone else struggling with this, Kevin is correct in that you need to read the ASP.Net Core docs.

We are running OpenIddict behind Azure Front Door with a custom domain. Despite setting the hostname explicitly with the options.Set... methods, it wouldn't work until we enabled forwarded headers from AFD.

The relevant bit of code we had to add is here:

https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-8.0&preserve-view=true#forwarded-headers-middleware-options

It's just a couple of lines, but it wires things up properly.