Skip to content
This repository was archived by the owner on Aug 21, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions realtime/_async/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
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
Expand Down Expand Up @@ -256,6 +259,30 @@ 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")

if token:
parsed = None
try:
payload = token.split(".")[1] + "=="
parsed = json.loads(b64decode(payload).decode("utf-8"))
except Exception:
raise ValueError("InvalidJWTToken")

if parsed:
# Handle expired token if any.
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

for _, channel in self.channels.items():
Expand Down
4 changes: 2 additions & 2 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
Loading