Opened 8 months ago
Closed 8 months ago
#35340 closed Uncategorized (invalid)
Why does Django add 1 second to the lifetime of a cookie?
Reported by: | Leonid | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | 5.0 |
Severity: | Normal | Keywords: | cookies |
Cc: | Leonid | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I'm trying to implement JWT authentication using django-graphql-jwt on the backend, and nuxt3 for the frontend. My token and refresh_token are stored in cookies, and I wrapped the GraphQLView in a jwt_cookie decorator that automatically checks for the existence of the jwt token in the cookie, as well as its validity.
In general, everything works great. When I send an authorization request, the backend returns me the "Set-Cookie" headers for JWT and JWT_REFRESH_TOKEN with an expiration date that automatically deletes them as soon as they become invalid, which saves me a lot of code/logic on the frontend.
However, there is one very unpleasant thing - Django adds 1 second to the cookie lifetime for some reason in the set_cookie function, and it ruins everything. Here is the Django code:
def set_cookie( self, key, value="", max_age=None, expires=None, path="/", domain=None, secure=False, httponly=False, samesite=None, ): self.cookies[key] = value if expires is not None: if isinstance(expires, datetime.datetime): if timezone.is_naive(expires): expires = timezone.make_aware(expires, datetime.timezone.utc) delta = expires - datetime.datetime.now(tz=datetime.timezone.utc) # Add one second so the date matches exactly (a fraction of # time gets lost between converting to a timedelta and # then the date string). # Here's what I mean ↓↓↓ delta += datetime.timedelta(seconds=1) # Just set max_age - the max_age logic will set expires. expires = None if max_age is not None: raise ValueError("'expires' and 'max_age' can't be used together.") max_age = max(0, delta.days * 86400 + delta.seconds) else: self.cookies[key]["expires"] = expires else: ...
I see the comment from Django, but I still don't understand what it means.
This may not be a critical issue, but I just can't understand why they did it. The result of this behavior is that within 1 second after the token has expired, it is still in the user's cookies, and that doesn't seem right to me.
I can fix this problem by subtracting 1 second when creating cookies, but I would like to avoid unpredictable errors that may arise due to this innovation.
I would appreciate your answers and explanations :)
Issue trackers are for reporting bugs, please don't seek assistance here. You can get help from friendly community members on Discord or the forum 👍 https://www.djangoproject.com/community/