Commit f1c4a449 by Cliff Dyer

Merge pull request #12152 from edx/cdyer/oauth-toolkit-allow-inactive

Fix django-oauth-toolkit email and inactive user issues
parents 72c058f2 28ab627a
"""
Classes that override default django-oauth-toolkit behavior
"""
from django.contrib.auth import authenticate, get_user_model
from oauth2_provider.oauth2_validators import OAuth2Validator
class EdxOAuth2Validator(OAuth2Validator):
"""
Validator class that implements edX-specific custom behavior:
* It allows users to log in with their email or username.
* It does not require users to be active before logging in.
"""
def validate_user(self, username, password, client, request, *args, **kwargs):
"""
Authenticate users, but allow inactive users (with u.is_active == False)
to authenticate.
"""
user = self._authenticate(username=username, password=password)
if user is not None:
request.user = user
return True
return False
def _authenticate(self, username, password):
"""
Authenticate the user, allowing the user to identify themself either by
username or email
"""
authenticated_user = authenticate(username=username, password=password)
if authenticated_user is None:
UserModel = get_user_model() # pylint: disable=invalid-name
try:
email_user = UserModel.objects.get(email=username)
except UserModel.DoesNotExist:
authenticated_user = None
else:
authenticated_user = authenticate(username=email_user.username, password=password)
return authenticated_user
"""
Test of custom django-oauth-toolkit behavior
"""
# pylint: disable=protected-access
from django.contrib.auth.models import User
from django.test import TestCase, RequestFactory
from ..dot_overrides import EdxOAuth2Validator
class AuthenticateTestCase(TestCase):
"""
Test that users can authenticate with either username or email
"""
def setUp(self):
super(AuthenticateTestCase, self).setUp()
self.user = User.objects.create_user(
username='darkhelmet',
password='12345',
email='darkhelmet@spaceball_one.org',
)
self.validator = EdxOAuth2Validator()
def test_authenticate_with_username(self):
user = self.validator._authenticate(username='darkhelmet', password='12345')
self.assertEqual(
self.user,
user
)
def test_authenticate_with_email(self):
user = self.validator._authenticate(username='darkhelmet@spaceball_one.org', password='12345')
self.assertEqual(
self.user,
user
)
class CustomValidationTestCase(TestCase):
"""
Test custom user validation works.
In particular, inactive users should be able to validate.
"""
def setUp(self):
super(CustomValidationTestCase, self).setUp()
self.user = User.objects.create_user(
username='darkhelmet',
password='12345',
email='darkhelmet@spaceball_one.org',
)
self.validator = EdxOAuth2Validator()
self.request_factory = RequestFactory()
def test_active_user_validates(self):
self.assertTrue(self.user.is_active)
request = self.request_factory.get('/')
self.assertTrue(self.validator.validate_user('darkhelmet', '12345', client=None, request=request))
def test_inactive_user_validates(self):
self.user.is_active = False
self.user.save()
request = self.request_factory.get('/')
self.assertTrue(self.validator.validate_user('darkhelmet', '12345', client=None, request=request))
......@@ -455,6 +455,12 @@ OAUTH_OIDC_USERINFO_HANDLERS = (
OAUTH_EXPIRE_CONFIDENTIAL_CLIENT_DAYS = 365
OAUTH_EXPIRE_PUBLIC_CLIENT_DAYS = 30
################################## DJANGO OAUTH TOOLKIT #######################################
OAUTH2_PROVIDER = {
'OAUTH2_VALIDATOR_CLASS': 'lms.djangoapps.oauth_dispatch.dot_overrides.EdxOAuth2Validator'
}
################################## TEMPLATE CONFIGURATION #####################################
# Mako templating
# TODO: Move the Mako templating into a different engine in TEMPLATES below.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment