Skip to content

Commit

Permalink
feat: allow for forcing asymmetric jwts (openedx#32045)
Browse files Browse the repository at this point in the history
Add a temporary feature toggle to force the LMS to
only produce asymmetric JWTs. This is a part of
DEPR of Symmetric JWTs:
openedx/public-engineering#83
  • Loading branch information
robrap authored Apr 10, 2023
1 parent 1e35bc1 commit 6cae1fa
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
26 changes: 25 additions & 1 deletion openedx/core/djangoapps/oauth_dispatch/jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from time import time

from django.conf import settings
from edx_django_utils.monitoring import set_custom_attribute
from edx_django_utils.monitoring import increment, set_custom_attribute
from edx_rbac.utils import create_role_auth_claim_for_user
from edx_toggles.toggles import SettingToggle
from jwkest import jwk
from jwkest.jws import JWS

Expand Down Expand Up @@ -159,6 +160,12 @@ def _create_jwt(
secret (string): Overrides configured JWT secret (signing) key.
"""
use_asymmetric_key = _get_use_asymmetric_key_value(is_restricted, use_asymmetric_key)
# Enable monitoring of key type used. Use increment in case there are multiple calls in a transaction.
if use_asymmetric_key:
increment('create_asymmetric_jwt_count')
else:
increment('create_symmetric_jwt_count')

# Default scopes should only contain non-privileged data.
# Do not be misled by the fact that `email` and `profile` are default scopes. They
# were included for legacy compatibility, even though they contain privileged data.
Expand Down Expand Up @@ -188,10 +195,27 @@ def _create_jwt(
return _encode_and_sign(payload, use_asymmetric_key, secret)


# .. toggle_name: JWT_AUTH_FORCE_CREATE_ASYMMETRIC
# .. toggle_implementation: SettingToggle
# .. toggle_default: False
# .. toggle_description: When True, forces the LMS to only create JWTs signed with the asymmetric
# key. This is a temporary rollout toggle for DEPR of symmetric JWTs.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2023-04-10
# .. toggle_target_removal_date: 2023-07-31
# .. toggle_tickets: https://github.com/openedx/public-engineering/issues/83
JWT_AUTH_FORCE_CREATE_ASYMMETRIC = SettingToggle(
'JWT_AUTH_FORCE_CREATE_ASYMMETRIC', default=False, module_name=__name__
)


def _get_use_asymmetric_key_value(is_restricted, use_asymmetric_key):
"""
Returns the value to use for use_asymmetric_key.
"""
if JWT_AUTH_FORCE_CREATE_ASYMMETRIC.is_enabled():
return True

return use_asymmetric_key or is_restricted


Expand Down
5 changes: 5 additions & 0 deletions openedx/core/djangoapps/oauth_dispatch/tests/test_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ def test_dot_create_jwt_for_token_with_asymmetric(self):
jwt_token = self._create_jwt_for_token(DOTAdapter(), use_asymmetric_key=True)
self._assert_jwt_is_valid(jwt_token, should_be_asymmetric_key=True)

@override_settings(JWT_AUTH_FORCE_CREATE_ASYMMETRIC=True)
def test_dot_create_jwt_for_token_forced_asymmetric(self):
jwt_token = self._create_jwt_for_token(DOTAdapter(), use_asymmetric_key=False)
self._assert_jwt_is_valid(jwt_token, should_be_asymmetric_key=True)

def test_create_jwt_for_token_default_expire_seconds(self):
oauth_adapter = DOTAdapter()
jwt_token = self._create_jwt_for_token(oauth_adapter, use_asymmetric_key=False)
Expand Down

0 comments on commit 6cae1fa

Please sign in to comment.