[英]Decide when to refresh OAUTH2 token with Python Social Auth
我認為這主要是關於最佳做法的問題。
我有一個OAUTH2提供程序,它會發出與刷新令牌一樣長的訪問令牌(有效期為10個小時)。
我在這里發現刷新訪問令牌非常容易,但是我不明白如何確定何時刷新。
一個簡單的答案可能是“何時不再起作用”,這意味着從后端獲取HTTP 401時。 該解決方案的問題在於效率不高,而且我只能假定我已經獲得了401,因為令牌已過期。
在我的django應用中,我發現user social auth
的Extra data
字段包含如下內容:
{ "scope": "read write", "expires": 36000, "refresh_token": "xxxxxxxxxxxxx", "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "token_type": "Bearer" }
但我不確定如何使用expires
字段。
所以我的問題是:我怎么知道訪問令牌是否已過期並且需要刷新它?
編輯 :我剛剛發現此注釋似乎相關,但我不明白如何在管道中插入此新功能以便在令牌刷新期間工作。
我最終想通了。 我最初感到困惑的原因是,實際上有兩種情況:
refresh_token
解決第一種情況
我為管道創建了一個新函數:
def set_last_update(details, *args, **kwargs): # pylint: disable=unused-argument
"""
Pipeline function to add extra information about when the social auth
profile has been updated.
Args:
details (dict): dictionary of informations about the user
Returns:
dict: updated details dictionary
"""
details['updated_at'] = datetime.utcnow().timestamp()
return details
在設置中,我在load_extra_data
之前將其添加到管道中
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
# the following custom pipeline func goes before load_extra_data
'backends.pipeline_api.set_last_update',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details',
'backends.pipeline_api.update_profile_from_edx',
'backends.pipeline_api.update_from_linkedin',
)
並且,仍然在設置中,我在額外數據中添加了新字段。
SOCIAL_AUTH_EDXORG_EXTRA_DATA = ['updated_at']
對於第二種情況:
我重寫了后端的refresh_token
方法以添加額外的字段。
def refresh_token(self, token, *args, **kwargs):
"""
Overridden method to add extra info during refresh token.
Args:
token (str): valid refresh token
Returns:
dict of information about the user
"""
response = super(EdxOrgOAuth2, self).refresh_token(token, *args, **kwargs)
response['updated_at'] = datetime.utcnow().timestamp()
return response
仍然在后端類中,我添加了一個額外的字段來提取來自服務器的expires_in
字段。
EXTRA_DATA = [
('refresh_token', 'refresh_token', True),
('expires_in', 'expires_in'),
('token_type', 'token_type', True),
('scope', 'scope'),
]
此時,我具有創建訪問令牌的時間戳記( updated_at
)和它將有效的秒數( expires_in
)。
注意: updated_at
是一個近似值,因為它是在客戶端而不是在提供程序服務器上創建的。
現在唯一缺少的是用於檢查是否該刷新訪問令牌的功能。
def _send_refresh_request(user_social):
"""
Private function that refresh an user access token
"""
strategy = load_strategy()
try:
user_social.refresh_token(strategy)
except HTTPError as exc:
if exc.response.status_code in (400, 401,):
raise InvalidCredentialStored(
message='Received a {} status code from the OAUTH server'.format(
exc.response.status_code),
http_status_code=exc.response.status_code
)
raise
def refresh_user_token(user_social):
"""
Utility function to refresh the access token if is (almost) expired
Args:
user_social (UserSocialAuth): a user social auth instance
"""
try:
last_update = datetime.fromtimestamp(user_social.extra_data.get('updated_at'))
expires_in = timedelta(seconds=user_social.extra_data.get('expires_in'))
except TypeError:
_send_refresh_request(user_social)
return
# small error margin of 5 minutes to be safe
error_margin = timedelta(minutes=5)
if datetime.utcnow() - last_update >= expires_in - error_margin:
_send_refresh_request(user_social)
我希望這對其他人有幫助。
當前, extra_data
字段現在具有auth_time
。 您可以將其與expires
一起使用,從而確定access_token
的有效性:
if (social.extra_data['auth_time'] + social.extra_data['expires'] - 10) <= int(time.time()):
from social_django.utils import load_strategy
strategy = load_strategy()
social.refresh_token(strategy)
多余的“ 10”秒用於防止出現爭用情況,在這種情況下, access_token
可能在執行進一步的代碼之前到期。
這個問題給出了更多細節: 如何使用social-auth-app-django刷新令牌?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.