我正在使用 Flask-dance 来对我的应用程序的用户进行身份验证。身份验证提供者是 Google。
不时会引发以下异常:
2019-08-09 08:07:26 default[20190809t105407] "GET / HTTP/1.1" 500
2019-08-09 08:07:26 default[20190809t105407] -- 0 --
2019-08-09 08:07:26 default[20190809t105407] -- 1 --
2019-08-09 08:07:27 default[20190809t105407] InvalidClientIdError was caught: (invalid_request) Missing required parameter: refresh_token
环顾这个问题,我可以找到两个方向:
offline=True
在创建 Google 蓝图时使用- 实现错误处理程序
TokenExpiredError
我两者都做了并将我的应用程序部署到 GAE,但我仍然面临同样的错误。从堆栈跟踪中,我了解到正在调用错误处理程序,但是在代码尝试恢复时引发了“refresh_token”
我的代码:(代码基于Google QuickStart和 Flask-dance issue 143)
import oauthlib
from flask import Flask, redirect, url_for, flash, session, current_app
from flask_dance.contrib.google import make_google_blueprint, google
import os
import time
from oauthlib.oauth2.rfc6749.errors import InvalidClientIdError, TokenExpiredError
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
app = Flask(__name__)
app.secret_key = "TODO_TODO"
blueprint = make_google_blueprint(
client_id=GOOGLE_CLIENT_ID,
client_secret=GOOGLE_CLIENT_SECRET,
offline=True
)
app.register_blueprint(blueprint, url_prefix="/login")
@app.route('/logout', methods=['GET'])
def logout():
_revoke_token_and_empty_session()
return redirect(url_for('app.index'))
def _revoke_token_and_empty_session():
print('inside _revoke_token_and_empty_session')
if google.authorized:
try:
google.get(
'https://accounts.google.com/o/oauth2/revoke',
params={
'token':
current_app.blueprints['google'].token['access_token']},
)
except TokenExpiredError:
pass
except InvalidClientIdError:
# Our OAuth session apparently expired. We could renew the token
# and logout again but that seems a bit silly, so for now fake
# it.
pass
session.clear()
@app.errorhandler(oauthlib.oauth2.rfc6749.errors.TokenExpiredError)
def token_expired(_):
print('In TokenExpiredError')
del blueprint.token
_revoke_token_and_empty_session()
flash('Your session had expired. Please submit the request again',
'error')
return redirect(url_for('app.index'))
@app.route("/")
def index():
print('-- 0 --')
if not google.authorized:
return redirect(url_for("google.login"))
print('-- 1 --')
user_info_url = 'https://openidconnect.googleapis.com/v1/userinfo'
try:
resp = google.get(user_info_url)
except InvalidClientIdError as e:
#
# Here is the problem
#
print('InvalidClientIdError was caught: {}'.format(str(e)))
return 'Having an InvalidClientIdError issue: {}'.format(str(e)), 500
else:
print('-- 2 --')
user_info = resp.json()
return "You are {user_name} on Google. Time: {t}".format(user_name=user_info['name'], t=time.time())
if __name__ == "__main__":
app.run()
我目前的理解是TokenExpiredError
被捕获并index
调用了函数。当函数尝试调用resp = google.get(user_info_url)
时InvalidClientIdError: (invalid_request) Missing required parameter: refresh_token
引发。
知道如何解决吗?