Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to configure a 'public path' ? #88

Open
fabiosimeoni opened this issue Mar 3, 2019 · 46 comments
Open

Is there a way to configure a 'public path' ? #88

fabiosimeoni opened this issue Mar 3, 2019 · 46 comments
Assignees
Labels

Comments

@fabiosimeoni
Copy link

Any way to configure a 'public path' ?

I'm using FusionAuth behind a gateway (Ambassador), mapping an /auth/ route onto it, but the Location header of 302 redirects assumes always a root context deployment (e.g. point to /login rather than /auth/login, or /authorize rather than /auth/authorize, or ...).

Is there any configuration for a public path? Is fusionauth-app.url possibly related?

Thanks for your help!

@robotdan robotdan self-assigned this Mar 3, 2019
@robotdan robotdan added the support Further information is requested or user requires assistance label Mar 3, 2019
@robotdan
Copy link
Member

robotdan commented Mar 4, 2019

Hi @fabiosimeoni

If I understand correctly, the FusionAuth UI will redirect the browser to /login which will then redirect to /oauth2/authorize (for example).

In your case, you have FA running behind a proxy which adds an additional URL prefix of /auth/.

Are you using the re-write rules similar to this?
https://www.getambassador.io/reference/rewrites/

This looks like it would map a request such as /auth/login to /login - which sounds like it would work ok. Is the specific issue that the initial re-write works, but then when FusionAuth requests a redirect to /login (for example) it is not re-written to /auth/login by Ambassador?

Is there any configuration for a public path? Is fusionauth-app.url possibly related?

This is something else - this is a URL (preferably on a private network) that a FusionAuth node can talk to another FusionAuth node when horizontally scaling.

@fabiosimeoni
Copy link
Author

fabiosimeoni commented Mar 4, 2019 via email

@robotdan
Copy link
Member

robotdan commented Mar 5, 2019

Thanks for the clarification @fabiosimeoni . I'll have to dig into this a bit further, I am not very knowledgeable about Ambassador.

Your link to issue #1064 is helpful, that does seem to be the same issue.

This sort of feels like setting the servlet context, but in this case we only want to change the redirect location. I'll have to do some additional investigation, I know some other folks are using Envoy, so this is something we should probably figure out.

Thanks for bringing this to our attention, more to come.

@robotdan
Copy link
Member

I've been reading up on this and trying to identify a solution. It seems the feature set of Envoy / Ambassador doesn't necessarily make it a great fit for a full web application such as FusionAuth due to redirects etc. It seems better suited for APIs.

In theory we could add a configuration to understand the public root and build our redirects accordingly, I'd have to think this through some more to understand if there are any other edge cases not covered by this strategy.

Could you use the proxy only for requests under /api which do not rely upon redirects and utilize a separate strategy for the FusionAuth UI and OAuth workflows?

@fabiosimeoni
Copy link
Author

fabiosimeoni commented Mar 11, 2019

Could you use the proxy only for requests under /api which do not rely upon redirects and utilize a separate strategy for the FusionAuth UI and OAuth workflows?

yes, that's what we're doing and most definitely works.

for the sake of discussion, what drew me to proxy FusionAuth was the idea that - differently from other IAM solutions, I could push it further and treat it as an application service in its own right, albeit third-party. A component in its own right, on par with frontends and backends we write ourselves, deployed like those in our Compose/Kubernetes clusters, not outside of it. This potential for 'embeddability' in an app is IMHO of great appeal, very dev-oriented, and it is an original stance when you compare it to the typical managed services for IAM.

But you're right, there's no need to expose your UI to browsers. User management occurs from our frontends, even when we integrate them with your APIs.

@robotdan
Copy link
Member

Thanks for that additional information, I'll leave this issue open for a bit longer until we rule out adding a config for a public path configuration option.

Keep the feedback coming! Thanks @fabiosimeoni

@robotdan robotdan reopened this Mar 11, 2019
@robotdan
Copy link
Member

The current plan is to leave FusionAuth as-is - there are proxy configuration that support redirect re-writes. Some proxies that are built more for API banks / gateways may not work without additional configuration to ensure redirects (302) work properly.

@fabiosimeoni
Copy link
Author

Ok, makes sense.

Just for completeness, it' worth bearing in mind that. it's not just redirects that break, also FusionAuth Admin UI is not using relative paths.

@robotdan
Copy link
Member

Thanks for the additional info @fabiosimeoni - this probably needs some more investigation on our end then.

I'll re-open and set up a similar environment to see if we need to change anything to better support this scenario.

Thanks for your feedback!

@robotdan robotdan reopened this Apr 10, 2019
@fabiosimeoni
Copy link
Author

fabiosimeoni commented Apr 10, 2019 via email

@robotdan
Copy link
Member

We have discussed using a servlet context, this is definitely an option. It has some drawbacks from our side due to how we support theming, etc.

Is your work around ok for now? It sounds like you've just configured the proxy to understand the URL path and modify the behavior?

Could you use the proxy only for requests under /api which do not rely upon redirects and utilize a separate strategy for the FusionAuth UI and OAuth workflows?

yes, that's what we're doing and most definitely works.

Really appreciate all the feedback and perspective, we do want to make FusionAuth as flexible as possible. We'll kick this around some more internally and see what we can come up with.

@fabiosimeoni
Copy link
Author

I've configured my api gateway to route /oauth2, /images, /js, /fonts, /css to FA. So I had to let FA take the 'root' mapping because I couldn't prefix it. This works, but it's hardly ideal, elegant, or indeed stable (e.g. I might enable your next coolest feature from the login box and discover I also need to route /someotherpath).

I can live with it for now, sure. That's why I cared to relate my experience to the broader use case, so that you'd attach a value to that, rather than my immediate need. No expectations otherwise ;)

@gmpreussner
Copy link

I ran into the same problem using Apache as the reverse proxy, and I temporarily worked around it the same way @fabiosimeoni did. I think that adding an option to specify a public path, such as http://example.com/mydir/ would be great. So far, this has been the only gripe I have with FusionAuth. Everything else works amazing, and the setup was a breeze.

@gmpreussner
Copy link

gmpreussner commented Jun 6, 2019

I almost have a reverse proxy configuration working that doesn't require any global routes. There are two problems remaining:

  1. Some Ajax paths seem to be built in JavaScript, so they can't be reversed via mod_proxy_html, and I have to forward the route explicitly. This is probably not easily fixable in a reverse proxy without identifying the affected scripts and adding special replacement rules.
  2. While I can access all pages on the Admin back-end, I am not authorized to make any changes (i.e. Save button returns "You are not authorized" message). I suspect that this has to do with cookies, referrer URLs, or both. Any idea what I might be missing, @fabiosimeoni ?

My fully self-contained Apache config for mapping https://example.com/foo to http://localhost:9011 is as follows:

...
<Proxy *>
     Order allow,deny
     Allow from all
</Proxy>

ProxyPreserveHost Off
ProxyRequests Off

ProxyPassReverseCookieDomain localhost:9011 example.com
ProxyPassReverseCookiePath / /foo/

<Location /ajax/>
    RequestHeader unset Accept-Encoding
    ProxyPass http://localhost:9011/ajax/
</Location>

<Location /foo/>
    RequestHeader unset Accept-Encoding
    ProxyPass http://localhost:9011/
    ProxyPassReverse /

    ProxyHTMLLinks a href
    ProxyHTMLLinks area href
    ProxyHTMLLinks link href
    ProxyHTMLLinks img src longdesc usemap
    ProxyHTMLLinks object classid codebase data usemap
    ProxyHTMLLinks q cite
    ProxyHTMLLinks blockquote cite
    ProxyHTMLLinks ins cite
    ProxyHTMLLinks del cite
    ProxyHTMLLinks form action
    ProxyHTMLLinks input src usemap
    ProxyHTMLLinks head profile
    ProxyHTMLLinks base href
    ProxyHTMLLinks script src for

    ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \
        onmouseover onmousemove onmouseout onkeypress \
        onkeydown onkeyup onfocus onblur onload \
        onunload onsubmit onreset onselect onchange

    ProxyHTMLEnable On
    ProxyHTMLExtended On
    ProxyHTMLURLMap http://localhost:9011 /foo
    ProxyHTMLURLMap ^// https:// R
    ProxyHTMLURLMap ^/ /foo/ R
</Location>
...

PS: The URL rewrite rule for "^//" is for protocol relative links, such as Gravatar images. I can probably find a better regex for "^/", so that it is not necessary.

@gmpreussner
Copy link

gmpreussner commented Jun 6, 2019

I found #112 and added the following:

RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Host example.com
RequestHeader set X-Forwarded-Port 443

Unfortunately, it results in internal server errors when modifying FusionAuth resources.

I haven't tried to set the Origin header yet. Should that be the internal localhost URL?

@robotdan
Copy link
Member

robotdan commented Jun 14, 2019

While I can access all pages on the Admin back-end, I am not authorized to make any changes (i.e. Save button returns "You are not authorized" message). I suspect that this has to do with cookies, referrer URLs, or both. Any idea what I might be missing.

As you mentioned in the latest comment, this is our CSRF protection - and it can be resolved by ensuring the proxy sets the X-Forwarded- headers.

When you were seeing the "You are not authorized" messages, did you see a warning on the dashboard about your configuration? If not, what version of FusionAuth are you running?

For example:

Screen Shot 2019-06-14 at 9 01 09 AM

Unfortunately, it results in internal server errors when modifying FusionAuth resources.

That isn't good.. can you share the exception you're seeing? There should be one in the log.

@gmpreussner
Copy link

I'll check this weekend if I can still find it in the logs. I decided to move FusionAuth to a separate server earlier this week, which is probably much safer from a security standpoint anyway, so I won't be able to repro it anymore.

@leksa
Copy link

leksa commented Aug 6, 2019

Hello, jump in here. Because i have same issue.
I had set Proxy Configuratio Warning above. But can't modify resources, including add user.
Another 500 error is when i go to menu "System".

The log exception show me

PM ERROR io.fusionauth.app.primeframework.error.ExceptionExceptionHandler - An unhandled exception was thrown
java.lang.NumberFormatException: For input string: ": 443"

I use nginx as a proxy

@robotdan
Copy link
Member

robotdan commented Aug 6, 2019

@leksa I think this is a separate issue, that bug has been fixed - but not yet released.

When viewing that form we add an X-XSS-Protection header so that the browser will not complain that the form input fields contain HTML and JavaScript (on the theme edit). When a validation error occurs in the form that header was not being re-added to display the error and a failure would occur. If you view your JavaScript console when you see that error in the UI you will see a message regarding XSS.

For input string: ": 443"

Can you tell me which input field this error was for?

@leksa
Copy link

leksa commented Aug 7, 2019

Thank you @robotdan for the bugs info.

Can you tell me which input field this error was for?

I got 500 error when input the new user and open "System" menu

@trevorr
Copy link

trevorr commented Sep 13, 2019

I'm interested in this too, because I'd like to put a shared AWS load balancer in front of FA. AWS load balancers are slightly expensive to run one per microservice, so I share them when possible by using path prefix rules. They don't support rewriting the path (or modifying the request in any way), although rewriting doesn't help anyway in cases where the service needs to respond with links to itself (such as redirects). I can use the default action for now, but obviously that only works for one service.

@jerryhopper
Copy link

jerryhopper commented Jan 11, 2020

@leksa i have been getting 500 errors on a fresh install when submitting forms in the admin backend ( but behind a Apache proxy )
So i came up with a working configuration.

The line that fixes/breaks any submit actions for me is : RequestHeader unset Host

the error that i saw in the logs:

Caused by: java.net.URISyntaxException: Illegal character in authority at index 8: https://idp.yourserver.ext, idp.yourserver.ext

this is my actual working apache proxy config.
`
RequestHeader unset Host

RequestHeader set X-Forwarded-Proto "https"

RequestHeader set X-Forwarded-Port "443"

RequestHeader set X-Forwarded-Host "idp.yourserver.ext"

ProxyPass / http://192.168.1.140:9011/

ProxyPassReverse / http://192.168.1.140:9011/
`

i hope this helps you ( and others )

@robotdan
Copy link
Member

Related
#470

@w-k-s
Copy link

w-k-s commented Oct 6, 2020

I'm interested in this too, because I'd like to put a shared AWS load balancer in front of FA. AWS load balancers are slightly expensive to run one per microservice, so I share them when possible by using path prefix rules. They don't support rewriting the path (or modifying the request in any way), although rewriting doesn't help anyway in cases where the service needs to respond with links to itself (such as redirects). I can use the default action for now, but obviously that only works for one service.

Hi @trevorr ,

Were you able to work around this somehow?

@trevorr
Copy link

trevorr commented Oct 6, 2020

Were you able to work around this somehow?

I'm still just letting FA have the default action, so other apps have to use a path or Host header condition. If you don't have a problem setting up DNS aliases for each app, the Host header approach works well. The biggest complication with that is needing a private DNS zone and server if you don't want your internal host/app names in a public DNS zone.

@fabiosimeoni
Copy link
Author

HI there,

I come back to this issue almost two years after I initially posted, would it be correct to say that the problem is still open? That is, that there's no easy way to access FA UI and APIs 'under' a particular route from the root context (e.g. https://<host>:<port>/iam/<fa-resources-here>)?

I'd love to be able to use FA in my next project without the workarounds that I used two years ago (which proved brittle at time, as expected). Thanks!

@mooreds
Copy link
Collaborator

mooreds commented Mar 5, 2021

@fabiosimeoni Yes, it would be correct to say this is still an open issue. Unfortunately we've not been able to get to this. We've been working on lots of other features (see the release notes) :) .

This is definitely toward the top of the list of requested features by both the community and some of our customers, but unfortunately we haven't had a chance to implement it, and I don't know when it will be resolved.

If you'd like a guaranteed timeline for implementation, please contact us to discuss a professional services agreement.

@fabiosimeoni
Copy link
Author

thanks @mooreds, no worries

@fabiosimeoni Yes, it would be correct to say this is still an open issue. Unfortunately we've not been able to get to this. We've been working on lots of other features (see the release notes) :) .

I noticed! FusionAuth looks great and thanks for making it broadly available.

This is definitely toward the top of the list of requested features by both the community and some of our customers, but unfortunately we haven't had a chance to implement it, and I don't know when it will be resolved.

sure, I just wanted to make extra sure I hadn't missed some new knob outside the scope of the ticket.

I am experimenting now with port-based routing. Instead of intercepting requests to FusionAuth based on a path that FusionAuth can't possibly know about and preserve in responses and redirects, I can get my gateway to operate at tcp-level and listen on a port dedicated to FusionAuth, and for which no path rewriting is required.

This would be good enough for me, as I'm not exposing your UI to end users, only to admins and operators, so it seems reasonable that it should be accessed 'out-of-band'.

And after a first run in staging, all seems to work pretty well. So far.

@mooreds
Copy link
Collaborator

mooreds commented Mar 8, 2021

That's awesome and a great workaround, @fabiosimeoni !

I feel like I should gather all these workarounds and document them...

@fabiosimeoni
Copy link
Author

one caveat though, when you enable tls on the the new port and terminate it at the gateway, your checks for CSRF notice a protocol discrepancy between https of the browser request and http of the gateway request to FusionAuth. This causes POST failures.

I cannot tell the gateway to add X-FORWARDED-PROTO headers, as it's operating at L4 and doesn't see http headers.

So one needs to either terminate tls at FusionAuth itself (replacing the self-signed certificates that you ship).

Or one can continue to terminate it at the gateway (with the certificates one was already using), but have the gateway initiate another https request to FusionAuth. Your self-signed certificates do not require user consent for this last leg.

I used the latter option, so all tls termination remains at the gateway while the original request and the proxied requests remain identical. The theoretical cost is the overhead of two https handshakes, but that's totally immaterial for my use case.

@mooreds
Copy link
Collaborator

mooreds commented Mar 12, 2021

@robotdan robotdan added feature and removed support Further information is requested or user requires assistance labels Aug 30, 2021
@yaskoo
Copy link

yaskoo commented Dec 2, 2021

I wonder if supporting the X-Forwarded-Prefix header would be easier to integrate.
Recently I had to fix a similar issue in a Spring Boot app which used Spring HATEOAS and this resolved the issue.

@yuriy-maftiyak-verint
Copy link

The workaround, https://github.com/FusionAuth/fusionauth-contrib/blob/master/Reverse%20Proxy%20Configurations/nginx/nginx.nonrootpath.excerpt.conf, does not work for deployment at my organization.

The workaround has a separate proxy rule for the /admin path, but at this path, we have another product deployed.

@shimshon70
Copy link

Our requirement is to install FusionAuth (standalone) in a non-root context path. We should have option to mention "Server Base URL" field in configuration. Rewrite rule in reverse proxy solution proposed above is not working, it is not maintainable, and performance affecting. For example something like this

@mooreds
Copy link
Collaborator

mooreds commented Dec 19, 2021

Thanks for the input, @shimshon70 and @yuriy-maftiyak-verint .

Please make sure you upvote the issue. If you have a support contract, please open a support ticket. Both of these feedback mechanisms help us determine future effort.

Here's our general roadmap guidance: https://fusionauth.io/docs/v1/tech/core-concepts/roadmap/

@surya-maximl
Copy link

The workaround, https://github.com/FusionAuth/fusionauth-contrib/blob/master/Reverse%20Proxy%20Configurations/nginx/nginx.nonrootpath.excerpt.conf, does not work for deployment at my organization.

The workaround has a separate proxy rule for the /admin path, but at this path, we have another product deployed.

Hi @yuriy-maftiyak-verint, do you really need to proxy pass the /admin path? If not you can remove it from the Nginx config.

@MikoverseAllar
Copy link

This is also one of the biggest issues we've faced when using FusionAuth. We can route it on its own subdomain but we want to proxy a subdir for internal admin purposes that will never be exposed to the public.

For now we can set up a local proxy and access it but this inability to use relative paths is a big thorn in our side in an otherwise mostly easy to use deployment. Our api requests are being handled fine, but the admin panel not using relative paths is frustrating. We will most likely drop it back to a subdomain but it is the only service in our entire tech stack that doesn't support relative url paths. But as this is for admin UI and internal network access only, we can work around it.

@MPH-DZP
Copy link

MPH-DZP commented Feb 21, 2023

+1

@jandeschuttere
Copy link

While setting up FusionAuth I had the same issue. Having support for this as part of the application itself would be helpful. I did notice the template files are using the request.contextPath variable as a prefix for the relative paths that I checked so I'm hopeful a configuration is possible to allow to define that variable in the near future.

I'm in luck however, the main application is publicly available via its own URL so I was able to configure the k8s ingress nginx config by defining the following annotation:

    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Accept-Encoding "";
      sub_filter '<head>' '<head> <base href="https://_THE_PUBLIC_DOMAIN_">';

This configures the relative paths to reference that domain instead. The receiving end does require to be set up to allow cors but as this is only for loading images and JS and such, you are able to define a wildcard on the allow-origin header and have the allow-credentials to be false.

@robotdan
Copy link
Member

robotdan commented Nov 6, 2023

Internal:
Let's review so we can either prioritize or close the issue.

@mooreds
Copy link
Collaborator

mooreds commented Nov 6, 2023

I thought that moving off of tomcat was driven in part by this feature.

@ajmueller
Copy link

ajmueller commented Jan 8, 2024

I'm currently evaluating FusionAuth as a replacement for Auth0 and ran across this exact issue. Thank you to @fabiosimeoni and @gmpreussner for your comments above. I ended up doing exactly what Fabio did here, but had to also proxy /app. This was in a test Vue 3 app using the Vue SDK.

Our use-case is that we use a single development Auth0 tenant for local development as well as shared development and PR preview environments. Hoping for a similar architecture with FusionAuth, we want to use a single hosted FusionAuth instance for these environments. For local development the fix was in Vite config and for our other environments it will be in AWS Amplify (presumably their rewrites/redirects functionality will suffice for this, but I haven't tested that yet).

Proxying all FusionAuth traffic under a single path (e.g. /auth) would simplify our configurations greatly, but also allow us to use the paths like /images or /css for our own assets instead of FusionAuth's.

@mooreds
Copy link
Collaborator

mooreds commented Jan 8, 2024

Thanks for your feedback @ajmueller . Please don't forget to upvote the issue if you haven't already, as community votes are incorporated into our roadmap.

@MikoverseAllar
Copy link

wMi6ADWhCX

@krtvelaz
Copy link

I am using this nginx configuration deploying a pod in the same deployment of fusionAuth, so it goes out on port 8080 with the path /fa

`map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream fusionauth {
server container-fusionauth:9011;
}
server {
listen 8080;
server_name _;

location /fa/ {
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-Proto http;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port 8080;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Accept-Encoding "";
    sub_filter       'action="/'  'action="/fa/';
    sub_filter       'href="/'  'href="/fa/';
    sub_filter       'href="/admin/'  'href="/fa/admin/';
    sub_filter       'src="/images'  'src="/fa/images';
    sub_filter       'src="/js'  'src="/fa/js';
    sub_filter_once  off;
    proxy_pass http://container-fusionauth/;
}

location / {
    return 301 http://$host:8080/fa$request_uri;
}

}
`

@mooreds
Copy link
Collaborator

mooreds commented Jul 22, 2024

Thanks @krtvelaz !

Please consider submitting this to our fusionauth-contrib repo: https://github.com/FusionAuth/fusionauth-contrib/tree/main/Reverse%20Proxy%20Configurations which has a number of reverse proxy configurations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests