flask - Authlib 客户端错误:请求和响应中的状态不相等
问题描述
我正在尝试实现authlib
客户端和服务器。我以 OAuth2.0 示例为例,并按照教程在 Flask 站点上进行了我自己的客户端授权。这是我的代码:
from flask import Flask, redirect, url_for, session, request
from authlib.flask.client import OAuth
from authlib.client.errors import OAuthException
APP_ID = 'KBtRDO3r2HETjw4TcLznthoj'
APP_SECRET = '3g4C6nbJcTIYX3jyCIEmf6KE8h8pzxUhjy6ArlY3AEgj1snv'
app = Flask('testa_client')
app.debug = True
app.secret_key = 'development'
oauth = OAuth()
oauth.init_app(app)
remote = oauth.register(
'testa',
client_id=APP_ID,
client_secret=APP_SECRET,
# request_token_params={'scope': 'base'},
base_url='http://127.0.0.1:5000',
access_token_url='http://127.0.0.1:5000/auth/token',
authorize_url='http://127.0.0.1:5000/auth/connect'
)
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
callback = url_for(
'websa_authorized',
next=request.args.get('next') or request.referrer or None,
_external=True
)
return remote.authorize_redirect(callback=callback)
@app.route('/login/authorized')
def websa_authorized():
resp = remote.authorize_access_token()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error_reason'],
request.args['error_description']
)
if isinstance(resp, OAuthException):
return 'Access denied: %s' % resp.message
session['oauth_token'] = (resp['access_token'], '')
me = remote.get('/user/me')
return 'Logged in as id=%s name=%s redirect=%s' % \
(me.data['id'], me.data['name'], request.args.get('next'))
app.run(port=9001)
我所说的服务器代码与https://github.com/authlib/example-oauth2-server存储库中的代码几乎相同。
当我尝试进行授权时,我将访问授权服务器(在端口 5000 上)并确认我允许访问。但是当我在页面http://127.0.0.1:9001/login/authorized?code=...&state=...
(9001)上重定向回客户端站点时,我收到了错误:
127.0.0.1 - - [20/Jun/2018 09:33:12] "GET /login/authorized?code=1jw8niqDdzSLpnYHGvT1NIulTwRdVoy22UNm3G4xEaTOWE9Y&state=JUuJtmnseITz8WZYaDeHcAsiIL6KfS HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/xen/Dev/auth/client_example/client_testa.py", line 52, in testa_authorized
resp = remote.authorize_access_token()
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/authlib/flask/client/oauth.py", line 257, in authorize_access_token
raise MismatchingStateError()
authlib.client.errors.MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response.
有什么问题?两个部分都使用 Authlib 0.8。
解决方案
我花了很多时间在我的代码中发现一个错误。问题不在于代码,而在于我使用它的方式。我通过本地 IP 地址127.0.0.1
和不同的端口访问了这两个应用程序。浏览器混合使用此类相关 URI 的会话和 cookie。我为该服务提供了另一个本地域名(http://test:9001
在我的情况下),这解决了我的问题。
当您使用 OAuth 时,不要使用本地地址和相同的域。
推荐阅读
- python - 导入模块在终端中有效,但在 IDLE 中无效
- r - 在 R 中格式化 HTML 标题
- python - 将 Python 结果保存为 .txt 文件
- azure - 如何重命名 BLOB 容器中的文件
- telegram-bot - 我们可以在一个应用程序中使用两个 MTProto 连接吗?
- html - 在 html5 中使用高度作为百分比
- regex - 如何匹配特定字符串后面的字符?
- c++ - LLVM 错误:MCJIT::runFunction 不支持全功能参数传递
- html - Angular - 在一个 HTML 文件中包含两个相同的 ng-template 和组件(如何参考,而不是复制)
- json - 我厌倦了在颤抖中找出我的产品列表长度。你能帮我找出我的问题吗?