From 46ff65c3e7cda1c3e7a66ce9523fb3fc61fb5d75 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Tue, 3 Dec 2024 19:07:19 -0300 Subject: [PATCH 1/6] feat: Do not send expired token --- realtime/_async/client.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/realtime/_async/client.py b/realtime/_async/client.py index fda8487..ce2854c 100644 --- a/realtime/_async/client.py +++ b/realtime/_async/client.py @@ -2,7 +2,11 @@ import json import logging import re + +from base64 import b64decode +from datetime import datetime from functools import wraps +from math import floor from typing import Any, Callable, Dict, List, Optional import websockets @@ -256,6 +260,27 @@ async def set_auth(self, token: Optional[str]) -> None: Returns: None """ + # No empty string tokens. + if isinstance(token, str) and len(token.strip()) == 0: + raise ValueError("InvalidJWTToken: Provide a valid jwt token") + + if token: + payload = token.split(".")[1] + "==" + parsed = None + try: + parsed = json.loads(b64decode(payload).decode("utf-8")) + except Exception: + raise ValueError("InvalidJWTToken: Provide a valid jwt token") + + # Handle expired token if any. + if parsed and "exp" in parsed: + now = floor(datetime.now().timestamp()) + valid = now - parsed["exp"] < 0 + if not valid: + raise ValueError( + f"InvalidJWTToken: Invalid value for JWT claim 'exp' with value { parsed['exp'] }" + ) + self.access_token = token for _, channel in self.channels.items(): From 987081964f74572a6abd54d1cdd39dc4958c82c3 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Tue, 3 Dec 2024 20:58:12 -0300 Subject: [PATCH 2/6] feat: Do not send expired token --- realtime/_async/client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/realtime/_async/client.py b/realtime/_async/client.py index ce2854c..7e39e72 100644 --- a/realtime/_async/client.py +++ b/realtime/_async/client.py @@ -2,7 +2,6 @@ import json import logging import re - from base64 import b64decode from datetime import datetime from functools import wraps From aee5050bad9fa703a567ea0cdf6ee33a7e34dd2f Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Tue, 3 Dec 2024 20:58:57 -0300 Subject: [PATCH 3/6] feat: do not send expired token From c3fdfad4dc12c480f8ff2915f0d8dccaba7a87a6 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Wed, 11 Dec 2024 00:01:19 -0300 Subject: [PATCH 4/6] fix: fix token parsing --- realtime/_async/client.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/realtime/_async/client.py b/realtime/_async/client.py index 7e39e72..f222d42 100644 --- a/realtime/_async/client.py +++ b/realtime/_async/client.py @@ -259,26 +259,27 @@ async def set_auth(self, token: Optional[str]) -> None: Returns: None """ - # No empty string tokens. if isinstance(token, str) and len(token.strip()) == 0: - raise ValueError("InvalidJWTToken: Provide a valid jwt token") + raise ValueError("Provide a valid jwt token") if token: - payload = token.split(".")[1] + "==" parsed = None try: + payload = token.split(".")[1] + "==" parsed = json.loads(b64decode(payload).decode("utf-8")) except Exception: - raise ValueError("InvalidJWTToken: Provide a valid jwt token") - - # Handle expired token if any. - if parsed and "exp" in parsed: - now = floor(datetime.now().timestamp()) - valid = now - parsed["exp"] < 0 - if not valid: - raise ValueError( - f"InvalidJWTToken: Invalid value for JWT claim 'exp' with value { parsed['exp'] }" - ) + raise ValueError("InvalidJWTToken") + + if parsed: + if "exp" in parsed: + now = floor(datetime.now().timestamp()) + valid = now - parsed["exp"] < 0 + if not valid: + raise ValueError( + f"InvalidJWTToken: Invalid value for JWT claim 'exp' with value { parsed['exp'] }" + ) + else: + raise ValueError("InvalidJWTToken: expected claim 'exp'") self.access_token = token From 09f0a8ab9b43e5b276ab36ecb8d2d150fac7da75 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Wed, 11 Dec 2024 00:12:22 -0300 Subject: [PATCH 5/6] fix: fix token parsing --- tests/test_connection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_connection.py b/tests/test_connection.py index fd510c9..1ee658a 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -49,8 +49,8 @@ async def access_token() -> str: async def test_set_auth(socket: AsyncRealtimeClient): await socket.connect() - await socket.set_auth("jwt") - assert socket.access_token == "jwt" + with pytest.raises(ValueError): + await socket.set_auth("jwt") # Invalid JWT. await socket.close() From 6aa9117fc58dfdf5bee1c6de7d17d6a1c16cd515 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Wed, 11 Dec 2024 00:12:29 -0300 Subject: [PATCH 6/6] fix: fix token parsing --- realtime/_async/client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/realtime/_async/client.py b/realtime/_async/client.py index f222d42..c099e9d 100644 --- a/realtime/_async/client.py +++ b/realtime/_async/client.py @@ -259,6 +259,7 @@ async def set_auth(self, token: Optional[str]) -> None: Returns: None """ + # No empty string tokens. if isinstance(token, str) and len(token.strip()) == 0: raise ValueError("Provide a valid jwt token") @@ -271,6 +272,7 @@ async def set_auth(self, token: Optional[str]) -> None: raise ValueError("InvalidJWTToken") if parsed: + # Handle expired token if any. if "exp" in parsed: now = floor(datetime.now().timestamp()) valid = now - parsed["exp"] < 0