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

Authentication via REMOTE_USER #3184

Closed
FieldofClay opened this issue Mar 13, 2020 · 18 comments
Closed

Authentication via REMOTE_USER #3184

FieldofClay opened this issue Mar 13, 2020 · 18 comments
Labels
enhancement Requests for enhancements of existing stuff. fixed Bugs that are fixed (in a coming release).

Comments

@FieldofClay
Copy link

FieldofClay commented Mar 13, 2020

Description
I'd like to Authenticate to Firefly-III via the REMOTE_USER variable. This will allow more external auth options (Authelia, Keycloak etc.) This is a standard detailed further here: https://tools.ietf.org/html/rfc3875

Solution
When the user first loads up Firefly-III, check to see if the REMOTE_USER header has been set, if it has, commence logging in as that user instead of presenting the login screen. A configuration variable to turn this behaviour on and off would be needed. (probably off by default)

@JC5
Copy link
Member

JC5 commented Mar 13, 2020

I’ll need some more background on this. The CGI standard doesn’t say much.

Authentication based on the remote user header alone isn’t going to happen.

@JC5
Copy link
Member

JC5 commented Mar 13, 2020

Wait it could work with some other settings. I’ll check it out. Not a big fan of accepting the remote_user header without some way of validating the request.

@FieldofClay
Copy link
Author

Have a look at this pull request from another Laravel app that implements this, it might make a bit more sense: snipe/snipe-it#5142

@JC5 JC5 added the enhancement Requests for enhancements of existing stuff. label Mar 13, 2020
@Wibbbs
Copy link

Wibbbs commented Apr 11, 2020

I am very interested in this as I am looking into using authelia. My question is how is this secured? If the only thing required for authentication is a header containing the user name. What is stopping me from manually adding that header with someone else’s username and get access to their account for free?

@JC5
Copy link
Member

JC5 commented Apr 11, 2020

That's a very good question! I haven't checked this out. See my comment as well:

Not a big fan of accepting the remote_user header without some way of validating the request.

Let's assume there is no way to validate the remote_user header. I don't believe this is the case but let's see what we can do:

  • Firefly III won't work out of the box with this header. It'll have to be configured somehow that Firefly III accepts this header as a means of authentication. But just firing this header at a random installation of Firefly III won't work.
  • It's assumed that you can't bypass Authelia. In other words it's impossible to reach Firefly III without passing through Authelia. This app is entirely responsible for Firefly III's security and user management.
  • Users created with a remote_user header can't be accessed through other means. For example, it's impossible to take such a user, reset their password and login in the traditional sense.

But like I said. I'm working through my tickets one at a time, oldest first. So we'll cross this bridge when we come to it. Please share your thoughts and inputs in the mean time, I'll take everything into account!

@yoyo-san
Copy link

Hi,
I believe the idea is to have a reverse proxy in front of the Firefly III (and other applications and services).
My use case: I have a reverse proxy which checks client certificate. If it is valid, then the proxy can/could set some header and I would not have to authenticate every time I use different application.
I could also use something like Authelia, but I think it's overkill to use it just for me.

@Wibbbs
Copy link

Wibbbs commented Apr 11, 2020

Ok I got this setup this morning and its actually pretty simple. It helped that I already had a traefik reverse proxy setup for a lot of my homelab.

So basically, the security here is really dependent on your architecture. The theory is that the application, in this case firefly, has to be accessible ONLY through the reverse proxy. This means you don't expose the ports of the application out from docker, you only allow access to the application trough the reverse proxy, which only has docker internal network access to the app. This means you are trusting the reverse proxy to do the auth and all authentication is handed off to authelia.

So in my test scenario, I disabled auth on my portainer application, disabled the direct exposed ports for portainer so that it was only accessible through the traefik reverse proxy. I then told traefik and authelia to protect my portainer. Now the only way I can get to portainer is through the reverse proxy and it check if i have been authenticated to authelia before letting me through. The backend app does no authentication at all.

Let me know if you have any questions about this architecture.

@JC5
Copy link
Member

JC5 commented Jun 10, 2020

Thanks for the info. The architecture makes sense, and I'm working on a custom guard that will pick up on the REMOTE_USER header. So far, it's not really working. I'll have to set up Authelia locally first, protecting Firefly III.

I was hoping to inject the REMOTE_USER header but nginx really doesn't like that. Nor does Symfony. The example implementation by @FieldofClay does it well, but they use if-else statements and that's not something I would use.

Stay tuned.

@FieldofClay
Copy link
Author

If you're trying to inject the REMOTE_USER header in via nginx, you'll need to enable the underscores_in_headers option. By default this is off, so could be the issue you're having.

On that, having the header name user configurable would be a nice bonus.

@JC5
Copy link
Member

JC5 commented Jun 11, 2020

But then it wouldn't adhere to the standards?

JC5 added a commit that referenced this issue Jun 11, 2020
JC5 added a commit that referenced this issue Jun 11, 2020
@JC5
Copy link
Member

JC5 commented Jun 11, 2020

First working version is up in the develop branch, as well as the :develop tag on Docker. Please read the documentation.

I invite you to test it on a (new) installation of Firefly III. Since 5.3.0 also includes some database changes, make sure you have a backup of your database.

Thanks!

@JC5 JC5 added the fixed Bugs that are fixed (in a coming release). label Jun 11, 2020
JC5 added a commit that referenced this issue Jun 11, 2020
@sudo-kraken
Copy link

Ok I got this setup this morning and its actually pretty simple. It helped that I already had a traefik reverse proxy setup for a lot of my homelab.

So basically, the security here is really dependent on your architecture. The theory is that the application, in this case firefly, has to be accessible ONLY through the reverse proxy. This means you don't expose the ports of the application out from docker, you only allow access to the application trough the reverse proxy, which only has docker internal network access to the app. This means you are trusting the reverse proxy to do the auth and all authentication is handed off to authelia.

So in my test scenario, I disabled auth on my portainer application, disabled the direct exposed ports for portainer so that it was only accessible through the traefik reverse proxy. I then told traefik and authelia to protect my portainer. Now the only way I can get to portainer is through the reverse proxy and it check if i have been authenticated to authelia before letting me through. The backend app does no authentication at all.

Let me know if you have any questions about this architecture.

Hey I have a question, I use the same architecture as you have described, my ownly issue is that for certain apps that have companion apps, is there a way to allow access through them bypassing authelia. This works for the api in sonarr and radarr etc but I aam yet to work out a way for firefly app and tautulli.

Thanks

@JC5 JC5 closed this as completed Jun 22, 2020
@bpatath
Copy link
Contributor

bpatath commented Jun 25, 2020

I just saw this issue in the changelog, and it is the same feature that I enabled for LDAP on #3215.

Is this fix authentication backend agnostic or is it just for eloquent ?
If it also applies to LDAP, maybe we could revert my changes ?
If it does not apply to LDAP, maybe we could merge the configuration keys and documentation ?

@JC5
Copy link
Member

JC5 commented Jun 26, 2020

It is slightly the same. The LDAP variant has its own middleware, which I sought to avoid for this solution.

$this->app['router']->pushMiddlewareToGroup('web', WindowsAuthenticate::class); 

The middleware will take the AUTH_USER variable and verify its contents with the LDAP server.

The REMOTE_USER doesn't verify anything. It assumes that Firefly III is unreachable except through an authentication proxy.

@Chluz
Copy link

Chluz commented Jun 28, 2020

Hi everyone, I will open an issue if appropriate, but I just want to check something in this thread first.
I've set the Request header for Apache2 with RequestHeader append "REMOTE_USER" "username" , but am getting an error message saying REMOTE_USER is empty when testing in firefly 5.3 beta 1 from docker. TRUSTED_PROXIES is set to my reverse proxy IP.

I was looking at the laravel documentation here https://laravel-news.com/trusted-proxy, and it seemed to say that the header format was treated a bit strangely, only accepting headers with a specific starting string, and converting them to upercase and underscores. Am I reading that correctly, and would that impact how I should pass the "REMOTE_USER" header ?

Thanks in advance,

@bpatath
Copy link
Contributor

bpatath commented Jun 28, 2020

@JC5 If we keep both codes, it could be nice to document the difference, something like:

Note that if an unknown user logs in, its account will be created. If you're using LDAP and you don't want this behavior, use the WINDOWS_SSO_ configuration keys instead. Before logging the REMOTE_USER in (or creating its account if it's his first connection), it will check its existence against the configured LDAP directory."

The thing is, why would an authenticating proxy allow a user to access the application if he is not in the LDAP directory...


@Chluz You need to use SetEnvIf to pass the header to the CGI script: SetEnvIf Remote-User ".+" REMOTE_USER=$0 where you replace Remote-User with the name of the header containing the user name. I'm no apache expert so there may be a better way of doing this.
It is not present on the Docker image, but you can create your own config file and mount/copy it to /etc/apache2/sites-available/000-default.conf.

@Chluz
Copy link

Chluz commented Jun 28, 2020

@bpatath, that worked great thanks ! I tested both USER_AUTH with ldap setup, and REMOTE_USER, both working fine with the apache2 reverse proxy connecting to keycloak through https://github.com/zmartzone/mod_auth_openidc

@github-actions
Copy link
Contributor

github-actions bot commented May 3, 2021

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests for enhancements of existing stuff. fixed Bugs that are fixed (in a coming release).
Projects
None yet
Development

No branches or pull requests

7 participants