簡體   English   中英

確定何時使用Python Social Auth刷新OAUTH2令牌

[英]Decide when to refresh OAUTH2 token with Python Social Auth

我認為這主要是關於最佳做法的問題。

我有一個OAUTH2提供程序,它會發出與刷新令牌一樣長的訪問令牌(有效期為10個小時)。

我在這里發現刷新訪問令牌非常容易,但是我不明白如何確定何時刷新。

一個簡單的答案可能是“何時不再起作用”,這意味着從后端獲取HTTP 401時。 該解決方案的問題在於效率不高,而且我只能假定我已經獲得了401,因為令牌已過期。

在我的django應用中,我發現user social authExtra data字段包含如下內容:

{ "scope": "read write", "expires": 36000, "refresh_token": "xxxxxxxxxxxxx", "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "token_type": "Bearer" }

但我不確定如何使用expires字段。

所以我的問題是:我怎么知道訪問令牌是否已過期並且需要刷新它?

編輯 :我剛剛發現此注釋似乎相關,但我不明白如何在管道中插入此新功能以便在令牌刷新期間工作。

我最終想通了。 我最初感到困惑的原因是,實際上有兩種情況:

  1. 當用戶來自登錄名時,基本上就可以執行管道。
  2. 刷新令牌后,調用用戶社交身份驗證方法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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM