diff --git a/.github/workflows/check_python_dependencies.yml b/.github/workflows/check_python_dependencies.yml index 85a4e796ce..b691e68d4b 100644 --- a/.github/workflows/check_python_dependencies.yml +++ b/.github/workflows/check_python_dependencies.yml @@ -14,18 +14,18 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v4 - + - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - + - name: Install repo-tools run: pip install edx-repo-tools[find_dependencies] - name: Install setuptool - run: pip install setuptools - + run: pip install setuptools + - name: Run Python script run: | find_python_dependencies \ @@ -35,6 +35,5 @@ jobs: --ignore https://github.com/edx/braze-client \ --ignore https://github.com/edx/edx-name-affirmation \ --ignore https://github.com/mitodl/edx-sga \ - --ignore https://github.com/edx/token-utils \ --ignore https://github.com/open-craft/xblock-poll - + diff --git a/lms/djangoapps/courseware/tests/test_jwt.py b/lms/djangoapps/courseware/tests/test_jwt.py index d21ac1778f..a513b1fec6 100644 --- a/lms/djangoapps/courseware/tests/test_jwt.py +++ b/lms/djangoapps/courseware/tests/test_jwt.py @@ -9,9 +9,6 @@ from jwkest.jws import JWS from lms.djangoapps.courseware.jwt import _encode_and_sign, create_jwt, unpack_jwt -import unittest -from unittest.mock import patch - test_user_id = 121 invalid_test_user_id = 120 @@ -28,6 +25,10 @@ expected_full_token = { class TestSign(unittest.TestCase): + """ + Tests for JWT creation and signing. + """ + def test_create_jwt(self): token = create_jwt(test_user_id, test_timeout, {}, test_now) @@ -53,6 +54,7 @@ class TestSign(unittest.TestCase): with self.assertRaises(BadSignature): _verify_jwt(token) + def _verify_jwt(jwt_token): """ Helper function which verifies the signature and decodes the token @@ -65,6 +67,10 @@ def _verify_jwt(jwt_token): class TestUnpack(unittest.TestCase): + """ + Tests for JWT unpacking. + """ + def test_unpack_jwt(self): token = create_jwt(test_user_id, test_timeout, {}, test_now) decoded = unpack_jwt(token, test_user_id, test_now) diff --git a/lms/djangoapps/courseware/utils.py b/lms/djangoapps/courseware/utils.py index 413e024d28..6755c5e7b5 100644 --- a/lms/djangoapps/courseware/utils.py +++ b/lms/djangoapps/courseware/utils.py @@ -234,36 +234,3 @@ def _use_new_financial_assistance_flow(course_id): ): return True return False - - - -def unpack_jwt(token, lms_user_id, now=None): - """ - Unpack and verify an encoded JWT. - - Validate the user and expiration. - - Arguments: - token (string): The token to be unpacked and verified. - lms_user_id (int): LMS user ID this token should match with. - now (int): Optional now value for testing. - - Returns a valid, decoded json payload (string). - """ - now = now or int(time()) - - # Unpack and verify token - keys = jwk.KEYS() - keys.load_jwks(settings.TOKEN_SIGNING['JWT_PUBLIC_SIGNING_JWK_SET']) - payload = JWS().verify_compact(token.encode('utf-8'), keys) - - if "lms_user_id" not in payload: - raise MissingKey("LMS user id is missing") - if "exp" not in payload: - raise MissingKey("Expiration is missing") - if payload["lms_user_id"] != lms_user_id: - raise Invalid("User does not match") - if payload["exp"] < now: - raise Expired("Token is expired") - - return payload diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 33bd4013f3..65c4172798 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -91,6 +91,7 @@ from lms.djangoapps.courseware.courses import ( ) from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link from lms.djangoapps.courseware.exceptions import CourseAccessRedirect, Redirect +from lms.djangoapps.courseware.jwt import unpack_jwt from lms.djangoapps.courseware.masquerade import is_masquerading_as_specific_student, setup_masquerade from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.models import BaseStudentModuleHistory, StudentModule @@ -105,7 +106,7 @@ from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateCli from lms.djangoapps.courseware.utils import ( _use_new_financial_assistance_flow, create_financial_assistance_application, - is_eligible_for_financial_aid, unpack_jwt + is_eligible_for_financial_aid ) from lms.djangoapps.edxnotes.helpers import is_feature_enabled from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 4861b7be1f..4dc66c138a 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -221,7 +221,6 @@ django==4.2.18 # edx-search # edx-submissions # edx-toggles - # edx-token-utils # edx-when # edxval # enmerkar @@ -546,7 +545,7 @@ edx-when==2.5.1 # edx-proctoring edxval==2.9.0 # via -r requirements/edx/kernel.in -elasticsearch==7.9.1 +elasticsearch==7.13.4 # via # -c requirements/edx/../common_constraints.txt # -c requirements/edx/../constraints.txt @@ -931,7 +930,6 @@ pygments==2.19.1 pyjwkest==1.4.2 # via # -r requirements/edx/kernel.in - # edx-token-utils # lti-consumer-xblock pyjwt[crypto]==2.10.1 # via @@ -1215,7 +1213,7 @@ uritemplate==4.1.1 # drf-spectacular # drf-yasg # google-api-python-client -urllib3==2.2.3 +urllib3==1.26.20 # via # -c requirements/edx/../common_constraints.txt # botocore diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index ae377bd5cc..84e2a26239 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -395,7 +395,6 @@ django==4.2.18 # edx-search # edx-submissions # edx-toggles - # edx-token-utils # edx-when # edxval # enmerkar @@ -858,7 +857,7 @@ edxval==2.9.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -elasticsearch==7.9.1 +elasticsearch==7.13.4 # via # -c requirements/edx/../common_constraints.txt # -c requirements/edx/../constraints.txt @@ -1598,7 +1597,6 @@ pyjwkest==1.4.2 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt - # edx-token-utils # lti-consumer-xblock pyjwt[crypto]==2.10.1 # via @@ -2172,7 +2170,7 @@ uritemplate==4.1.1 # drf-spectacular # drf-yasg # google-api-python-client -urllib3==2.2.3 +urllib3==1.26.20 # via # -c requirements/edx/../common_constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 354e85c98f..2b7072e447 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -280,7 +280,6 @@ django==4.2.18 # edx-search # edx-submissions # edx-toggles - # edx-token-utils # edx-when # edxval # enmerkar @@ -637,7 +636,7 @@ edx-when==2.5.1 # edx-proctoring edxval==2.9.0 # via -r requirements/edx/base.txt -elasticsearch==7.9.1 +elasticsearch==7.13.4 # via # -c requirements/edx/../common_constraints.txt # -c requirements/edx/../constraints.txt @@ -1147,7 +1146,6 @@ pygments==2.19.1 pyjwkest==1.4.2 # via # -r requirements/edx/base.txt - # edx-token-utils # lti-consumer-xblock pyjwt[crypto]==2.10.1 # via @@ -1529,7 +1527,7 @@ uritemplate==4.1.1 # drf-spectacular # drf-yasg # google-api-python-client -urllib3==2.2.3 +urllib3==1.26.20 # via # -c requirements/edx/../common_constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/kernel.in b/requirements/edx/kernel.in index d1a1327781..a17b9db4c8 100644 --- a/requirements/edx/kernel.in +++ b/requirements/edx/kernel.in @@ -84,7 +84,6 @@ edx-rest-api-client edx-search edx-submissions edx-toggles # Feature toggles management -edx-token-utils # Validate exam access tokens edx-when edxval event-tracking diff --git a/requirements/edx/semgrep.txt b/requirements/edx/semgrep.txt index 65a0b794b9..0caf869df7 100644 --- a/requirements/edx/semgrep.txt +++ b/requirements/edx/semgrep.txt @@ -125,7 +125,7 @@ typing-extensions==4.12.2 # opentelemetry-sdk # referencing # semgrep -urllib3==2.2.3 +urllib3==2.3.0 # via # -c requirements/edx/../common_constraints.txt # requests diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 799f8b16ed..29bc1e960b 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -306,7 +306,6 @@ django==4.2.18 # edx-search # edx-submissions # edx-toggles - # edx-token-utils # edx-when # edxval # enmerkar @@ -660,7 +659,7 @@ edx-when==2.5.1 # edx-proctoring edxval==2.9.0 # via -r requirements/edx/base.txt -elasticsearch==7.9.1 +elasticsearch==7.13.4 # via # -c requirements/edx/../common_constraints.txt # -c requirements/edx/../constraints.txt @@ -1211,7 +1210,6 @@ pygments==2.19.1 pyjwkest==1.4.2 # via # -r requirements/edx/base.txt - # edx-token-utils # lti-consumer-xblock pyjwt[crypto]==2.10.1 # via @@ -1615,7 +1613,7 @@ uritemplate==4.1.1 # drf-spectacular # drf-yasg # google-api-python-client -urllib3==2.2.3 +urllib3==1.26.20 # via # -c requirements/edx/../common_constraints.txt # -r requirements/edx/base.txt diff --git a/scripts/xblock/requirements.txt b/scripts/xblock/requirements.txt index 9af137853d..aabed41ba0 100644 --- a/scripts/xblock/requirements.txt +++ b/scripts/xblock/requirements.txt @@ -14,7 +14,5 @@ idna==3.10 # via requests requests==2.32.3 # via -r scripts/xblock/requirements.in -urllib3==2.2.3 - # via - # -c scripts/xblock/../../requirements/common_constraints.txt - # requests +urllib3==2.3.0 + # via requests