Skip to content

Commit 1871fb5

Browse files
authored
fix: reverts cookie timezones to GMT (#588)
1 parent 4db27ad commit 1871fb5

File tree

7 files changed

+32
-20
lines changed

7 files changed

+32
-20
lines changed

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88

99
## [unreleased]
10-
- Upgrades `pip` and `setuptools` in CI publish job
11-
- Also upgrades `poetry` and it's dependency - `clikit`
10+
11+
## [0.28.2] - 2025-05-19
12+
- Fixes cookies being set without expiry in Django
13+
- Reverts timezone change from 0.28.0 and uses GMT
1214

1315
## [0.28.1] - 2025-02-26
1416
- Pins `httpx` and `respx` to current major versions (<1.0.0)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282

8383
setup(
8484
name="supertokens_python",
85-
version="0.28.1",
85+
version="0.28.2",
8686
author="SuperTokens",
8787
license="Apache 2.0",
8888
author_email="[email protected]",

supertokens_python/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from __future__ import annotations
1616

1717
SUPPORTED_CDI_VERSIONS = ["5.2"]
18-
VERSION = "0.28.1"
18+
VERSION = "0.28.2"
1919
TELEMETRY = "/telemetry"
2020
USER_COUNT = "/users/count"
2121
USER_DELETE = "/user/remove"

supertokens_python/framework/django/django_response.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ def set_cookie(
5151
key=key,
5252
value=value,
5353
expires=datetime.fromtimestamp(ceil(expires / 1000)).strftime(
54-
"%a, %d %b %Y %H:%M:%S UTC"
54+
# NOTE: This should always be GMT. HTTP only supports GMT in cookies.
55+
# If this is not respected, the cookie is always treated as a session cookie.
56+
"%a, %d %b %Y %H:%M:%S GMT"
5557
),
5658
path=path,
5759
domain=domain,

tests/Django/test_django.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ async def test_login_handle(self):
295295

296296
try:
297297
datetime.strptime(
298-
cookies["sAccessToken"]["expires"], "%a, %d %b %Y %H:%M:%S UTC"
298+
cookies["sAccessToken"]["expires"], "%a, %d %b %Y %H:%M:%S GMT"
299299
)
300300
except ValueError:
301301
assert False, "cookies expiry time doesn't have the correct format"

tests/test_session.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,15 @@ async def test_token_cookie_expires(
663663
for c in response.cookies.jar:
664664
if c.name == "sAccessToken": # 100 years (set by the SDK)
665665
# some time must have elasped since the cookie was set. So less than current time
666-
assert datetime.fromtimestamp(c.expires or 0, tz=timezone.utc) - timedelta(
667-
days=365.25 * 100
668-
) < datetime.now(tz=timezone.utc)
666+
assert datetime.fromtimestamp(
667+
c.expires or 0, tz=timezone(timedelta(0), "GMT")
668+
) - timedelta(days=365.25 * 100) < datetime.now(
669+
tz=timezone(timedelta(0), "GMT")
670+
)
669671
if c.name == "sRefreshToken": # 100 days (set by the core)
670-
assert datetime.fromtimestamp(c.expires or 0, tz=timezone.utc) - timedelta(
671-
days=100
672-
) < datetime.now(tz=timezone.utc)
672+
assert datetime.fromtimestamp(
673+
c.expires or 0, tz=timezone(timedelta(0), "GMT")
674+
) - timedelta(days=100) < datetime.now(tz=timezone(timedelta(0), "GMT"))
673675

674676
assert response.headers["anti-csrf"] != ""
675677
assert response.headers["front-token"] != ""
@@ -691,13 +693,15 @@ async def test_token_cookie_expires(
691693
for c in response.cookies.jar:
692694
if c.name == "sAccessToken": # 100 years (set by the SDK)
693695
# some time must have elasped since the cookie was set. So less than current time
694-
assert datetime.fromtimestamp(c.expires or 0, tz=timezone.utc) - timedelta(
695-
days=365.25 * 100
696-
) < datetime.now(tz=timezone.utc)
696+
assert datetime.fromtimestamp(
697+
c.expires or 0, tz=timezone(timedelta(0), "GMT")
698+
) - timedelta(days=365.25 * 100) < datetime.now(
699+
tz=timezone(timedelta(0), "GMT")
700+
)
697701
if c.name == "sRefreshToken": # 100 days (set by the core)
698-
assert datetime.fromtimestamp(c.expires or 0, tz=timezone.utc) - timedelta(
699-
days=100
700-
) < datetime.now(tz=timezone.utc)
702+
assert datetime.fromtimestamp(
703+
c.expires or 0, tz=timezone(timedelta(0), "GMT")
704+
) - timedelta(days=100) < datetime.now(tz=timezone(timedelta(0), "GMT"))
701705

702706
assert response.headers["anti-csrf"] != ""
703707
assert response.headers["front-token"] != ""

tests/utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
# Import AsyncMock
1818
import sys
19-
from datetime import datetime
19+
from datetime import datetime, timezone
2020
from http.cookies import SimpleCookie
2121
from os import environ, kill, remove, scandir
2222
from pathlib import Path
@@ -320,7 +320,11 @@ def assert_info_clears_tokens(info: Dict[str, Any], token_transfer_method: str):
320320

321321

322322
def get_unix_timestamp(expiry: str):
323-
return int(datetime.strptime(expiry, "%a, %d %b %Y %H:%M:%S UTC").timestamp())
323+
return int(
324+
datetime.strptime(expiry, "%a, %d %b %Y %H:%M:%S GMT")
325+
.replace(tzinfo=timezone.utc)
326+
.timestamp()
327+
)
324328

325329

326330
def verify_within_5_second_diff(n1: int, n2: int):

0 commit comments

Comments
 (0)