Open fabiosimeoni opened 5 years ago
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.
Hi, thanks for the super-prompt reply.
Yep that’s exactly it. All the 302 ( including the one from / to /login), construct a Location header under the assumption that FusionAuth is reachable at the root context. Envoy, upon which Ambassador is based, does not manipulate Locations (or indeed any other URI that the server may “introspect” in its responses), but expects applications to be configurable in this respect. I suppose either with a a “public path” (to use as a prefix in the construction of relative URIs) or a configurable deployment context (eg to be available under /auth). See here: https://github.com/datawire/ambassador/issues/1064.
My overall use case is to use FusionAuth (like ElasticSearch) as one component of a distributed application which sits entirely behind Ambassador. Browser requests to other components are intercepted by Ambassador, and to routed to an Auth Bridge that starts an OAuth2 dance with FusionAuth. So the bridge redirects to your Authorize endpoint using the mapping required by Ambassador to route the browser to FusionAuth.
On 4 Mar 2019, at 01:01, Daniel DeGroff notifications@github.com wrote:
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?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
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.
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?
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.
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
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.
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.
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!
I do appreciate the goodwill, but let me put this into perspective: I think the problem emerges only in a class of use cases that you might well not consider high-priority (or maybe do not want to support at all).
The use case is when FusionAuth is embedded in a distributed application architecture, rather than being integrated with as an external IdP. In this “Bring Your Own Auth” approach, FusionAuth would share a reverse-proxy/api-gateway with other application components, hence would be routed under a "path prefix”. And this is where one needs more flexibility than it’s available right now. This is the use case I had in mind when I picked FusionAuth, preferring to managed services like Auth0, Okta, etc, and even to enterprise installations ala Keycloak, because it seemed the lightweight yet full-featured third-party product to embed as a "piece of my app". But maybe this is not a general or generally-agreed upon approach.
In terms of solutions, again I suspect the least painful route for you would be to make the ‘mount point' of FusionAuth in Tomcat - the context path in servlet jargon - configurable. Then I’d configure FusionAuth to run under /auth in Tomcat and map the prefix /auth trivially to /auth itself. You may not need to change anything else, I reckon. Perhaps :)
On 10 Apr 2019, at 16:38, Daniel DeGroff notifications@github.com wrote:
Reopened #88 https://github.com/FusionAuth/fusionauth-issues/issues/88.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/FusionAuth/fusionauth-issues/issues/88#event-2266320364, or mute the thread https://github.com/notifications/unsubscribe-auth/ADR8IfLTT1a_M5v_BVGeKhr-x0wEkEEEks5vffddgaJpZM4bbUh5.
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.
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 ;)
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.
I almost have a reverse proxy configuration working that doesn't require any global routes. There are two problems remaining:
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.
I found https://github.com/FusionAuth/fusionauth-issues/issues/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?
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:
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.
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.
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
@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?
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
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.
@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 )
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?
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.
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!
@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.
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.
That's awesome and a great workaround, @fabiosimeoni !
I feel like I should gather all these workarounds and document them...
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.
For anyone else with this issue, there are proxy configurations that work here: https://github.com/FusionAuth/fusionauth-contrib/tree/master/Reverse%20Proxy%20Configurations/
In particular: https://github.com/FusionAuth/fusionauth-contrib/blob/master/Reverse%20Proxy%20Configurations/nginx/nginx.nonrootpath.excerpt.conf may be helpful.
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.
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.
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
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/
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.
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.
+1
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.
Internal: Let's review so we can either prioritize or close the issue.
I thought that moving off of tomcat was driven in part by this feature.
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.
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.
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; servername ;
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;
}
} `
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.
Any way to configure a 'public path' ?
I'm using
FusionAuth
behind a gateway (Ambassador
), mapping an/auth/
route onto it, but theLocation
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
? Isfusionauth-app.url
possibly related?Thanks for your help!