如何使用social-auth-app-django刷新令牌?

时间:2017-01-04 14:52:28

标签: python django python-social-auth

我使用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?

3 个答案:

答案 0 :(得分:8)

如果令牌已过期,

.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())

答案 1 :(得分:7)

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

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

现在可以从access_token检索更新的social.extra_data['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_token中的AzureADOAuth2方法。我不认为这种方法可以在管道外访问,如果有任何方法可以回答这个问题。

更新

更新1 - 20/01/2017

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

在将来的版本中(0.2.1的&gt; 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)此值正在保存为expires。小心了解后端的行为! 对此存在Issue,我将使用相关信息更新答案。

更新2 - 17/02/17

此外,UserMixin中有一种名为access_token_expiredcode)的方法可用于断言令牌是否有效(注意 :这种方法不适用于竞争条件,正如this anwser @SCasey所指出的那样。

更新3 - 31/05/17

get_access_token(self, strategy)中引入了Python Social Auth - Core v1.3.0 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指出。

答案 2 :(得分:2)

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

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.01s,然后因为我们发送了请求而收到错误到期后。我想添加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的上述代码适用于v {1.0}的provider="google-oauth2"