我有一个现有的flask应用程序,该应用程序使用flask会话存储数据。我刚刚将google oauth集成到应用程序中,并且此方法有效。在将基本的flask会话更改为将flask-session用于服务器端会话后,发生了此问题(主要是因为需要更多的会话限制(4kb))。此时,我得到了一个永无止境的重定向循环。
我正在使用pycharm在本地运行它。我已经在Google API中创建了一个clientID和机密,并添加了http://127.0.0.1:5000/oauth2callback作为授权的重定向URL。我还添加了https://example.com/oauth2calback并带有指向要在其上(通过docker容器)进行部署的服务器的本地DNS记录
在本地,即使实现服务器端会话,一切似乎都可以正常工作。但是,一旦我部署了它并输入https://example.com,在Google身份验证之后,我就陷入了无限重定向循环。
import ...
import google.oauth2.credentials
import google_auth_oauthlib.flow
from from flask_session import Session
app = Flask(__name__)
# Get if this is either dev env or prod env
# then set appropriate dev properties.
env = os.getenv('ENV', 'dev')
if env == 'dev':
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
app.config['SECRET_KEY'] = b'some super secret key'
# for server side sessions
## Commenting these two lines allows everything to work
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)
GOOGLE_OAUTH2_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
GOOGLE_OAUTH2_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
REDIRECT_URI = '/oauth2callback'
CLIENT_CONFIG = {'web':{
'client_id':GOOGLE_OAUTH2_CLIENT_ID ,
'client_secret':GOOGLE_OAUTH2_CLIENT_SECRET,
'redirect_uris':["http://localhost:5000/oauth2callback"],
'auth_uri':"https://accounts.google.com/o/oauth2/auth",
'token_uri':"https://accounts.google.com/o/oauth2/token"
}}
SCOPES=["https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/userinfo.email"]
def generate_csrf_token():
if '_csrf_token' not in session:
session['_csrf_token'] = some_random_string()
return session['_csrf_token']
def check_access_token():
login_bypass = not os.getenv('ENFORCE_LOGIN', False)
if login_bypass:
return True
return 'credentials' in session
@app.route('/login')
def login():
flow = google_auth_oauthlib.flow.Flow.from_client_config(CLIENT_CONFIG, scopes=SCOPES)
flow.redirect_uri = url_for('oauth2callback', _external=True)
authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true')
session['state'] = state
return redirect(authorization_url)
def credentials_to_dict(credentials):
return {'token': credentials.token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes}
@app.route('/oauth2callback')
def oauth2callback():
state = session.get('state')
flow = google_auth_oauthlib.flow.Flow.from_client_config(CLIENT_CONFIG, scopes=SCOPES, state=state)
flow.redirect_uri = url_for('oauth2callback', _external=True)
authorization_response = request.url
flow.fetch_token(authorization_response=authorization_response)
credentials = flow.credentials
id_info = jwt.decode(credentials.id_token, verify=False)
email = id_info['email']
#allow anyone from example.com to log in
if email.split('@')[1] != "example.com":
return "Login failed!"
session['credentials'] = credentials_to_dict(credentials)
session.modified = True
#return render_template()
return redirect(url_for('loglist'))
@app.route("/")
@app.route("/loglist")
def loglist():
if not check_access_token():
return redirect(url_for('login'))
return "yay!"
在许多打印语句之后,在已部署的代码中,我可以看到我的会话不再包含'credentials'键,因此我将其重定向回登录。我猜测这与DNS有关,因为它似乎在没有DNS的情况下也可以工作(通过127.0.0.1),尽管我无法将私有IP添加到Google的授权重定向URL中以进一步验证。
我可以通过使用cachelib模块并初始化SimpleCache()/ FileSystemCache()来解决此问题。这不是最大的解决方案,但此刻对我有用,直到我可以花更多的时间解决这个问题。