Skip to content

Commit 44f7b39

Browse files
feat: Check if token is a JWT (#159)
1 parent e496e2b commit 44f7b39

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

supabase_functions/_async/functions_client.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from httpx import HTTPError, Response
44

55
from ..errors import FunctionsHttpError, FunctionsRelayError
6-
from ..utils import AsyncClient, is_http_url, is_valid_str_arg
6+
from ..utils import AsyncClient, is_http_url, is_valid_jwt, is_valid_str_arg
77
from ..version import __version__
88

99

@@ -60,6 +60,9 @@ def set_auth(self, token: str) -> None:
6060
the new jwt token sent in the authorization header
6161
"""
6262

63+
if not is_valid_jwt(token):
64+
ValueError("token must be a valid JWT authorization token string.")
65+
6366
self.headers["Authorization"] = f"Bearer {token}"
6467

6568
async def invoke(

supabase_functions/_sync/functions_client.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from httpx import HTTPError, Response
44

55
from ..errors import FunctionsHttpError, FunctionsRelayError
6-
from ..utils import SyncClient, is_http_url, is_valid_str_arg
6+
from ..utils import SyncClient, is_http_url, is_valid_jwt, is_valid_str_arg
77
from ..version import __version__
88

99

@@ -60,6 +60,9 @@ def set_auth(self, token: str) -> None:
6060
the new jwt token sent in the authorization header
6161
"""
6262

63+
if not is_valid_jwt(token):
64+
ValueError("token must be a valid JWT authorization token string.")
65+
6366
self.headers["Authorization"] = f"Bearer {token}"
6467

6568
def invoke(

supabase_functions/utils.py

+25
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import re
12
from urllib.parse import urlparse
23

34
from httpx import AsyncClient as AsyncClient # noqa: F401
45
from httpx import Client as BaseClient
56

67
DEFAULT_FUNCTION_CLIENT_TIMEOUT = 5
8+
BASE64URL_REGEX = r"^([a-z0-9_-]{4})*($|[a-z0-9_-]{3}$|[a-z0-9_-]{2}$)$"
79

810

911
class SyncClient(BaseClient):
@@ -17,3 +19,26 @@ def is_valid_str_arg(target: str) -> bool:
1719

1820
def is_http_url(url: str) -> bool:
1921
return urlparse(url).scheme in {"https", "http"}
22+
23+
24+
def is_valid_jwt(value: str) -> bool:
25+
"""Checks if value looks like a JWT, does not do any extra parsing."""
26+
if not isinstance(value, str):
27+
return False
28+
29+
# Remove trailing whitespaces if any.
30+
value = value.strip()
31+
32+
# Remove "Bearer " prefix if any.
33+
if value.startswith("Bearer "):
34+
value = value[7:]
35+
36+
# Valid JWT must have 2 dots (Header.Paylod.Signature)
37+
if value.count(".") != 2:
38+
return False
39+
40+
for part in value.split("."):
41+
if not re.search(BASE64URL_REGEX, part, re.IGNORECASE):
42+
return False
43+
44+
return True

0 commit comments

Comments
 (0)