【问题标题】:How can I refresh the token with social-auth-app-django?如何使用 social-auth-app-django 刷新令牌?
【发布时间】:2017-05-18 21:58:56
【问题描述】:

我使用Python Social Auth - Django 登录我的用户。

我的后端是微软,所以我可以使用Microsoft Graph,但我认为这无关紧要。

Python Social Auth 处理身份验证,但现在我想调用 API,为此,我需要一个有效的访问令牌。 关注use cases,我可以做到这一点:

social = request.user.social_auth.get(provider='azuread-oauth2')
response = self.get_json('https://graph.microsoft.com/v1.0/me',
                         headers={'Authorization': social.extra_data['token_type'] + ' ' 
                                                   + social.extra_data['access_token']})

但是访问令牌的有效期只有 3600 秒,所以我需要刷新,我想我可以手动完成,但必须有更好的解决方案。 如何刷新 access_token?

【问题讨论】:

    标签: python django python-social-auth


    【解决方案1】:

    .get_access_token(strategy) 如果令牌过期,则自动刷新令牌。你可以这样使用它:

    from social_django.utils import load_strategy
    #...
    social = request.user.social_auth.get(provider='google-oauth2')
    access_token = social.get_access_token(load_strategy())
    

    【讨论】:

    • 我已更新我的答案以反映此更新。谢谢!
    【解决方案2】:

    social.apps.django_app.utils使用load_strategy()

    social = request.user.social_auth.get(provider='azuread-oauth2')
    strategy = load_strategy()
    social.refresh_token(strategy)
    

    现在可以从social.extra_data['access_token'] 检索更新的access_token

    最好的方法可能是检查它是否需要更新(针对 AzureAD Oauth2 定制):

    def get_azuread_oauth2_token(user):
        social = user.social_auth.get(provider='azuread-oauth2')
        if social.extra_data['expires_on'] <= int(time.time()):
            strategy = load_strategy()
            social.refresh_token(strategy)
        return social.extra_data['access_token']
    

    这是基于 get_auth_tokenfrom AzureADOAuth2 的方法。我不认为这个方法可以在管道之外访问,如果有任何方法,请回答这个问题。

    更新

    更新 1 - 20/01/2017

    Issue 请求一个额外的数据参数和访问令牌刷新时间之后,现在可以检查access_token 是否需要在每个后端更新。

    在未来的版本中(>0.2.1 for the social-auth-core)将在额外数据中添加一个新字段:

    'auth_time': int(time.time())
    

    这样就可以了:

    def get_token(user, provider):
        social = user.social_auth.get(provider=provider)
        if (social.extra_data['auth_time'] + social.extra_data['expires']) <= int(time.time()):
            strategy = load_strategy()
            social.refresh_token(strategy)
        return social.extra_data['access_token']
    

    注意:根据OAuth 2 RFC,所有响应都应该(这是一个推荐参数)提供一个expires_in,但对于大多数后端(包括azuread-oauth2),这个值被保存为@987654343 @。请注意了解您的后端的行为方式! 存在一个Issue,当它存在时,我将使用相关信息更新答案。

    更新 2 - 17/02/17

    另外,UserMixin 中有一个名为access_token_expired (code) 的方法,可用于断言令牌是否有效(注意:此方法不为竞争条件工作,正如@SCasey 在this anwser 中指出的那样)。

    更新 3 - 2017 年 5 月 31 日

    Python Social Auth - Core v1.3.0get_access_token(self, strategy) 中引入storage.py

    那么现在:

    from social_django.utils import load_strategy
    
    social = request.user.social_auth.get(provider='azuread-oauth2')
    response = self.get_json('https://graph.microsoft.com/v1.0/me',
                         headers={'Authorization': '%s %s' % (social.extra_data['token_type'], 
                                                              social.get_access_token(load_strategy())}
    

    感谢@damio 指出。

    【讨论】:

      【解决方案3】:

      @NBajanca 的更新对于 1.0.1 版几乎是正确的。

      extra_data['expires_in']
      

      现在是

      extra_data['expires']
      

      所以代码是:

      def get_token(user, provider):
          social = user.social_auth.get(provider=provider)
          if (social.extra_data['auth_time'] + social.extra_data['expires']) <= int(time.time()):
              strategy = load_strategy()
              social.refresh_token(strategy)
          return social.extra_data['access_token']
      

      我还建议从该计算中减去任意时间量,这样我们就不会遇到竞争情况,即我们在到期前 0.01 秒检查了令牌,然后因为我们发送了请求而出现错误到期后。为了安全起见,我喜欢增加 10 秒,但这可能有点矫枉过正:

      def get_token(user, provider):
          social = user.social_auth.get(provider=provider)
          if (social.extra_data['auth_time'] + social.extra_data['expires'] - 10) <= int(time.time()):
              strategy = load_strategy()
              social.refresh_token(strategy)
          return social.extra_data['access_token']
      

      编辑 @NBajanca 指出,根据 Oauth2 文档,expires_in 在技术上是正确的。似乎对于某些后端,这可能有效。上面使用expires 的代码适用于provider="google-oauth2" v1.0.1

      【讨论】:

      • 我对比赛条件投了赞成票,但您对 expires 的看法不正确。 expires_in 是在 OAuth 2 RFC 中定义的,而不是在这个包中。
      • PS:我知道有些后端有这个设置“expires_in to expires”,但我不同意。可能需要小心。
      • 啊,在我的例子中,上面的社交对象是针对 provider='google-oauth2' 的,从 v1.0.1 开始,它具有 'expires' 而不是 'expires_in'。将进行编辑。此外,我为此打开了一个问题,但似乎 'auth_time' 在刷新令牌时不会自动更改:github.com/omab/python-social-auth/issues/1089。你会期待吗?
      • 提供者实际上是azuread-oauth2,但您对这个包中的expires 是正确的。顺便说一句,创建问题的正确位置是here
      • 我已经用关于比赛条件的注释和expires_in 更新了我的答案。作为一个推荐的响应参数,并非所有提供者都必须提供它,因此该方法将始终由提供者提供。
      猜你喜欢
      • 1970-01-01
      • 2020-09-23
      • 2021-08-24
      • 2012-10-06
      • 2018-07-18
      • 2016-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多