Skip to content

Commit fb28a8d

Browse files
Kelketekxitij2000
authored andcommitted
feat: Allow trusted apps to perform cookie login.
1 parent ab6d8cb commit fb28a8d

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

openedx/core/djangoapps/auth_exchange/tests/test_views.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,15 @@ def _verify_response(self, access_token, expected_status_code, token_type='Beare
168168
if expected_cookie_name:
169169
assert expected_cookie_name in response.cookies
170170

171-
def _create_dot_access_token(self, grant_type='Client credentials'):
171+
def _create_dot_access_token(self, grant_type='Client credentials', skip_authorization=False):
172172
"""
173173
Create dot based access token
174174
"""
175-
dot_application = dot_factories.ApplicationFactory(user=self.user, authorization_grant_type=grant_type)
175+
dot_application = dot_factories.ApplicationFactory(
176+
user=self.user,
177+
authorization_grant_type=grant_type,
178+
skip_authorization=skip_authorization,
179+
)
176180
return dot_factories.AccessTokenFactory(user=self.user, application=dot_application)
177181

178182
def test_failure_with_invalid_token(self):
@@ -189,6 +193,10 @@ def test_failure_with_dot_client_credentials_unsupported(self):
189193
access_token = self._create_dot_access_token()
190194
self._verify_response(access_token, expected_status_code=401)
191195

196+
def test_dot_client_credentials_supported_if_authorization_skipped(self):
197+
access_token = self._create_dot_access_token(skip_authorization=True)
198+
self._verify_response(access_token, expected_status_code=204, expected_cookie_name='sessionid')
199+
192200
def _create_jwt_token(self, grant_type='password', scope='email profile', use_asymmetric_key=True):
193201
"""
194202
Create jwt token

openedx/core/djangoapps/auth_exchange/views.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,10 @@ def _get_path_of_arbitrary_backend_for_user(user):
132132
return backend_path
133133

134134
@staticmethod
135-
def _ensure_access_token_has_password_grant(request):
135+
def _ensure_access_token_has_password_grant_or_privileged_application(request):
136136
"""
137-
Ensures the access token provided has password type grant.
137+
Ensures the access token provided has password type grant, or if 'skip_authorization'
138+
has been enabled, implying this is a trusted application.
138139
"""
139140
if is_jwt_authenticated(request):
140141
jwt_payload = get_decoded_jwt_from_auth(request)
@@ -143,12 +144,17 @@ def _ensure_access_token_has_password_grant(request):
143144
else:
144145
token_query = dot_models.AccessToken.objects.select_related('user')
145146
dot_token = token_query.filter(token=request.auth).first()
146-
if dot_token and dot_token.application.authorization_grant_type == dot_models.Application.GRANT_PASSWORD:
147+
if dot_token and (
148+
dot_token.application.authorization_grant_type == dot_models.Application.GRANT_PASSWORD
149+
or dot_token.application.skip_authorization
150+
):
147151
return
148152

149153
raise AuthenticationFailed({
150154
'error_code': 'non_supported_token',
151-
'developer_message': 'Only access tokens with grant type password are supported.'
155+
'developer_message': 'Only Django Oauth Toolkit access tokens for applications which '
156+
'are trusted (with "skip_authentication" set to True, or with grant type '
157+
'password) are supported.'
152158
})
153159

154160
@staticmethod
@@ -194,7 +200,7 @@ def post(self, request):
194200
request.user.backend = self._get_path_of_arbitrary_backend_for_user(request.user)
195201

196202
self._ensure_user_is_not_disabled(request)
197-
self._ensure_access_token_has_password_grant(request)
203+
self._ensure_access_token_has_password_grant_or_privileged_application(request)
198204
self._ensure_jwt_is_asymmetric(request)
199205

200206
login(request, request.user) # login generates and stores the user's cookies in the session

0 commit comments

Comments
 (0)