feat: add user_id in the default scopes

This commit is contained in:
Ehmad Saeed
2024-03-12 22:37:15 +05:00
parent 4a8cc1e77e
commit 51de2c6197
4 changed files with 62 additions and 4 deletions

View File

@@ -94,11 +94,13 @@ class EdxOAuth2Validator(OAuth2Validator):
def get_default_scopes(self, client_id, request, *args, **kwargs):
"""
If the request payload does not have `scopes` attribute for a grant_type of
client credentials, it should use available scopes as default.
client credentials, it should add `user_id` in the default scopes.
"""
default_scopes = super().get_default_scopes(client_id, request, *args, **kwargs)
if request.grant_type == 'client_credentials' and not request.scopes:
return get_scopes_backend().get_available_scopes(application=request.client, request=request)
return super().get_default_scopes(client_id, request, *args, **kwargs)
if get_scopes_backend().has_user_id_in_application_scopes(application=request.client):
default_scopes.append('user_id')
return default_scopes
def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs):
"""

View File

@@ -22,3 +22,15 @@ class ApplicationModelScopes(SettingsScopes):
default_scopes = self.get_default_scopes()
all_scopes = list(self.get_all_scopes().keys())
return set(application_scopes + default_scopes).intersection(all_scopes)
def has_user_id_in_application_scopes(self, application):
"""
Returns the user id associated with the given application.
"""
try:
application_scopes = ApplicationAccess.get_scopes(application)
if 'user_id' in application_scopes:
return True
except ApplicationAccess.DoesNotExist:
return False
return False

View File

@@ -5,6 +5,7 @@ Test of custom django-oauth-toolkit behavior
# pylint: disable=protected-access
import datetime
from unittest import mock
from django.conf import settings
from django.test import RequestFactory, TestCase
@@ -77,6 +78,40 @@ class CustomValidationTestCase(TestCase):
request = self.request_factory.get('/')
assert self.validator.validate_user('darkhelmet', self.TEST_PASSWORD, client=None, request=request)
@mock.patch(
'openedx.core.djangoapps.oauth_dispatch.scopes.ApplicationModelScopes.has_user_id_in_application_scopes'
)
@mock.patch('oauth2_provider.oauth2_validators.OAuth2Validator.get_default_scopes')
def test_get_updated_default_scopes(self, mock_get_default_scopes, mock_has_user_id_in_application_scopes):
"""
Test that get_default_scopes returns the default scopes plus the user_id scope if it's available.
"""
default_scopes = ['profile', 'email']
mock_get_default_scopes.return_value = default_scopes.copy()
mock_has_user_id_in_application_scopes.return_value = True
request = mock.Mock(grant_type='client_credentials', client=None, scopes=None)
overriden_default_scopes = self.validator.get_default_scopes(request=request, client_id='client_id')
self.assertEqual(overriden_default_scopes, default_scopes + ['user_id'])
@mock.patch(
'openedx.core.djangoapps.oauth_dispatch.scopes.ApplicationModelScopes.has_user_id_in_application_scopes'
)
@mock.patch('oauth2_provider.oauth2_validators.OAuth2Validator.get_default_scopes')
def test_get_default_scopes(self, mock_get_default_scopes, mock_has_user_id_in_application_scopes):
"""
Test that get_default_scopes returns the default scopes if user_id scope is not available.
"""
default_scopes = ['profile', 'email']
mock_get_default_scopes.return_value = default_scopes.copy()
mock_has_user_id_in_application_scopes.return_value = False
request = mock.Mock(grant_type='client_credentials', client=None, scopes=None)
overriden_default_scopes = self.validator.get_default_scopes(request=request, client_id='client_id')
self.assertEqual(overriden_default_scopes, default_scopes)
@skip_unless_lms
class CustomAuthorizationViewTestCase(TestCase):

View File

@@ -30,4 +30,13 @@ class ApplicationModelScopesTestCase(TestCase):
application_access = ApplicationAccessFactory(scopes=application_scopes)
scopes = ApplicationModelScopes()
assert set(scopes.get_available_scopes(application_access.application)) == \
set(list(settings.OAUTH2_DEFAULT_SCOPES.keys()) + expected_additional_scopes)
set(list(settings.OAUTH2_DEFAULT_SCOPES.keys()) + expected_additional_scopes)
def test_has_user_id_in_application_scopes(self):
""" Verify the settings backend correctly identifies whether the user_id scope is available. """
application_access = ApplicationAccessFactory(scopes=['user_id'])
scopes = ApplicationModelScopes()
assert scopes.has_user_id_in_application_scopes(application_access.application)
application_access.scopes = []
application_access.save()
assert not scopes.has_user_id_in_application_scopes(application_access.application)