簡體   English   中英

每次使用 django-graphql-jwt 生成新令牌時,如何撤銷 JWT?

[英]How do I revoke JWT everytime a new token generated using django-graphql-jwt?

我正在使用 django-graphql-jwt ( https://django-graphql-jwt.domake.io/en/latest/index.html ) 來處理我的 Django Python Graphene 應用程序的身份驗證。 目前,每產生一個新的JWT,之前的JWT只要沒有過期,它仍然是活躍的。

每當我生成新的 JWT 時,我想撤銷/阻止對先前生成的 JWT 的訪問(即使 JWT 尚未過期)。

我在想的是利用 JWT 有效負載中的 origIat,並將其與用戶 model 的 last_login 屬性進行比較。不過我注意到,每當我使用 JWT 進行身份驗證時,User.last_login 都不會更新。

仍在尋找如何正確解決這個問題,想知道你們中是否有人已經解決了這個問題。

謝謝!

我目前的解決方案:

  1. 為用戶 model 添加 last_jwt_iat 字段
class User(AbstractUser):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    email = models.EmailField(unique=True, null=False, blank=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    last_jwt_iat = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return f'{self.email}'
  1. 子類化 graphql_jwt.relay.JSONWebTokenMutation,並在請求新令牌時更新 User.last_jwt_iat
class ObtainJSONWebToken(graphql_jwt.relay.JSONWebTokenMutation):

    @classmethod
    def resolve(cls, root, info, **kwargs):
        # Update User.last_jwt_iat by generating current UTC timestamp
        # Probably better if we can extract the origIat from GraphQL payload
        user = info.context.user
        last_jwt_iat = datetime.datetime.utcnow()
        user.last_jwt_iat = last_jwt_iat
        user.save()
        return cls()
  1. 使用 Graphene 中間件檢查 User.last_jwt_iat > 當前 JWT 的 iat
def _authenticate(request):
    """
    Check if user is anonymous and JWT authorization header exist
    :param request: HttpRequest instance
    :return: Boolean
    """
    is_anonymous = not hasattr(request, 'user') or request.user.is_anonymous
    return is_anonymous and get_http_authorization(request) is not None


class AuthCheckIat(object):
    def resolve(self, next, root, info, **args):
        context = info.context
        # Check if User.last_jwt_iat > token iat, raise error, stop evaluation
        if _authenticate(context):
            jwt_decoded = jwt_decode(get_http_authorization(context))
            username = jwt_decoded['username']
            user = User.objects.get(username=username)
            iat = datetime.datetime.fromtimestamp(jwt_decoded['origIat'], tz=datetime.timezone.utc)
            if user.last_jwt_iat > iat:
                raise PermissionDenied(
                    'User last JWT issued time is greater than supplied JWT issued time. Please use newer token. ')
        return next(root, info, **args)

這是我的解決方案

from django.dispatch import receiver
from django.db.models.signals import post_save
from graphql_jwt.refresh_token.models import RefreshToken


@receiver(post_save, sender=RefreshToken)
def clear_tokens(sender, instance, **kwargs):
    recent_issued_token = instance
    try:
        token_user = RefreshToken.objects.get(token=recent_issued_token).user
        user_all_tokens = RefreshToken.objects.filter(user=token_user)
        tokens_length = len(user_all_tokens)
        if tokens_length > 1:
            tokens_to_delete = user_all_tokens[0:tokens_length - 1]
            for token in tokens_to_delete:
                token.delete()
    except Exception as e:
        print(e)
        print('Error deleting existing tokens')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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