singingwolfboy / flask-dance

Doing the OAuth dance with style using Flask, requests, and oauthlib.
https://pypi.python.org/pypi/Flask-Dance/
MIT License
1k stars 157 forks source link

CSRF Warning! State not equal in request and response. #390

Open gg4u opened 2 years ago

gg4u commented 2 years ago
Screen Shot 2022-05-20 at 11 12 28 AM

I found this issue when trying to localtunneling for testing my local env. In local env, everything works ok.

But concerned in production for someone else spotted this too: https://community.auth0.com/t/non-google-users-need-to-login-twice-due-to-csrf-error/77958

https://github.com/lepture/authlib/issues/376

oauthlib.oauth2.rfc6749.errors.MismatchingStateError: (mismatching_state) CSRF Warning! State not equal in request and response.

I have redirect failing:

techhouse-lk commented 2 years ago

same here!! authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response.

Did anyone find the issue? Cleared all cookies and cache , checked with 1.0.0 , 22.1.1 Keycloak authentication on airflow -OpenID

This is my webserver_config.py on airflow . Are there any errors in this python code

` """ webserver_config Referencies

class CustomSecurityManager(AirflowSecurityManager): authoauthview = CustomAuthRemoteUserView

def oauth_user_info(self, provider, response): if provider == MY_PROVIDER: token = response["access_token"] me = jwt.decode(token, algorithms="RS256", verify=False)

sample of resource_access

    # {
    #   "resource_access": { "airflow": { "roles": ["airflow_admin"] }}
    # }
  groups = me["resource_access"]["airflow"]["roles"] # unsafe
  # log.info("groups: {0}".format(groups))
  if len(groups) < 1:
    groups = ["airflow_public"]
  else:
    groups = [str for str in groups if "airflow" in str]
    userinfo = {
            "username": me.get("preferred_username"),
            "email": me.get("email"),
            "first_name": me.get("given_name"),
            "last_name": me.get("family_name"),
            "role_keys": groups
            }
    log.info("user info: {0}".format(userinfo))
    return userinfo
else:
  return {}  

SECURITY_MANAGER_CLASS = CustomSecurityManager APP_THEME = "simplex.css"`

carlosvega commented 1 year ago

Did you manage to solve this issue?

Teraskull commented 1 year ago

@carlosvega I managed to get a probably bad workaround for now:

from oauthlib.oauth2.rfc6749.errors import MismatchingStateError
from flask import redirect, url_for, jsonify
import app

@app.errorhandler(MismatchingStateError)
def mismatching_state(e):
    return redirect(url_for("google.login"))  # You could redirect to the Google login again, which resets the session state.
    # return jsonify({"error": "state_mismatch"}), 401  # Or you could handle this in any other way.

You can replicate the issue via calling the "/google/authorized" (or whatever URI is set for your Authorized redirect URI) more than once. You will get the MismatchingStateError.

With this handler, it will redirect once and not show the Werkzeug traceback. Not proud, but I wasted too much time trying anything else.