Source code for scipost.tests.test_totp

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


import datetime

from django.urls import reverse
from django.test import TestCase, Client

from mock import Mock, patch

from scipost.factories import UserFactory, TOTPDeviceFactory
from scipost.totp import TOTPVerification

# Mock random test time of which the test values are know
# Secret key: 'XTNHYG5OJPQ7ZRDC'
# Valid token: '451977'
mock_time = Mock()
mock_time.return_value = datetime.datetime(2019, 12, 8, 11, 1, 1).timestamp()


[docs]class TOTPVerificationTest(TestCase): """ Test the scipost.totp.TOTPVerification util. """ valid_secret_key = 'XTNHYG5OJPQ7ZRDC' valid_token = '451977'
[docs] def setUp(self): super().setUp() self.client = Client()
[docs] @classmethod def setUpTestData(cls): super().setUpTestData() cls.password = 'super_secret_123' cls.user = UserFactory(contrib=None) cls.user.set_password(cls.password) cls.user.save()
[docs] @patch('time.time', mock_time) def test_proper_return_classmethod(self): """Test if valid secret_key/time/token combinations return True.""" self.assertTrue(TOTPVerification.verify_token(self.valid_secret_key, self.valid_token)) self.assertFalse(TOTPVerification.verify_token('XTNHYG5OJPQ7ZRDX', self.valid_token)) self.assertFalse(TOTPVerification.verify_token(self.valid_secret_key, '4519000'))
[docs] def test_2fa_workaround_closed(self): """ Test if the admin login form is disabled. It's an easy workaround for 2FA. """ # Test GET request self.client.logout() response = self.client.get('/admin') self.assertEqual(response.status_code, 301) # Disabled by permanent redirect # Test POST request response = self.client.post('/admin', follow=True, data={ 'username': self.user.username, 'password': self.password, 'next': '/' }) self.assertNotEqual(response.context['user'], self.user) self.assertEqual(response.redirect_chain[0][0], '/admin/') self.assertEqual(response.redirect_chain[0][1], 301) # Check if immediately redirected
[docs] @patch('time.time', mock_time) def test_proper_login_procedure(self): """Test if CBV fails gently if not used properly.""" login_url = reverse('scipost:login') response = self.client.get(login_url) self.assertEqual(response.status_code, 200) # Does posting work? response = self.client.post( login_url, follow=True, data={ 'username': self.user.username, 'password': self.password, 'next': '/', 'code': '' }) self.assertEqual(response.context['user'], self.user) self.assertEqual(response.redirect_chain[-1][0], '/') # Check if eventually redirected self.assertEqual(response.redirect_chain[-1][1], 302) # Logout for next step self.client.logout() # Check if a simple login without code fails if device is set up. TOTPDeviceFactory.create(user=self.user, token=self.valid_secret_key) response = self.client.post( login_url, follow=True, data={ 'username': self.user.username, 'password': self.password, 'next': '/', 'code': '' }) self.assertNotEqual(response.context['user'], self.user) # Check if login fails with invalid code response = self.client.post( login_url, follow=True, data={ 'username': self.user.username, 'password': self.password, 'next': '/', 'code': '912334' }) self.assertNotEqual(response.context['user'], self.user) response = self.client.post( login_url, follow=True, data={ 'username': self.user.username, 'password': self.password, 'next': '/', 'code': '000000' }) self.assertNotEqual(response.context['user'], self.user) # Check if login *WORKS* with a valid code. response = self.client.post( login_url, follow=True, data={ 'username': self.user.username, 'password': self.password, 'next': '/', 'code': self.valid_token }) self.assertEqual(response.context['user'], self.user)