diff --git a/common/djangoapps/enrollment/tests/test_views.py b/common/djangoapps/enrollment/tests/test_views.py index 42a7aff93f..edaff1fe41 100644 --- a/common/djangoapps/enrollment/tests/test_views.py +++ b/common/djangoapps/enrollment/tests/test_views.py @@ -28,16 +28,16 @@ from enrollment import api from enrollment.errors import CourseEnrollmentError from enrollment.views import EnrollmentUserThrottle from openedx.core.djangoapps.content.course_overviews.models import CourseOverview +from openedx.core.djangoapps.course_groups import cohorts from openedx.core.djangoapps.embargo.models import Country, CountryAccessRule, RestrictedCourse from openedx.core.djangoapps.embargo.test_utils import restrict_course -from openedx.core.djangoapps.course_groups import cohorts +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.user_api.models import ( RetirementState, UserRetirementStatus, UserOrgTag ) from openedx.core.lib.django_test_client_utils import get_absolute_url -from openedx.core.lib.token_utils import JwtBuilder from openedx.features.enterprise_support.tests import FAKE_ENTERPRISE_CUSTOMER from openedx.features.enterprise_support.tests.mixins.enterprise import EnterpriseServiceMockMixin from student.models import ( @@ -1340,7 +1340,7 @@ class UnenrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase): """ Helper function for creating headers for the JWT authentication. """ - token = JwtBuilder(user).build_token([]) + token = create_jwt_for_user(user) headers = {'HTTP_AUTHORIZATION': 'JWT ' + token} return headers diff --git a/lms/djangoapps/commerce/tests/__init__.py b/lms/djangoapps/commerce/tests/__init__.py index 4ae655e335..3999d262e0 100644 --- a/lms/djangoapps/commerce/tests/__init__.py +++ b/lms/djangoapps/commerce/tests/__init__.py @@ -8,7 +8,7 @@ from django.test import TestCase from freezegun import freeze_time from openedx.core.djangoapps.commerce.utils import ecommerce_api_client -from openedx.core.lib.token_utils import JwtBuilder +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from student.tests.factories import UserFactory JSON = 'application/json' @@ -62,7 +62,7 @@ class EdxRestApiClientTest(TestCase): 'lms_ip': '127.0.0.1', } } - expected_jwt = JwtBuilder(self.user).build_token(['email', 'profile'], additional_claims=claims) + expected_jwt = create_jwt_for_user(self.user, additional_claims=claims) expected_header = 'JWT {}'.format(expected_jwt) self.assertEqual(actual_header, expected_header) diff --git a/lms/djangoapps/discussion_api/tests/test_views.py b/lms/djangoapps/discussion_api/tests/test_views.py index 3f8deca412..e08eac6dd3 100644 --- a/lms/djangoapps/discussion_api/tests/test_views.py +++ b/lms/djangoapps/discussion_api/tests/test_views.py @@ -26,10 +26,10 @@ from discussion_api.tests.utils import ( make_paginated_api_response ) from django_comment_client.tests.utils import ForumsEnableMixin +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus from openedx.core.lib.tests import attr -from openedx.core.lib.token_utils import JwtBuilder from student.models import get_retired_username_by_username from student.tests.factories import CourseEnrollmentFactory, UserFactory, SuperuserFactory from util.testing import PatchMediaTypeMixin, UrlResetMixin @@ -190,7 +190,7 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): """ Helper function for creating headers for the JWT authentication. """ - token = JwtBuilder(user).build_token([]) + token = create_jwt_for_user(user) headers = {'HTTP_AUTHORIZATION': 'JWT ' + token} return headers diff --git a/lms/djangoapps/edxnotes/helpers.py b/lms/djangoapps/edxnotes/helpers.py index 8c42da5ef7..b5e92c8c2c 100644 --- a/lms/djangoapps/edxnotes/helpers.py +++ b/lms/djangoapps/edxnotes/helpers.py @@ -24,7 +24,7 @@ from courseware.courses import get_current_child from edxnotes.exceptions import EdxNotesParseError, EdxNotesServiceUnavailable from edxnotes.plugins import EdxNotesTab from lms.lib.utils import get_parent_unit -from openedx.core.lib.token_utils import JwtBuilder +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from student.models import anonymous_id_for_user from util.date_utils import get_default_time_display from xmodule.modulestore.django import modulestore @@ -59,12 +59,7 @@ def get_edxnotes_id_token(user): raise ImproperlyConfigured( 'OAuth2 Client with name [{}] does not exist.'.format(CLIENT_NAME) ) - - scopes = ['email', 'profile'] - expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION - jwt = JwtBuilder(user, secret=client.client_secret).build_token(scopes, expires_in, aud=client.client_id) - - return jwt + return create_jwt_for_user(user, secret=client.client_secret, aud=client.client_id) def get_token_url(course_id): diff --git a/lms/djangoapps/edxnotes/tests.py b/lms/djangoapps/edxnotes/tests.py index f5fcfabe80..48824d4367 100644 --- a/lms/djangoapps/edxnotes/tests.py +++ b/lms/djangoapps/edxnotes/tests.py @@ -27,9 +27,9 @@ from edxnotes import helpers from edxnotes.decorators import edxnotes from edxnotes.exceptions import EdxNotesParseError, EdxNotesServiceUnavailable from edxnotes.plugins import EdxNotesTab +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus from openedx.core.lib.tests import attr -from openedx.core.lib.token_utils import JwtBuilder from student.tests.factories import CourseEnrollmentFactory, SuperuserFactory, UserFactory from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore @@ -1185,7 +1185,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase): """ Helper function for creating headers for the JWT authentication. """ - token = JwtBuilder(user).build_token([]) + token = create_jwt_for_user(user) headers = {'HTTP_AUTHORIZATION': 'JWT ' + token} return headers diff --git a/openedx/core/djangoapps/catalog/utils.py b/openedx/core/djangoapps/catalog/utils.py index ece807f53d..a823153f2c 100644 --- a/openedx/core/djangoapps/catalog/utils.py +++ b/openedx/core/djangoapps/catalog/utils.py @@ -18,8 +18,8 @@ from openedx.core.djangoapps.catalog.cache import (PATHWAY_CACHE_KEY_TPL, PROGRA SITE_PATHWAY_IDS_CACHE_KEY_TPL, SITE_PROGRAM_UUIDS_CACHE_KEY_TPL) from openedx.core.djangoapps.catalog.models import CatalogIntegration +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.lib.edx_api_utils import get_edx_api_data -from openedx.core.lib.token_utils import JwtBuilder from student.models import CourseEnrollment logger = logging.getLogger(__name__) @@ -27,9 +27,7 @@ logger = logging.getLogger(__name__) def create_catalog_api_client(user, site=None): """Returns an API client which can be used to make Catalog API requests.""" - scopes = ['email', 'profile'] - expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION - jwt = JwtBuilder(user).build_token(scopes, expires_in) + jwt = create_jwt_for_user(user) if site: url = site.configuration.get_value('COURSE_CATALOG_API_URL') diff --git a/openedx/core/djangoapps/commerce/utils.py b/openedx/core/djangoapps/commerce/utils.py index a7971cd0b8..c020ed21d9 100644 --- a/openedx/core/djangoapps/commerce/utils.py +++ b/openedx/core/djangoapps/commerce/utils.py @@ -3,8 +3,9 @@ from django.conf import settings from edx_rest_api_client.client import EdxRestApiClient from eventtracking import tracker +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.lib.token_utils import JwtBuilder + ECOMMERCE_DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' @@ -29,10 +30,10 @@ def is_commerce_service_configured(): return bool(ecommerce_api_url) -def ecommerce_api_client(user, session=None, token_expiration=None): +def ecommerce_api_client(user, session=None): """ Returns an E-Commerce API client setup with authentication for the specified user. """ claims = {'tracking_context': create_tracking_context(user)} - jwt = JwtBuilder(user).build_token(['email', 'profile'], expires_in=token_expiration, additional_claims=claims) + jwt = create_jwt_for_user(user, additional_claims=claims) return EdxRestApiClient( configuration_helpers.get_value('ECOMMERCE_API_URL', settings.ECOMMERCE_API_URL), diff --git a/openedx/core/djangoapps/credentials/utils.py b/openedx/core/djangoapps/credentials/utils.py index 25eb37649e..98dfbec430 100644 --- a/openedx/core/djangoapps/credentials/utils.py +++ b/openedx/core/djangoapps/credentials/utils.py @@ -5,8 +5,8 @@ from django.conf import settings from edx_rest_api_client.client import EdxRestApiClient from openedx.core.djangoapps.credentials.models import CredentialsApiConfig +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.lib.edx_api_utils import get_edx_api_data -from openedx.core.lib.token_utils import JwtBuilder def get_credentials_records_url(program_uuid=None): @@ -35,10 +35,7 @@ def get_credentials_api_client(user, org=None): org (str): Optional organization to look up the site config for, rather than the current request """ - - scopes = ['email', 'profile'] - expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION - jwt = JwtBuilder(user).build_token(scopes, expires_in) + jwt = create_jwt_for_user(user) if org is None: url = CredentialsApiConfig.current().internal_api_url # by current request diff --git a/openedx/core/djangoapps/credit/tests/test_views.py b/openedx/core/djangoapps/credit/tests/test_views.py index f529168528..d786f279b7 100644 --- a/openedx/core/djangoapps/credit/tests/test_views.py +++ b/openedx/core/djangoapps/credit/tests/test_views.py @@ -24,9 +24,9 @@ from openedx.core.djangoapps.credit.signature import signature from openedx.core.djangoapps.credit.tests.factories import ( CreditProviderFactory, CreditEligibilityFactory, CreditCourseFactory, CreditRequestFactory, ) +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangolib.testing.utils import skip_unless_lms from openedx.core.lib.tests import attr -from openedx.core.lib.token_utils import JwtBuilder from student.tests.factories import UserFactory, AdminFactory from util.date_utils import to_timestamp @@ -88,9 +88,7 @@ class AuthMixin(object): def test_jwt_auth(self): """ verify the endpoints JWT authentication. """ - scopes = ['email', 'profile'] - expires_in = settings.OAUTH_ID_TOKEN_EXPIRATION - token = JwtBuilder(self.user).build_token(scopes, expires_in) + token = create_jwt_for_user(self.user) headers = { 'HTTP_AUTHORIZATION': 'JWT ' + token } diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py index 1a3cc6c5fd..e07740ad92 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py @@ -44,6 +44,7 @@ from openedx.core.djangoapps.credit.models import ( CreditRequirementStatus, CreditRequest, CreditCourse, CreditProvider, CreditRequirement ) from openedx.core.djangoapps.course_groups.models import CourseUserGroup, UnregisteredLearnerCohortAssignments +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory from openedx.core.djangoapps.user_api.accounts.signals import USER_RETIRE_THIRD_PARTY_MAILINGS from openedx.core.djangoapps.user_api.models import ( @@ -53,7 +54,6 @@ from openedx.core.djangoapps.user_api.models import ( UserOrgTag ) from openedx.core.djangoapps.user_api.accounts.views import AccountRetirementPartnerReportView -from openedx.core.lib.token_utils import JwtBuilder from student.models import ( CourseEnrollment, CourseEnrollmentAllowed, @@ -90,7 +90,7 @@ def build_jwt_headers(user): """ Helper function for creating headers for the JWT authentication. """ - token = JwtBuilder(user).build_token([]) + token = create_jwt_for_user(user) headers = { 'HTTP_AUTHORIZATION': 'JWT ' + token } diff --git a/openedx/core/djangoapps/video_pipeline/utils.py b/openedx/core/djangoapps/video_pipeline/utils.py index 58290d96ac..85b1e10e30 100644 --- a/openedx/core/djangoapps/video_pipeline/utils.py +++ b/openedx/core/djangoapps/video_pipeline/utils.py @@ -4,7 +4,7 @@ Utils for video_pipeline app. from django.conf import settings from edx_rest_api_client.client import EdxRestApiClient -from openedx.core.lib.token_utils import JwtBuilder +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user def create_video_pipeline_api_client(user, api_client_id, api_client_secret, api_url): @@ -17,9 +17,5 @@ def create_video_pipeline_api_client(user, api_client_id, api_client_secret, api api_client_secret(unicode): Video pipeline client secret. api_url(unicode): It is video pipeline's API URL. """ - jwt_token = JwtBuilder(user, secret=api_client_secret).build_token( - scopes=[], - expires_in=settings.OAUTH_ID_TOKEN_EXPIRATION, - aud=api_client_id - ) + jwt_token = create_jwt_for_user(user, secret=api_client_secret, aud=api_client_id) return EdxRestApiClient(api_url, jwt=jwt_token) diff --git a/openedx/core/lib/tests/test_token_utils.py b/openedx/core/lib/tests/test_token_utils.py deleted file mode 100644 index f2ea488d6d..0000000000 --- a/openedx/core/lib/tests/test_token_utils.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Tests covering the JwtBuilder utility.""" -import ddt -from django.test import TestCase - -from openedx.core.djangoapps.oauth_dispatch.tests import mixins -from openedx.core.lib.token_utils import JwtBuilder -from student.tests.factories import UserFactory, UserProfileFactory - - -@ddt.ddt -class TestDeprecatedJwtBuilder(mixins.AccessTokenMixin, TestCase): - """ - Test class for the deprecated JwtBuilder class. - """ - - expires_in = 10 - shard = 2 - - def setUp(self): - super(TestDeprecatedJwtBuilder, self).setUp() - - self.user = UserFactory() - self.profile = UserProfileFactory(user=self.user) - self.scopes = ['email', 'profile'] - - def test_jwt_construction(self): - """ - Verify that a valid JWT is built, including claims for the requested scopes. - """ - token = JwtBuilder(self.user).build_token(expires_in=self.expires_in) - self.assert_valid_jwt_access_token(token, self.user, self.scopes) - - def test_user_profile_missing(self): - """ - Verify that token construction succeeds if the UserProfile is missing. - """ - self.profile.delete() - - token = JwtBuilder(self.user).build_token(expires_in=self.expires_in) - self.assert_valid_jwt_access_token(token, self.user, self.scopes) - - def test_override_secret_and_audience(self): - """ - Verify that the signing key and audience can be overridden. - """ - secret = 'avoid-this' - audience = 'avoid-this-too' - - token = JwtBuilder( - self.user, - secret=secret, - ).build_token( - expires_in=self.expires_in, - aud=audience, - ) - self.assert_valid_jwt_access_token(token, self.user, self.scopes, aud=audience, secret=secret) diff --git a/openedx/core/lib/token_utils.py b/openedx/core/lib/token_utils.py deleted file mode 100644 index 076c460c61..0000000000 --- a/openedx/core/lib/token_utils.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -TODO (ARCH-248) -Deprecated JwtBuilder class. -Use openedx.core.djangoapps.oauth_dispatch.jwt.JwtBuilder directly. -This is here for backward compatibility reasons only. -""" -from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user - - -class JwtBuilder(object): - """ - Deprecated. See module docstring above. - """ - def __init__(self, user, secret=None): - self.user = user - self.secret = secret - - def build_token( - self, - scopes=None, # pylint: disable=unused-argument - expires_in=None, # pylint: disable=unused-argument - aud=None, - additional_claims=None, - ): - """ - Deprecated. See module docstring above. - """ - return create_jwt_for_user( - self.user, - secret=self.secret, - aud=aud, - additional_claims=additional_claims, - ) diff --git a/openedx/features/enterprise_support/api.py b/openedx/features/enterprise_support/api.py index 92ee78d9dd..9783af21aa 100644 --- a/openedx/features/enterprise_support/api.py +++ b/openedx/features/enterprise_support/api.py @@ -15,8 +15,8 @@ from django.utils.translation import ugettext as _ from edx_rest_api_client.client import EdxRestApiClient from slumber.exceptions import HttpClientError, HttpNotFoundError, HttpServerError +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.lib.token_utils import JwtBuilder from openedx.features.enterprise_support.utils import get_cache_key from third_party_auth.pipeline import get as get_partial_pipeline from third_party_auth.provider import Registry @@ -49,7 +49,7 @@ class ConsentApiClient(object): Initialize an authenticated Consent service API client by using the provided user. """ - jwt = JwtBuilder(user).build_token([]) + jwt = create_jwt_for_user(user) url = configuration_helpers.get_value('ENTERPRISE_CONSENT_API_URL', settings.ENTERPRISE_CONSENT_API_URL) self.client = EdxRestApiClient( url, @@ -127,7 +127,7 @@ class EnterpriseApiClient(object): provided user. """ self.user = user - jwt = JwtBuilder(user).build_token([]) + jwt = create_jwt_for_user(user) self.client = EdxRestApiClient( configuration_helpers.get_value('ENTERPRISE_API_URL', settings.ENTERPRISE_API_URL), jwt=jwt diff --git a/openedx/features/enterprise_support/tests/test_api.py b/openedx/features/enterprise_support/tests/test_api.py index fb8f1a0ffa..88683f2618 100644 --- a/openedx/features/enterprise_support/tests/test_api.py +++ b/openedx/features/enterprise_support/tests/test_api.py @@ -67,7 +67,7 @@ class TestEnterpriseApi(EnterpriseServiceMockMixin, CacheIsolationTestCase): Verify that the provided api client uses the enterprise service user to generate JWT token for auth. """ - mocked_jwt_builder.return_value.build_token.return_value = 'test-token' + mocked_jwt_builder.return_value = 'test-token' enterprise_service_user = User.objects.get(username=settings.ENTERPRISE_SERVICE_WORKER_USERNAME) enterprise_api_service_client = api_client() @@ -80,7 +80,7 @@ class TestEnterpriseApi(EnterpriseServiceMockMixin, CacheIsolationTestCase): Verify that the provided api client uses the expected user to generate JWT token for auth. """ - mocked_jwt_builder.return_value.build_token.return_value = 'test-token' + mocked_jwt_builder.return_value = 'test-token' dummy_enterprise_user = UserFactory.create( username='dummy-enterprise-user', email='dummy-enterprise-user@example.com', @@ -117,10 +117,10 @@ class TestEnterpriseApi(EnterpriseServiceMockMixin, CacheIsolationTestCase): self.assertEqual(cached_enterprise_customer, enterprise_customer) @httpretty.activate - @mock.patch('openedx.features.enterprise_support.api.JwtBuilder') + @mock.patch('openedx.features.enterprise_support.api.create_jwt_for_user') def test_enterprise_api_client_with_service_user(self, mock_jwt_builder): """ - Verify that enterprise API service client uses enterprise service user + Verify that enterprise API service client uses enterprcreate_jwt_for_userise service user by default to authenticate and access enterprise API. """ self._assert_api_service_client(EnterpriseApiServiceClient, mock_jwt_builder) @@ -138,7 +138,7 @@ class TestEnterpriseApi(EnterpriseServiceMockMixin, CacheIsolationTestCase): self._assert_get_enterprise_customer(enterprise_api_client, enterprise_api_data_for_mock_2) @httpretty.activate - @mock.patch('openedx.features.enterprise_support.api.JwtBuilder') + @mock.patch('openedx.features.enterprise_support.api.create_jwt_for_user') def test_enterprise_api_client_with_user(self, mock_jwt_builder): """ Verify that enterprise API client uses the provided user to @@ -147,7 +147,7 @@ class TestEnterpriseApi(EnterpriseServiceMockMixin, CacheIsolationTestCase): self._assert_api_client_with_user(EnterpriseApiClient, mock_jwt_builder) @httpretty.activate - @mock.patch('openedx.features.enterprise_support.api.JwtBuilder') + @mock.patch('openedx.features.enterprise_support.api.create_jwt_for_user') def test_enterprise_consent_api_client_with_service_user(self, mock_jwt_builder): """ Verify that enterprise API consent service client uses enterprise @@ -156,7 +156,7 @@ class TestEnterpriseApi(EnterpriseServiceMockMixin, CacheIsolationTestCase): self._assert_api_service_client(ConsentApiServiceClient, mock_jwt_builder) @httpretty.activate - @mock.patch('openedx.features.enterprise_support.api.JwtBuilder') + @mock.patch('openedx.features.enterprise_support.api.create_jwt_for_user') def test_enterprise_consent_api_client_with_user(self, mock_jwt_builder): """ Verify that enterprise API consent service client uses the provided diff --git a/openedx/features/journals/api.py b/openedx/features/journals/api.py index 77baee101a..5014efd729 100644 --- a/openedx/features/journals/api.py +++ b/openedx/features/journals/api.py @@ -12,9 +12,9 @@ from django.core.cache import cache from django.core.exceptions import ObjectDoesNotExist from edx_rest_api_client.client import EdxRestApiClient from openedx.core.djangoapps.catalog.models import CatalogIntegration +from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace -from openedx.core.lib.token_utils import JwtBuilder from slumber.exceptions import HttpClientError, HttpServerError @@ -54,7 +54,7 @@ class DiscoveryApiClient(object): LOGGER.error("Unable to retrieve catalog integration service user") return None - jwt = JwtBuilder(user).build_token([]) + jwt = create_jwt_for_user(user) base_url = configuration_helpers.get_value('COURSE_CATALOG_URL_BASE', settings.COURSE_CATALOG_URL_BASE) self.client = EdxRestApiClient( '{base_url}{journals_path}'.format(base_url=base_url, journals_path=JOURNALS_API_PATH), @@ -110,7 +110,7 @@ class JournalsApiClient(object): LOGGER.error(error) raise ValueError(error) - jwt = JwtBuilder(self.user).build_token(['email', 'profile'], 16000) + jwt = create_jwt_for_user(self.user) self.client = EdxRestApiClient( configuration_helpers.get_value('JOURNALS_API_URL', settings.JOURNALS_API_URL), jwt=jwt