From 5e91cfa4e04dd1945539dc4fed5b3fba069ebfe9 Mon Sep 17 00:00:00 2001 From: "Johannes H. Gjeraker" Date: Fri, 24 Jan 2025 11:34:23 +0100 Subject: [PATCH 1/2] chore: exclude ruff formatting --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e57d158..ee46d6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,4 +3,7 @@ requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [tool.black] -force-exclude = '.*' \ No newline at end of file +force-exclude = '.*' + +[tool.ruff.format] +exclude = ["*"] \ No newline at end of file From 3977f38fc0ac0f7c2ad2f108e976c4fef95e5e62 Mon Sep 17 00:00:00 2001 From: "Johannes H. Gjeraker" Date: Fri, 24 Jan 2025 11:38:47 +0100 Subject: [PATCH 2/2] fix: remove pyjwt dependency Since we only used a single function of the library it makes sense to just replicate it manually instead of relying on a 3rd party package. --- disruptive/authentication.py | 49 +++++++++++++++++++++++++++++++++--- setup.cfg | 1 - 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/disruptive/authentication.py b/disruptive/authentication.py index f04f02e..735dde2 100644 --- a/disruptive/authentication.py +++ b/disruptive/authentication.py @@ -5,12 +5,53 @@ import time import urllib.parse from typing import Any - -import jwt +import base64 +import hmac +import hashlib from disruptive import requests as dtrequests, errors as dterrors +def base64url_encode(data: bytes) -> str: + return base64.urlsafe_b64encode(data).rstrip(b"=").decode("utf-8") + + +def base64url_decode(data: str) -> bytes: + padding = '=' * (4 - (len(data) % 4)) + return base64.urlsafe_b64decode(data + padding) + + +def create_jwt(payload: dict, + secret: str, + algorithm: str, + headers: dict, + ) -> str: + headers["typ"] = "JWT" + + header_encoded = base64url_encode(data=json.dumps( + obj=headers, + separators=(',', ':'), + ).encode("utf-8")) + payload_encoded = base64url_encode(json.dumps( + obj=payload, + separators=(',', ':'), + ).encode("utf-8")) + + message = f"{header_encoded}.{payload_encoded}" + + if algorithm == "HS256": + signature = hmac.new( + key=secret.encode("utf-8"), + msg=message.encode("utf-8"), + digestmod=hashlib.sha256, + ).digest() + else: + raise ValueError(f"Unsupported algorithm: {algorithm}") + + signature_encoded = base64url_encode(signature) + return f"{message}.{signature_encoded}" + + class _AuthRoutineBase(object): def __init__(self) -> None: @@ -227,9 +268,9 @@ def _get_access_token(self) -> dict: } # Sign and encode JWT with the secret. - encoded_jwt: str = jwt.encode( + encoded_jwt: str = create_jwt( payload=jwt_payload, - key=self.secret, + secret=self.secret, algorithm=self.algorithm, headers=jwt_headers, ) diff --git a/setup.cfg b/setup.cfg index b8cdf7e..327a87e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,6 @@ classifiers = python_requires = >=3.9 install_requires = requests >= 2.19.0, < 3.0.0 - pyjwt >= 2.0.0, < 3.0.0 include-package-data = True packages = find: