diff --git a/CHANGELOG.md b/CHANGELOG.md index bde04afb2..ecd8b4ce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ ### Removed - Django 2.2, 3.0, and 3.1 support +### Changed + +- display the TOTP secret key alongside the QR code to streamline setup for + password managers without QR support. + ## 1.14.0 ### Added diff --git a/tests/test_views_setup.py b/tests/test_views_setup.py index f6573c45f..06b9bb3f5 100644 --- a/tests/test_views_setup.py +++ b/tests/test_views_setup.py @@ -38,6 +38,12 @@ def test_setup_only_generator_available(self): # test if secret key is valid base32 and has the correct number of bytes secret_key = response.context_data['secret_key'] self.assertEqual(len(b32decode(secret_key)), 20) + self.assertEqual( + response.context_data['otpauth_url'], + f'otpauth://totp/testserver%3A%20bouke%40example.com?secret={secret_key}&digits=6&issuer=testserver' + ) + self.assertEqual(response.context_data['issuer'], 'testserver') + self.assertEqual(response.context_data['totp_digits'], 6) response = self.client.post( reverse('two_factor:setup'), diff --git a/two_factor/templates/two_factor/core/setup.html b/two_factor/templates/two_factor/core/setup.html index 222039094..1596fee00 100644 --- a/two_factor/templates/two_factor/core/setup.html +++ b/two_factor/templates/two_factor/core/setup.html @@ -17,9 +17,13 @@
{% blocktrans trimmed %}To start using a token generator, please use your smartphone to scan the QR code below. For example, use Google - Authenticator. Then, enter the token generated by the app. - {% endblocktrans %}
+ Authenticator.{% endblocktrans %} +{% blocktrans trimmed %}Alternatively you can use the following secret to + setup TOTP in your authenticator or password manager manually.{% endblocktrans %}
+{% translate "TOTP Secret:" %} {{ secret_key }}
+{% blocktrans %}Then, enter the token generated by the app.{% endblocktrans %}
+ {% elif wizard.steps.current == 'sms' %}{% blocktrans trimmed %}Please enter the phone number you wish to receive the text messages on. This number will be validated in the next step. diff --git a/two_factor/views/core.py b/two_factor/views/core.py index 1a3ca96c4..d347e8273 100644 --- a/two_factor/views/core.py +++ b/two_factor/views/core.py @@ -596,10 +596,18 @@ def get_context_data(self, form, **kwargs): key = self.get_key('generator') rawkey = unhexlify(key.encode('ascii')) b32key = b32encode(rawkey).decode('utf-8') + issuer = get_current_site(self.request).name + username = self.request.user.get_username() + otpauth_url = get_otpauth_url(username, b32key, issuer) self.request.session[self.session_key_name] = b32key context.update({ + # used in default template + 'otpauth_url': otpauth_url, 'QR_URL': reverse(self.qrcode_url), 'secret_key': b32key, + # available for custom templates + 'issuer': issuer, + 'totp_digits': totp_digits(), }) elif self.steps.current == 'validation': context['device'] = self.get_device()