2

这让我非常抓狂,让我无法进行本地开发/测试。

我有一个使用 authlib 的烧瓶应用程序(仅限客户端功能)。当用户点击我的主页时,我的烧瓶后端会将他们重定向到 /login,然后再重定向到 Google Auth。Google Auth 然后将它们发布回我的应用程序的 /auth 端点。

几个月来,我一直遇到 authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF 警告的临时问题!请求和响应中的状态不相等。感觉就像一个 cookie 问题,大多数时候,我只是打开一个新的浏览器窗口或隐身或尝试清除缓存,最终,它有点工作。

但是,我现在在 docker 容器内运行完全相同的应用程序,并且在某个阶段它正在工作。我不知道我做了什么改变,但是每当我浏览到 localhost/ 或 127.0.0.1/ 并通过身份验证过程(每次清除 cookie 以确保我没有自动登录)时,我都会不断被重定向回 l​​ocalhost /auth?state=blah blah blah 我遇到了这个问题:authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF 警告!请求和响应中的状态不相等。

我认为我的代码的相关部分是:

@app.route("/", defaults={"path": ""})
@app.route("/<path:path>")
def catch_all(path: str) -> Union[flask.Response, werkzeug.Response]:
    if flask.session.get("user"):
        return app.send_static_file("index.html")
    return flask.redirect("/login")


@app.route("/auth")
def auth() -> Union[Tuple[str, int], werkzeug.Response]:
    token = oauth.google.authorize_access_token()
    user = oauth.google.parse_id_token(token)
    flask.session["user"] = user
    return flask.redirect("/")


@app.route("/login")
def login() -> werkzeug.Response:
    return oauth.google.authorize_redirect(flask.url_for("auth", _external=True))

我将非常感谢任何帮助。

当我在本地运行时,我从以下内容开始:

export FLASK_APP=foo && flask run

当我在 docker 容器中运行时,我从以下内容开始:

.venv/bin/gunicorn -b :8080 --workers 16 foo
4

2 回答 2

8

问题是 SECRET_KEY 是使用 os.random 填充的,它为不同的工作人员产生了不同的值,因此无法访问会话 cookie。

于 2020-05-23T09:22:54.617 回答
2

@adamcunnington 这里是你如何调试它:

@app.route("/auth")
def auth() -> Union[Tuple[str, int], werkzeug.Response]:
    # Check these two values
    print(flask.request.args.get('state'), flask.session.get('_google_authlib_state_'))

    token = oauth.google.authorize_access_token()
    user = oauth.google.parse_id_token(token)
    flask.session["user"] = user
    return flask.redirect("/")

检查值request.argssession查看发生了什么。

也许是因为Flask 会话在 Heroku 上的 Gunicorn 的 Flask 应用程序中的请求之间没有持久性

于 2020-05-21T02:47:01.277 回答