Watcharr icon indicating copy to clipboard operation
Watcharr copied to clipboard

Proxy authentication flow

Open lufixSch opened this issue 1 year ago • 1 comments

This PR aims to add forward auth/proxy auth to this project as discussed in #461. In forward auth a proxy routes requests through a third party authentication service and only if this service returns a 200 response, the request is passed to the actual service. The authentication service will add one or many authentication headers to the request depending on the service which can be used to identify the authenticated user.

Changes made

In an ideal implementation the user would be authenticated automatically (e.g. no 'login' button has to be pressed) but with the current implementation I wasn't able to think of a viable solution which doesn't require a DB lookup on every API request. Instead, I added another provider ("proxy") and a corresponding login button in the frontend. When this button is pressed an API request to /auth/proxy is made which checks for the authentication header and returns an authentication token if the header is valid.

The current implementation is a minimal proof of concept in order to see if it could work. It's the first time I worked with GO, and I'm open to feedback.

Missing features

  • [ ] Settings for enabling proxy auth and specifying the name of the authentication header
  • [x] Allow creation of a new user if it doesn't already exist
  • [ ] Protect /auth/proxy route so that it only works if proxy auth is specifically enabled

lufixSch avatar Sep 18 '24 16:09 lufixSch

I added automatic user creation. The current behavior is the following: If the user already exists either with no UserType (e.g. username + password) or PROXY_USER they are authenticated. If no user exists with that username and either no UserType or PROXY_USER as type then a new user with UserType PROXY_USER is created. A user of type PROXY_USER can not log in with username and password.

lufixSch avatar Sep 18 '24 17:09 lufixSch

The authentication header can now be specified using the watcharr.json config file or through the admin settings in the frontend

The /auth/proxy route will return 403 as long as no authentication header is specified in the config. It also returns 403 if the authentication header is missing or if it is empty (e.g. "")

lufixSch avatar Oct 12 '24 09:10 lufixSch

@IRHM Can you please take a look at this? It's really useful, thanks!

christaikobo avatar Dec 10 '24 01:12 christaikobo

Oh sorry! I hadn't realised this was completed. Will hopefully have a look for the next release.

Would someone be able to list some common proxies that people use? I would like to try them out to test this pr.

I think authentik and authelia?

IRHM avatar Dec 10 '24 15:12 IRHM

Usually people use caddy, traefik or nginx as proxy, authelia or authentik as forward authentication service.

On Tue, Dec 10, 2024, 07:36 Mr @.***> wrote:

Oh sorry! I hadn't realised this was completed. Will hopefully have a look for the next release.

Would someone be able to list some common proxies that people use? I would like to try them out to test this pr.

— Reply to this email directly, view it on GitHub https://github.com/sbondCo/Watcharr/pull/632#issuecomment-2532082178, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFY26LFW4UWT4DFCFM3YIGD2E4C7BAVCNFSM6AAAAABOOD6V3KVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMZSGA4DEMJXHA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

christaikobo avatar Dec 10 '24 17:12 christaikobo

Thanks for confirming @terrytw, I appreciate that! I will look at testing with both when I find the time. Hopefully that covers most people who'd like to use this functionality.

IRHM avatar Dec 10 '24 18:12 IRHM

I'm using traefik together with authentik. I've been using this MR for the past months now and had no issues.

lufixSch avatar Dec 10 '24 23:12 lufixSch

If I am correct, it seems your code looks for a header (PROXY_AUTH_HEADER) containing a username and if found, allows login.

This is pretty standard, I self host several services myself and it's usually how it's handled. It is dangerous and the responsibility falls on the users to correctly configure it.

Of course full OIDC is better but it's so much more work, and proxy header auth is a decent compromise.

One thing I would like to remind you guys is that with this kind of authentication, maybe it's better to either disable or hide logout button. Maybe it's already in the code and I'm blind and didn't see it, in that case, my apologies.

christaikobo avatar Dec 18 '24 05:12 christaikobo

This is pretty standard, I self host several services myself and it's usually how it's handled. It is dangerous and the responsibility falls on the users to correctly configure it.

Thanks for your input @terrytw, it does make me feel better knowing you agree and that its common.

One thing I would like to remind you guys is that with this kind of authentication, maybe it's better to either disable or hide logout button. Maybe it's already in the code and I'm blind and didn't see it, in that case, my apologies.

I tried looking up why apps may disable the logout button when forward auth headers are used, but couldn't find much (likely because i'm using the wrong key terms).

Anywho, I believe the current code issues a (watcharr) JWT token to the user after successful SSO/proxy login, so the logout button does do stuff in our case and could allow users to login to non sso accounts if they desired? (Our logout button doesn't perform any http requests, if i remember correctly, it just simply clears all app state in the client)

I wonder if you think it makes sense for us to keep it in our case, since it still performs a function? Maybe we could rename it for proxy users if you think that could make sense/be less confusing.

IRHM avatar Dec 18 '24 14:12 IRHM

@IRHM As @terrytw already said, this is a pretty common method for easy authentication with a shared account in a self-hosted environment. I also agree, that OIDC would be preferable. However it is far more complicated to implement.

You are also right, with your assessment, that this poses a significant security risk, if the setting is enabled, when Watcharr is NOT running behind a proxy. For this reason I added the warning "Only set this if Watcharr is running behind a trusted proxy" on the settings page. I could emphasize this (bold/red text or similar) to make sure no one enables this by accident if you want.

Your Idea with the automatic login sound good. It would be nice if you could implement it. I can also do it but as I am pretty busy right now it would probably take until March.

@terrytw Concerning the logout button I agree with @IRHM it still needs to be enabled. With the current login solution Watcharr only checks for the proxy header on login and uses the JWT afterward. So if you want to change users you would still need to press the logout button.

lufixSch avatar Dec 18 '24 14:12 lufixSch

Thanks for your comments @lufixSch, it makes a lot of sense!

and thanks again for doing the heavy lifting on this, I can look into those smaller changes for us shortly.

IRHM avatar Dec 18 '24 14:12 IRHM

I was suggesting to hide/disable logout is because most of the users would completely let forward auth middleware handle authentication once they switch to proxy header authentication. And it is how it's implemented for some of the projects I self host, either logout is hidden or it does nothing other than refreshing the page.

If there is use case for people to still need the logout button, then by all means we should keep it, it's just that I'm a bit confused:

With the current login solution Watcharr only checks for the proxy header on login and uses the JWT afterward. So if you want to change users you would still need to press the logout button.

But doesn't that make a loop? For example I click logout and I'm back to the login page where it checks the proxy header and it logs me in again. And the double auth could be confusing to user as well, like if Jack logs in authentik/authelia as Jack, he is logged in in watcharr as Jack as well. He then logs out watcharr and creates a new account John in watcharr, but the account is not created in authentik/authelia, then once the current authentication middleware session expires, he can't go back in as John because he created the watcharr account but not authentik/authelia account. He will have to log in authentik/authelia as Jack first then log out as Jack in watcharr and then log in as John again every time. If both Jack and John are already present in authentik/authelia, he should simply logout and log in again as the user he desires in authentik/authelia instead of wathcarr.

I think if user want to logout they should logout the forward auth middleware. IMHO maybe we can redirect user to the forward auth page when they hit the "logout" button in watcharr, they can logout their authentik/authelia session there. How does that sound?

christaikobo avatar Dec 18 '24 19:12 christaikobo

I think you're right @terrytw. When we add the auto login flow (currently requires a button press on login page) then the logout button would indeed be a loop and we should probably hide or alter what it does in that case.

Is there a standard way that auth providers give services (us) a page that we can redirect to, to let the user actually logout, or would we just need to add another setting in the admin panel like "Proxy Logout URL" or "Proxy Address"?

I tried with my test authelia setup and if I navigate to the domain its setup at I can indeed click a logout button, if i were to guess, that would be what all of them do.

IRHM avatar Dec 18 '24 19:12 IRHM

@IRHM I have been using authelia as well, so don't know how authentik handles things. AFAIK there is no standard way, services will probably have to add a setting for logout redirection URL.

Most services don't even bother with that...It's definitely nice to have though.

christaikobo avatar Dec 18 '24 19:12 christaikobo

@IRHM I have been using authelia as well, so don't know how authentik handles things. AFAIK there is no standard way, services will probably have to add a setting for logout redirection URL.

I suppose we could only show the logout button if that setting is configured then, I think that should be okay.

IRHM avatar Dec 18 '24 19:12 IRHM

For reference, authelia has documents about either a frontend or backend solution for logout. https://github.com/authelia/authelia/commit/100d598a0edfef6980e2cbf2af554f4217d27497 The api document is also available at /api/ where you host authelia.

But I think the solution we discussed above (which corresponds to the frontend approach in the document) is easy to implement and works just as well.

christaikobo avatar Dec 18 '24 21:12 christaikobo

Usually forward auth services provide a URL to redirect to, if you want to log out again. Adding this as a feature for logout would be the cleanest solution. Of course the specific structure of that value may vary depending on the use service. This means a setting for the logout URL is needed

As @terrytw said most applications don't bother implementing this feature, but they usually use tokens with a limited lifespan (usually the session). Watcharr instead uses a JWT which doesn't expire. Therefore, a working solution for logout is definitely needed.

lufixSch avatar Dec 19 '24 10:12 lufixSch

Session expiration can also be handle by authelia/authentik if that is a concern.

It's ultimately up to you guys, I'm just providing some context.

christaikobo avatar Dec 19 '24 20:12 christaikobo

Thank you @lufixSch and @terrytw, I have merged everything auth related in #736, so closing this one now. If anything doesn't look right please let me know!

IRHM avatar Dec 29 '24 22:12 IRHM

@IRHM Thanks for doing the work making my proof of concept actually usable. I just upgraded my instance with your changes, and it's working very well so far. I'm glad I could help with this.

I'll just take this Opportunity to thank you for creating and maintaining Watcharr. Me and my friends with access to my instance really like it.

lufixSch avatar Dec 30 '24 13:12 lufixSch

@IRHM Thanks for doing the work making my proof of concept actually usable. I just upgraded my instance with your changes, and it's working very well so far. I'm glad I could help with this.

I'll just take this Opportunity to thank you for creating and maintaining Watcharr. Me and my friends with access to my instance really like it.

That is awesome, thank you and I am glad you are enjoying the app!

IRHM avatar Dec 30 '24 13:12 IRHM