在 Flask 会话中存储 oAuth 状态令牌

Posted

技术标签:

【中文标题】在 Flask 会话中存储 oAuth 状态令牌【英文标题】:Storing oAuth state token in Flask session 【发布时间】:2018-02-05 06:21:31 【问题描述】:

一些关于 oAuth 的教程使用 Flask 会话在 Flask 会话中存储状态参数和访问令牌。 (Brendan McCollam's very useful presentation from Pycon is an example)

我了解 Flask 将会话存储在客户端的 cookie 中,并且它们很容易暴露(see Michael Grinberg's how-secure-is-the-flask-user-session)。我自己尝试过,并且能够看到令牌过期等。

在烧瓶会话中存储状态和令牌是否正确,或者它们应该存储在其他地方?

代码示例:

@app.route('/login', methods=['GET'])
def login():
    provider = OAuth2Session(
                   client_id=CONFIG['client_id'],
                   scope=CONFIG['scope'],
                   redirect_uri=CONFIG['redirect_uri'])
    url, state = provider.authorization_url(CONFIG['auth_url'])
    session['oauth2_state'] = state
    return redirect(url)

@app.route('/callback', methods=['GET'])
def callback():
    provider = OAuth2Session(CONFIG['client_id'],
                             redirect_uri=CONFIG['redirect_uri'],
                             state=session['oauth2_state'])
    token_response = provider.fetch_token(
                        token_url=CONFIG['token_url'],
                        client_secret=CONFIG['client_secret'],
                        authorization_response=request.url)

    session['access_token'] = token_response['access_token']
    session['access_token_expires'] = token_response['expires_at']

    transfers = provider.get('https://transfer.api.globusonline.org/v0.10/task_list?limit=1')

    return redirect(url_for('index'))

@app.route('/')
def index():
    if 'access_token' not in session:
        return redirect(url_for('login'))
    transfers = requests.get('https://transfer.api.globusonline.org/v0.10/task_list?limit=1',
                             headers='Authorization': 'Bearer ' + session['access_token'])
    return render_template('index.html.jinja2',
                           transfers=transfers.json())

【问题讨论】:

有人吗?任何人?我会回答一半......当然我不是唯一一个认为这很重要的人 【参考方案1】:

我认为有些教程为了显示更简单的代码而过度简化了。一个好的经验法则是仅将会话 cookie 用于您的应用程序和用户浏览器必须知道的信息,而不是私人信息。这通常会转化为会话 ID 和可能的其他非敏感信息,例如语言选择。

应用该经验法则,我建议在每个标记旁边使用:

    授权令牌:根据定义,用户和应用程序都知道此数据,因此在 cookie 中公开它不应该是安全问题。但是,一旦您获得访问代码,确实没有必要保留此令牌,因此我建议您不要将其保存在本地或您的 cookie 中。

    访问代码:此数据必须被视为机密,并且只能由您的应用程序和提供商知道。没有理由让任何其他方(包括用户)知道它,因此它不应包含在 cookie 中。如果您需要存储它,请将其本地保存在您的服务器中(可能在您的数据库中,引用您的用户会话 ID)。

    CSRF 状态令牌:此数据理想地包含在隐藏表单字段中,并针对服务器端变量进行验证,因此 cookie 似乎是不必要的复杂化。但我不会担心这些数据在 cookie 中,因为它无论如何都是响应的一部分。

请记住,还有诸如烧瓶会话之类的扩展,实际上相同的代码使用服务器端变量而不是 cookie 变量。

【讨论】:

谢谢JavoSN...我一直在寻找这个答案很长一段时间...非常感谢全面的解释。

以上是关于在 Flask 会话中存储 oAuth 状态令牌的主要内容,如果未能解决你的问题,请参考以下文章

Oauth2令牌 - 我可以将令牌存储在会话中

OAuth 2.0。没有会议? (无国籍)

SPA 应该在哪里保存 OAuth 2.0 访问令牌?

对 OAuth 的访问令牌保密有多重要?

对 OAuth 的访问令牌保密有多重要?

如何使用 OAuth 存储和发送带有 API 请求的授权令牌?