1

我有一个现有的烧瓶应用程序,它使用烧瓶会话来存储数据。我刚刚将 google oauth 集成到应用程序中,这很有效。将基本烧瓶会话更改为使用烧瓶会话进行服务器端会话后出现此问题(主要是因为会话需要超过 4kb 限制)。在这一点上,我得到了一个永无止境的重定向循环。

我正在使用 pycharm 在本地运行它。我在 google API 中创建了一个 clientID 和 secret,并添加了http://127.0.0.1:5000/oauth2callback作为授权的重定向 URL。我还添加了https://example.com/oauth2calback与本地 DNS 记录指向我正在部署它的服务器(通过 docker 容器)

在本地,一切似乎都可以正常工作,即使在实现服务器端会话时也是如此。但是,一旦我部署了它并输入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!"

在许多打印语句之后,在部署的代码中,我可以看到我的会话不再包含“凭据”密钥,因此我重定向回登录。我猜这与某处的 DNS 有关,因为它似乎在没有 DNS 的情况下工作(以某种方式通过 127.0.0.1),尽管我无法将私有 IP 添加到谷歌授权的重定向 URL 以进一步验证。

编辑:

我可以通过使用 cachelib 模块并初始化 SimpleCache()/FileSystemCache() 来解决这个问题。不是最好的解决方案,但它目前对我有用,直到我可以花更多时间来解决这个问题。

4

0 回答 0