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

AUTH_REMOTE_USER reads REMOTE_USER variable instead of HTTP_REMOTE_USER #2014

Closed
sc-anssi opened this issue Apr 11, 2023 · 5 comments
Closed

Comments

@sc-anssi
Copy link

Reopening #1764

Environment

Flask-Appbuilder version: 3.4.1

pip freeze output:

apispec==3.3.2
attrs==21.2.0
Babel==2.9.1
click==7.1.2
colorama==0.4.4
defusedxml==0.7.1
dnspython==2.1.0
email-validator==1.1.3
Flask==1.1.4
Flask-AppBuilder==3.4.1
Flask-Babel==2.0.0
Flask-JWT-Extended==3.25.1
Flask-Login==0.4.1
Flask-OpenID==1.3.0
Flask-SQLAlchemy==2.5.1
Flask-WTF==0.14.3
idna==3.3
itsdangerous==1.1.0
Jinja2==2.11.3
jsonschema==3.2.0
MarkupSafe==2.0.1
marshmallow==3.14.1
marshmallow-enum==1.5.1
marshmallow-sqlalchemy==0.26.1
prison==0.2.1
PyJWT==1.7.1
pyrsistent==0.18.0
python-dateutil==2.8.2
python3-openid==3.2.0
pytz==2021.3
PyYAML==6.0
six==1.16.0
SQLAlchemy==1.3.24
SQLAlchemy-Utils==0.38.1
Werkzeug==1.0.1
WTForms==2.3.3

Describe the expected results

When using FAB with AUTH_TYPE = AUTH_REMOTE_USER behind a reverse proxy which sets the request header REMOTE_USER, FAB should authenticate that user when trying to login

Describe the actual results

Authentication fails with message Invalid login. Please try again. when clicking "login" link.

Steps to reproduce

  1. Setup the base skeleton app
  2. Modify config.py to set AUTH_TYPE = AUTH_REMOTE_USER
  3. Setup a reverse proxy in front of the app setting the request header REMOTE_USER to "Admin" (the following example is for Apache HTTPD):
        ProxyRequests Off
        ProxyPass / "http://localhost:5000/"
        ProxyPassReverse / "http://localhost:5000/"
        RequestHeader set REMOTE_USER Admin
  1. Restart reverse proxy and start the app
  2. Try to login and fail with message Invalid login. Please try again.

Potential lead

I believe CGI uses HTTP request headers as environment variable by prefixing them with HTTP_ (https://www.ietf.org/rfc/rfc3875, section 4.1.18). However FAB reads REMOTE_USER in flask_appbuilder/security/views.py.

Patching the code as follow seems to fix the problem:

--- a/flask_appbuilder/security/views.py
+++ b/flask_appbuilder/security/views.py
@@ -715,7 +715,7 @@ class AuthRemoteUserView(AuthView):
 
     @expose("/login/")
     def login(self) -> WerkzeugResponse:
-        username = request.environ.get("REMOTE_USER")
+        username = request.environ.get("HTTP_REMOTE_USER")
         if g.user is not None and g.user.is_authenticated:
             return redirect(self.appbuilder.get_url_for_index)
         if username:
@dpgaspar
Copy link
Owner

dpgaspar commented May 3, 2023

Thank you for opening the issue. I believe HTTP headers can be renamed using a reverse proxy. Having said that, I understand this is not flexible enough. Would be an improvement to create a new config key to set this header name with REMOTE_USER as the default.

@slmg
Copy link

slmg commented Jun 28, 2023

Hi @dpgaspar, what do you mean by "I believe HTTP headers can be renamed using a reverse proxy."? That's precisely what I reported I could not do in #1764 (comment), did I miss anything obvious?

@sc-anssi
Copy link
Author

Hi @dpgaspar ! Any update on this issue ? As @slmg and myself already stated, no matter what the reverse proxy sets as header in the forwarded request, it will be prefixed with HTTP_ by the web server running the CGI app. This is how CGI works (cf. RFC) : the reverse proxy acts as a client for the web server running the CGI app and all client variables are prefixed with the protocol (ie. HTTP_).

I therefore believe that FAB will always get HTTP_REMOTE_USER (and not REMOTE_USER) when run behind a reverse proxy. It is only when the web server running the CGI app is performing the authentication by itself that REMOTE_USER will be available (and not HTTP_REMOTE_USER).

Maybe testing for both variable names could be a solution ?

@dpgaspar
Copy link
Owner

I think that adding a new config key with a default to REMOTE_USER is probably a simple non breaking change. Can you do the PR, I'll help reviewing

@dpgaspar
Copy link
Owner

dpgaspar commented Feb 8, 2024

Ref PR should address this, will release soon

@dpgaspar dpgaspar closed this as completed Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants