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

Production doesn't login after confirmation but dev server does #829

Closed
dadiletta opened this issue Aug 18, 2023 · 9 comments · Fixed by #842
Closed

Production doesn't login after confirmation but dev server does #829

dadiletta opened this issue Aug 18, 2023 · 9 comments · Fixed by #842

Comments

@dadiletta
Copy link

When I invite a new user using my local development environment, the confirmation link successfully logs in the new user. However, the exact same software running on my production environment flashes a successful confirmation message but redirects to the login page instead. The only thing that I can think of that has changed is that I upgraded my Nginx service in my production environment. Any idea what setting might be adjusted to fix this situation?
Video explanation

@jwag956
Copy link
Collaborator

jwag956 commented Aug 18, 2023

The default behavior changed in 5.3 - any chance you have an older version on your dev?
Look at release notes for details

@dadiletta
Copy link
Author

Your help is much appreciated! The requirements.txt and both environments' site-packages reads 5.3.0.

I did find another curious error. I thought to recommend my incoming batch of new users reset their passwords so that they might login but if they try they can an error:
Bad Request
The referrer header is missing.

This error occurs when resetting new and established accounts only in production and not in dev. Could it be connected to the stuttering confirmation emails?

Thank you kindly.

@jwag956
Copy link
Collaborator

jwag956 commented Aug 18, 2023

Hmm as mentioned in the release notes - reset and confirm now set the no-referrer header as suggested by OWASP - possibly I interpreted that incorrectly.
What is complaining about no-referer ??

You might try downgrading to 5.2.x and see if your issues go away

@dadiletta
Copy link
Author

Yes, thanks! The rollback has my service back online, ready for the first day of school. Thanks again.

@jwag956
Copy link
Collaborator

jwag956 commented Aug 21, 2023

Glad things are working - if you have a chance - could you check your NGINX configuration to see if it explicitly denying requests with no referrer (and maybe any ideas on why?).
Note that OWASP best practice is to set the noreferrer header in the case of confirmation and reset links:
https://cheatsheetseries.owasp.org/cheatsheets/Forgot_Password_Cheat_Sheet.html#url-tokens

Any additional info would be appreaciated.

@dadiletta
Copy link
Author

I've crawled over my nginx sites-available and the .conf but I don't see any referrer policy settings. I'd be happy to try to modify nginx to see if I can catch up to the latest release. Let me know if you'd like me to give that a try. I really appreciate your support.

@jwag956
Copy link
Collaborator

jwag956 commented Sep 6, 2023

Quick searching shows that $http_referer would be the variable to look for. I guess it's worth making absolutely sure it is NGINX that is throwing that error and not other part of your stack...
I am considering adding a config to disable this code (i.e. continue adding the referrer header as before) in an upcoming patch release.

@augustomen
Copy link

I ran into this exact issue and I think I know what the root cause is: there's an incompatibility between Flask-Security and Flask-WTF. The latter has a built-in CSRF verification that works differently under HTTPS (current version is 1.1.1) - see protect() at https://github.com/wtforms/flask-wtf/blob/v1.1.1/src/flask_wtf/csrf.py#L256:

        if request.is_secure and current_app.config["WTF_CSRF_SSL_STRICT"]:
            if not request.referrer:
                self._error_response("The referrer header is missing.")

            good_referrer = f"https://{request.host}/"

            if not same_origin(request.referrer, good_referrer):
                self._error_response("The referrer does not match the host.")

That's probably where you are getting your error. I manage to fix it by setting WTF_CSRF_SSL_STRICT to False, but it feels like the wrong approach, since it disables CSRF for all requests, not just password reset.

@jwag956
Copy link
Collaborator

jwag956 commented Sep 28, 2023

Thanks for the tip - will look into that - SSL_STRICT doesn't disable CSRF - just same-origin validation - but I agree FS shouldn't require that. Those redirects shouldn't be form-driven - so possibly I implemented the no-referrer at the wrong place....

jwag956 added a commit that referenced this issue Sep 29, 2023
Although OWASP still recommends that reset password and confirmation links have the no-referrer header option set - this causes issues with HTTPS and Flask-WTF that requires a referrer header.
Also - for the past 5 years, the browser default for Referrer-Policy is 'strict-origin-when-cross-origin' which should be enough to mitigate any possible Referrer leakage.

closes #829
jwag956 added a commit that referenced this issue Sep 29, 2023
Although OWASP still recommends that reset password and confirmation links have the no-referrer header option set - this causes issues with HTTPS and Flask-WTF that requires a referrer header.
Also - for the past 5 years, the browser default for Referrer-Policy is 'strict-origin-when-cross-origin' which should be enough to mitigate any possible Referrer leakage.

closes #829
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants