-
-
Notifications
You must be signed in to change notification settings - Fork 449
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #500 from MWeesenaar/enforce-setup-device-on-otp-r…
…equired-page Enforcing a redirect to setup of otp device when none available for user
- Loading branch information
Showing
4 changed files
with
98 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,7 +38,7 @@ def test_valid_login(self, mock_signal): | |
response = self._post({'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, resolve_url(settings.LOGIN_REDIRECT_URL)) | ||
self.assertRedirects(response, reverse('two_factor:setup')) | ||
|
||
# No signal should be fired for non-verified user logins. | ||
self.assertFalse(mock_signal.called) | ||
|
@@ -80,7 +80,8 @@ def test_valid_login_with_allowed_external_redirect(self): | |
{'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, redirect_url, fetch_redirect_response=False) | ||
self.assertEqual(self.client.session.get('next'), redirect_url) | ||
self.assertRedirects(response, reverse('two_factor:setup'), fetch_redirect_response=False) | ||
|
||
def test_valid_login_with_disallowed_external_redirect(self): | ||
redirect_url = 'https://test.disallowed-success-url.com' | ||
|
@@ -90,7 +91,7 @@ def test_valid_login_with_disallowed_external_redirect(self): | |
{'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, reverse('two_factor:profile'), fetch_redirect_response=False) | ||
self.assertRedirects(response, reverse('two_factor:setup'), fetch_redirect_response=False) | ||
|
||
@mock.patch('two_factor.views.core.time') | ||
def test_valid_login_primary_key_stored(self, mock_time): | ||
|
@@ -395,12 +396,12 @@ def test_login_different_user_on_existing_session(self, mock_logger): | |
response = self._post({'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, resolve_url(settings.LOGIN_REDIRECT_URL)) | ||
self.assertRedirects(response, reverse('two_factor:setup')) | ||
|
||
response = self._post({'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, resolve_url(settings.LOGIN_REDIRECT_URL)) | ||
self.assertRedirects(response, reverse('two_factor:setup')) | ||
|
||
def test_missing_management_data(self): | ||
# missing management data | ||
|
@@ -431,8 +432,7 @@ def test_login_different_user_with_otp_on_existing_session(self): | |
response = self._post({'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, | ||
resolve_url(settings.LOGIN_REDIRECT_URL)) | ||
self.assertRedirects(response, reverse('two_factor:setup')) | ||
|
||
response = self._post({'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,12 @@ | ||
from binascii import unhexlify | ||
|
||
from django.conf import settings | ||
from django.shortcuts import resolve_url | ||
from django.test import TestCase | ||
from django.urls import reverse | ||
from django_otp.oath import totp | ||
|
||
from .utils import UserMixin | ||
from .utils import UserMixin, method_registry | ||
|
||
|
||
class OTPRequiredMixinTest(UserMixin, TestCase): | ||
|
@@ -53,3 +57,48 @@ def test_verified(self): | |
self.login_user() | ||
response = self.client.get('/secure/') | ||
self.assertEqual(response.status_code, 200) | ||
|
||
@method_registry(['generator']) | ||
def test_valid_login_with_redirect_field_name_without_device(self): | ||
self.create_user() | ||
protected_url = '/secure/' | ||
|
||
# Open URL that is protected | ||
# assert go to login page | ||
# assert the next param not in the session (but still in url) | ||
response = self.client.get(protected_url) | ||
redirect_url = "%s?%s%s" % (reverse('two_factor:login'), 'next=', protected_url) | ||
self.assertRedirects(response, redirect_url) | ||
self.assertEqual(self.client.session.get('next'), None) | ||
|
||
# Log in given the last redirect | ||
# assert redirect to setup | ||
response = self.client.post( | ||
redirect_url, | ||
{'auth-username': '[email protected]', | ||
'auth-password': 'secret', | ||
'login_view-current_step': 'auth'}) | ||
self.assertRedirects(response, reverse('two_factor:setup')) | ||
self.assertEqual(self.client.session.get('next'), protected_url) | ||
|
||
# Setup the device accordingly | ||
# assert redirect to setup completed | ||
# assert button for redirection to the original page | ||
response = self.client.post( | ||
reverse('two_factor:setup'), | ||
data={'setup_view-current_step': 'welcome'}) | ||
self.assertContains(response, 'Token:') | ||
self.assertContains(response, 'autofocus="autofocus"') | ||
self.assertContains(response, 'inputmode="numeric"') | ||
self.assertContains(response, 'autocomplete="one-time-code"') | ||
|
||
key = response.context_data['keys'].get('generator') | ||
bin_key = unhexlify(key.encode()) | ||
response = self.client.post( | ||
reverse('two_factor:setup'), | ||
data={'setup_view-current_step': 'generator', | ||
'generator-token': totp(bin_key)}, | ||
follow=True, | ||
) | ||
|
||
self.assertRedirects(response, protected_url) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters