Skip to content
Snippets Groups Projects
Commit 8056d89f authored by Diana Huang's avatar Diana Huang
Browse files

Create new auth endpoint for checking user password.

parent c3bb21c7
No related branches found
No related tags found
No related merge requests found
......@@ -638,3 +638,55 @@ class LoginOAuthTokenTestFacebook(LoginOAuthTokenMixin, ThirdPartyOAuthTestMixin
class LoginOAuthTokenTestGoogle(LoginOAuthTokenMixin, ThirdPartyOAuthTestMixinGoogle, TestCase):
"""Tests login_oauth_token with the Google backend"""
pass
class TestPasswordVerificationView(CacheIsolationTestCase):
"""
Test the password verification endpoint.
"""
def setUp(self):
super(TestPasswordVerificationView, self).setUp()
self.user = UserFactory.build(username='test_user', is_active=True)
self.password = 'test_password'
self.user.set_password(self.password)
self.user.save()
# Create a registration for the user
RegistrationFactory(user=self.user)
# Create a profile for the user
UserProfileFactory(user=self.user)
# Create the test client
self.client = Client()
cache.clear()
self.url = reverse('verify_password')
def test_password_logged_in_valid(self):
success = self.client.login(username=self.user.username, password=self.password)
assert success
response = self.client.post(self.url, {'password': self.password})
assert response.status_code == 200
def test_password_logged_in_invalid(self):
success = self.client.login(username=self.user.username, password=self.password)
assert success
response = self.client.post(self.url, {'password': 'wrong_password'})
assert response.status_code == 403
def test_password_logged_out(self):
response = self.client.post(self.url, {'username': self.user.username, 'password': self.password})
assert response.status_code == 302
@patch.dict("django.conf.settings.FEATURES", {'ENABLE_MAX_FAILED_LOGIN_ATTEMPTS': True})
@override_settings(MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS=6000)
def test_locked_out(self):
success = self.client.login(username=self.user.username, password=self.password)
assert success
# Attempt a password check greater than the number of allowed times.
for _ in xrange(settings.MAX_FAILED_LOGIN_ATTEMPTS_ALLOWED + 1):
self.client.post(self.url, {'password': 'wrong_password'})
response = self.client.post(self.url, {'password': self.password})
assert response.status_code == 403
assert response.content == ('This account has been temporarily locked due '
'to excessive login failures. Try again later.')
......@@ -37,10 +37,12 @@ urlpatterns = [
views.password_reset_confirm_wrapper,
name='password_reset_confirm',
),
url(r'accounts/verify_password', views.verify_user_password, name='verify_password'),
url(r'^course_run/{}/refund_status$'.format(settings.COURSE_ID_PATTERN),
views.course_run_refund_status,
name="course_run_refund_status"),
]
# enable automatic login
......
......@@ -15,6 +15,7 @@ import edx_oauth2_provider
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import authenticate, load_backend, login as django_login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import AnonymousUser, User
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.urlresolvers import NoReverseMatch, reverse, reverse_lazy
......@@ -386,6 +387,32 @@ def send_reactivation_email_for_user(user):
return JsonResponse({"success": True})
@login_required
@ensure_csrf_cookie
def verify_user_password(request):
"""
If the user is logged in and we want to verify that they have submitted the correct password
for a major account change (for example, retiring this user's account).
Args:
request (HttpRequest): A request object where the password should be included in the POST fields.
"""
try:
_check_excessive_login_attempts(request.user)
user = authenticate(username=request.user.username, password=request.POST['password'], request=request)
if user:
if LoginFailures.is_feature_enabled():
LoginFailures.clear_lockout_counter(user)
return JsonResponse({'success': True})
else:
_handle_failed_authentication(request.user)
except AuthFailedError as err:
return HttpResponse(err.value, content_type="text/plain", status=403)
except Exception: # pylint: disable=broad-except
log.exception("Could not verify user password")
return HttpResponseBadRequest()
@ensure_csrf_cookie
def login_user(request):
"""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment