cachethq / cachet

🚦 The open-source status page system.
https://cachethq.io
MIT License
13.93k stars 1.55k forks source link

Header-based authentication (e.g. REMOTE_USER) #3243

Closed jcmcken closed 5 years ago

jcmcken commented 5 years ago

Are there plans to support fronting Cachet with an authenticating web proxy? For example, a frontend web proxy authenticates the user, and passes the authenticated user name to Cachet via an HTTP header or environment variable, which Cachet can then trust implicitly.

This type of configuration allows users to use arbitrary authentication methods (including LDAP, CAS, SAML, OAuth, OIDC, etc.) without needing to add this functionality directly into Cachet's code base.

This possibility was mentioned in a few other issues that I saw, but it didn't look like it was addressed. Our team uses this pattern with a lot of applications that don't natively support things like OAuth and SAML authentication

welcome[bot] commented 5 years ago

:wave: Thank you for opening your first issue. I'm just an automated bot that's here to help you get the information you need quicker, so please ignore this message if it doesn't apply to your issue. If you're looking for support, you should try the Slack group by registering your email address at https://cachethq-slack.herokuapp.com. Alternatively, email support@alt-three.com for our Professional support service (please note, this a paid service.) If you're issue is with documentation, you can suggest edits by clicking the Suggest Edits link on any page, or open an issue at https://github.com/CachetHQ/Docs

jbrooksuk commented 5 years ago

I've not actually heard of this authentication previously. Is there any documentation or examples?

jcmcken commented 5 years ago

It's very common. E.g. here's some sample documentation from popular apps/frameworks:

jbrooksuk commented 5 years ago

@jcmcken I'd quite like to see this in Cachet as it would solve other issues. I'm still unsure how to implement this and how to test it, having not used this before.

jcmcken commented 5 years ago

I'm not super familiar with PHP tooling, but I've done this extensively for Python web apps. In Python, there's typically an auth middleware somewhere in the stack that looks at a particular environment variable and trusts its value as the logged in user.

In pseudocode:

if remote_auth_enabled and 'REMOTE_USER' in os.environ:
    user = os.environ['REMOTE_USER']
    password = None
    trust_user = True
else:
    user, password = extract_username_password(request.headers['Authorization'])
    trust_user = False

login(
  username=user, 
  password=password,
  trust_user=trust_user,
)

Implementation-wise, there would be a frontend web server that

  1. authenticates the user
  2. if authenticated successfully, sets the REMOTE_USER env var for the request
  3. reverse proxies the request to Cachet on the backend, which should only be listening on 127.0.0.1 (you don't want users hitting Cachet directly in this case)

I've used Apache and haproxy to do this in the past (there are several modules that perform 1 and 2 for you, then you just need to set some reverse proxy configs for your virtual host) but I believe other web servers have this capability too.

As far as unit-tests go, if your web framework allows you to mock out the request environment, that's one way to test.

For smoke-testing a live instance, you can use Apache and probably set the environment statically (e.g. set REMOTE_USER to joe@example.com) and verify that the login process works correctly.

jbrooksuk commented 5 years ago

@jcmcken oh! That sounds much easier than I thought it would be. So basically, if REMOTE_USER is set to test@example.com then we should authenticate as such user automatically?

jcmcken commented 5 years ago

@jbrooksuk Yep, that's all it is. You trust whatever the auth proxy gives you for a username. If no username is passed, the auth proxy failed to auth and you can deny login

christidis commented 3 years ago

Hi @jbrooksuk Is this available in 2.4? Can I enable remote user authentication with a configuration option/env variable? I am thinking of using a 3rd party login portal using oauth2-proxy or similar proxy and passthrough authenticated requests directly to Cachet.