From 7195b8222bb2fa981817685f05c27b6153abcd37 Mon Sep 17 00:00:00 2001 From: Ruslan Sayfutdinov Date: Wed, 8 Sep 2021 04:59:02 +0100 Subject: [PATCH] Bump PyJWT to 2.1.0 (#55911) --- .github/workflows/ci.yaml | 4 ++-- homeassistant/auth/__init__.py | 6 ++++-- homeassistant/components/google_assistant/http.py | 2 +- homeassistant/components/html5/notify.py | 6 ++++-- homeassistant/components/http/auth.py | 2 +- homeassistant/helpers/config_entry_oauth2_flow.py | 2 +- homeassistant/package_constraints.txt | 2 +- requirements.txt | 2 +- requirements_test.txt | 1 - setup.py | 2 +- tests/auth/test_init.py | 6 +++--- 11 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ec7aeb7afb0..27ab710e1ff 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ on: pull_request: ~ env: - CACHE_VERSION: 2 + CACHE_VERSION: 3 DEFAULT_PYTHON: 3.8 PRE_COMMIT_CACHE: ~/.cache/pre-commit SQLALCHEMY_WARN_20: 1 @@ -580,7 +580,7 @@ jobs: python -m venv venv . venv/bin/activate - pip install -U "pip<20.3" setuptools wheel + pip install -U "pip<20.3" "setuptools<58" wheel pip install -r requirements_all.txt pip install -r requirements_test.txt pip install -e . diff --git a/homeassistant/auth/__init__.py b/homeassistant/auth/__init__.py index 519582ea48c..717285d7b51 100644 --- a/homeassistant/auth/__init__.py +++ b/homeassistant/auth/__init__.py @@ -466,7 +466,7 @@ class AuthManager: }, refresh_token.jwt_key, algorithm="HS256", - ).decode() + ) @callback def _async_resolve_provider( @@ -507,7 +507,9 @@ class AuthManager: ) -> models.RefreshToken | None: """Return refresh token if an access token is valid.""" try: - unverif_claims = jwt.decode(token, verify=False) + unverif_claims = jwt.decode( + token, algorithms=["HS256"], options={"verify_signature": False} + ) except jwt.InvalidTokenError: return None diff --git a/homeassistant/components/google_assistant/http.py b/homeassistant/components/google_assistant/http.py index 3787a63a514..61768ff2be8 100644 --- a/homeassistant/components/google_assistant/http.py +++ b/homeassistant/components/google_assistant/http.py @@ -51,7 +51,7 @@ def _get_homegraph_jwt(time, iss, key): "iat": now, "exp": now + 3600, } - return jwt.encode(jwt_raw, key, algorithm="RS256").decode("utf-8") + return jwt.encode(jwt_raw, key, algorithm="RS256") async def _get_homegraph_token(hass, jwt_signed): diff --git a/homeassistant/components/html5/notify.py b/homeassistant/components/html5/notify.py index b3d5a081d1b..eceaa0b73b9 100644 --- a/homeassistant/components/html5/notify.py +++ b/homeassistant/components/html5/notify.py @@ -320,7 +320,9 @@ class HTML5PushCallbackView(HomeAssistantView): # 2a. If decode is successful, return the payload. # 2b. If decode is unsuccessful, return a 401. - target_check = jwt.decode(token, verify=False) + target_check = jwt.decode( + token, algorithms=["ES256", "HS256"], options={"verify_signature": False} + ) if target_check.get(ATTR_TARGET) in self.registrations: possible_target = self.registrations[target_check[ATTR_TARGET]] key = possible_target[ATTR_SUBSCRIPTION][ATTR_KEYS][ATTR_AUTH] @@ -557,7 +559,7 @@ def add_jwt(timestamp, target, tag, jwt_secret): ATTR_TARGET: target, ATTR_TAG: tag, } - return jwt.encode(jwt_claims, jwt_secret).decode("utf-8") + return jwt.encode(jwt_claims, jwt_secret) def create_vapid_headers(vapid_email, subscription_info, vapid_private_key): diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py index 7004b279bd0..43ea0522594 100644 --- a/homeassistant/components/http/auth.py +++ b/homeassistant/components/http/auth.py @@ -45,7 +45,7 @@ def async_sign_path( secret, algorithm="HS256", ) - return f"{path}?{SIGN_QUERY_PARAM}={encoded.decode()}" + return f"{path}?{SIGN_QUERY_PARAM}={encoded}" @callback diff --git a/homeassistant/helpers/config_entry_oauth2_flow.py b/homeassistant/helpers/config_entry_oauth2_flow.py index 8704932db73..71281b57a30 100644 --- a/homeassistant/helpers/config_entry_oauth2_flow.py +++ b/homeassistant/helpers/config_entry_oauth2_flow.py @@ -505,7 +505,7 @@ def _encode_jwt(hass: HomeAssistant, data: dict) -> str: if secret is None: secret = hass.data[DATA_JWT_SECRET] = secrets.token_hex() - return jwt.encode(data, secret, algorithm="HS256").decode() + return jwt.encode(data, secret, algorithm="HS256") @callback diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index e1d95a5cd23..1f8d19e9dde 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -1,4 +1,4 @@ -PyJWT==1.7.1 +PyJWT==2.1.0 PyNaCl==1.4.0 aiodiscover==1.4.2 aiohttp==3.7.4.post0 diff --git a/requirements.txt b/requirements.txt index e6b4b5845c4..1ea8772728e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ certifi>=2020.12.5 ciso8601==2.1.3 httpx==0.19.0 jinja2==3.0.1 -PyJWT==1.7.1 +PyJWT==2.1.0 cryptography==3.3.2 pip>=8.0.3,<20.3 python-slugify==4.0.1 diff --git a/requirements_test.txt b/requirements_test.txt index 86114cc02b1..c0207dddc14 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -37,7 +37,6 @@ types-decorator==0.1.7 types-emoji==1.2.4 types-enum34==0.1.8 types-ipaddress==0.1.5 -types-jwt==0.1.3 types-pkg-resources==0.1.3 types-python-slugify==0.1.2 types-pytz==2021.1.2 diff --git a/setup.py b/setup.py index e9ab189406b..eb33b492beb 100755 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ REQUIRES = [ "ciso8601==2.1.3", "httpx==0.19.0", "jinja2==3.0.1", - "PyJWT==1.7.1", + "PyJWT==2.1.0", # PyJWT has loose dependency. We want the latest one. "cryptography==3.3.2", "pip>=8.0.3,<20.3", diff --git a/tests/auth/test_init.py b/tests/auth/test_init.py index 4a763a6e995..4c3d93ede15 100644 --- a/tests/auth/test_init.py +++ b/tests/auth/test_init.py @@ -539,7 +539,7 @@ async def test_create_access_token(mock_hass): access_token = manager.async_create_access_token(refresh_token) assert access_token is not None assert refresh_token.jwt_key == jwt_key - jwt_payload = jwt.decode(access_token, jwt_key, algorithm=["HS256"]) + jwt_payload = jwt.decode(access_token, jwt_key, algorithms=["HS256"]) assert jwt_payload["iss"] == refresh_token.id assert ( jwt_payload["exp"] - jwt_payload["iat"] == timedelta(minutes=30).total_seconds() @@ -558,7 +558,7 @@ async def test_create_long_lived_access_token(mock_hass): ) assert refresh_token.token_type == auth_models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN access_token = manager.async_create_access_token(refresh_token) - jwt_payload = jwt.decode(access_token, refresh_token.jwt_key, algorithm=["HS256"]) + jwt_payload = jwt.decode(access_token, refresh_token.jwt_key, algorithms=["HS256"]) assert jwt_payload["iss"] == refresh_token.id assert ( jwt_payload["exp"] - jwt_payload["iat"] == timedelta(days=300).total_seconds() @@ -610,7 +610,7 @@ async def test_one_long_lived_access_token_per_refresh_token(mock_hass): assert jwt_key != jwt_key_2 rt = await manager.async_validate_access_token(access_token_2) - jwt_payload = jwt.decode(access_token_2, rt.jwt_key, algorithm=["HS256"]) + jwt_payload = jwt.decode(access_token_2, rt.jwt_key, algorithms=["HS256"]) assert jwt_payload["iss"] == refresh_token_2.id assert ( jwt_payload["exp"] - jwt_payload["iat"] == timedelta(days=3000).total_seconds()