##// END OF EJS Templates
feat(2fa): updated and UI fixes...
super-admin -
r5373:834643be default
parent child Browse files
Show More
@@ -34,7 +34,7 b' from pyramid.renderers import render'
34 34 from pyramid.response import Response
35 35 from pyramid.httpexceptions import HTTPFound
36 36
37
37 import rhodecode
38 38 from rhodecode.apps._base import BaseAppView
39 39 from rhodecode.authentication.base import authenticate, HTTP_TYPE
40 40 from rhodecode.authentication.plugins import auth_rhodecode
@@ -510,9 +510,10 b' class LoginView(BaseAppView):'
510 510 # only then we should persist it
511 511 secret = user_instance.init_secret_2fa(persist=False)
512 512
513 totp_name = f'RhodeCode token ({self.request.user.username})'
513 instance_name = rhodecode.ConfigGet().get_str('app.base_url', 'rhodecode')
514 totp_name = f'{instance_name}:{self.request.user.username}'
514 515
515 qr = qrcode.QRCode(version=1, box_size=10, border=5)
516 qr = qrcode.QRCode(version=1, box_size=5, border=4)
516 517 qr.add_data(pyotp.totp.TOTP(secret).provisioning_uri(name=totp_name))
517 518 qr.make(fit=True)
518 519 img = qr.make_image(fill_color='black', back_color='white')
@@ -919,7 +919,7 b' class User(Base, BaseModel):'
919 919 return ''
920 920
921 921 def get_secret_2fa(self) -> str:
922 secret_2fa = self.user_data['secret_2fa']
922 secret_2fa = self.user_data.get('secret_2fa')
923 923 if secret_2fa:
924 924 strict_mode = ConfigGet().get_bool('rhodecode.encrypted_values.strict', missing=True)
925 925 return safe_str(
@@ -6,9 +6,11 b''
6 6 · ${h.branding(c.rhodecode_name)}
7 7 %endif
8 8 </%def>
9
9 10 <style>body{background-color:#eeeeee;}</style>
10 11
11 <div class="loginbox">
12 <div class="loginbox" style="width: 600px">
13
12 14 <div class="header-account">
13 15 <div id="header-inner" class="title">
14 16 <div id="logo">
@@ -22,66 +24,67 b''
22 24 </div>
23 25
24 26 <div class="loginwrapper">
25 <h1>${_('Setup the authenticator app')}</h1>
26
27 <p>Authenticator apps like <a href='https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2' target="_blank" rel="noopener noreferrer">Google Authenticator</a>, etc. generate one-time passwords that are used as a second factor to verify you identity.</p>
28 27 <rhodecode-toast id="notifications"></rhodecode-toast>
29 28
30 <div id="setup_2fa">
29 <div class="sign-in-title">
30 <h1>${_('Set up the authenticator app')} - ${_('scan the QR code')}</h1>
31 </div>
32 <div class="inner form">
31 33 ${h.secure_form(h.route_path('setup_2fa'), request=request, id='totp_form')}
32 <div class="sign-in-title">
33 <h1>${_('Scan the QR code')}: "${totp_name}"</h1>
34 <strong>${_('Use an authenticator app to scan.')}</strong><br/>
35
36 ## QR CODE
37 <code>${_('Account')}: ${totp_name}</code><br/>
38 <div class="qr-code-container">
39 <img alt="qr-code" src="data:image/png;base64, ${qr}"/>
34 40 </div>
35 <p>${_('Use an authenticator app to scan.')}</p>
36 <img alt="qr-code" src="data:image/png;base64, ${qr}"/>
41
42 <div id="alternativeCode" style="margin: -10px 0 5px 0">${_('Unable to scan?')} <a id="toggleLink">${_('Click here')}</a></div>
43
44 ## Secret alternative code
45 <div id="secretDiv" style="display: none">
37 46
38 <p>${_('Unable to scan?')} <a id="toggleLink">${_('Click here')}</a></p>
39 <div id="secretDiv" class="hidden">
40 <p>${_('Copy and use this code to manually set up an authenticator app')}</p>
41 <input type="text" class="input-monospace" value="${key}" id="secret_totp" name="secret_totp" style="width: 400px"/>
42 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${key}" title="${_('Copy the secret key')}"></i>
47 <div style="padding: 10px 0">
48 <strong style="padding: 4px 0">${_('Copy and use this code to manually set up an authenticator app')}</strong>
49 <code>${key}</code><i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${key}" title="${_('Copy the secret key')}" ></i><br/>
50 <code>${_('type')}: time-based</code>
51 </div>
52
43 53 </div>
44 54
45 <div id="verify_2fa">
55 <label for="totp">${_('Verify the code from the app')}:</label>
56 ${h.text('totp', class_='form-control', )}
57 <div id="formErrors">
58 % if 'totp' in errors:
59 <span class="error-message">${errors.get('totp')}</span>
60 <br />
61 % endif
62 % if 'secret_totp' in errors:
63 <span class="error-message">SECRET:${errors.get('secret_totp')}</span>
64 <br />
65 % endif
66 </div>
67 ${h.hidden('secret_totp', key)}
68 ${h.submit('verify_2fa',_('Verify'), class_="btn sign-in")}
46 69
47 <div class="form mt-4">
48 <div class="field">
49 <p>
50 <div class="label">
51 <label for="totp" class="form-label text-dark font-weight-bold" style="text-align: left;">${_('Verify the code from the app')}:</label>
52 </div>
53 </p>
54 <p>
55 <div>
56 <div class="input-group">
57 ${h.text('totp', class_='form-control', style='width: 40%;')}
58 <div id="formErrors">
59 % if 'totp' in errors:
60 <span class="error-message">${errors.get('totp')}</span>
61 <br />
62 % endif
63 </div>
64 <div class="input-group-append">
65 ${h.submit('verify_2fa',_('Verify'),class_="btn btn-primary", style='width: 40%;')}
66 </div>
67 </div>
68 </div>
69 </p>
70 </div>
71 </div>
72 </div>
73 70 ${h.end_form()}
74 71 </div>
72
75 73 </div>
74
76 75 </div>
77 76
78 <script>
77 <script type="text/javascript">
78
79 $(document).ready(function() {
79 80
80 document.getElementById('toggleLink').addEventListener('click', function() {
81 let hiddenField = document.getElementById('secretDiv');
82 if (hiddenField.classList.contains('hidden')) {
83 hiddenField.classList.remove('hidden');
84 }
85 });
81 $( "#toggleLink" ).on("click", function() {
82 $( "#secretDiv" ).toggle();
83 $( "#alternativeCode").hide();
84 $('#totp').focus();
85 });
86
87 $('#totp').focus();
88 })
86 89
87 90 </script>
@@ -8,7 +8,7 b''
8 8 </%def>
9 9 <style>body{background-color:#eeeeee;}</style>
10 10
11 <div class="loginbox">
11 <div class="loginbox" style="width: 600px">
12 12 <div class="header-account">
13 13 <div id="header-inner" class="title">
14 14 <div id="logo">
General Comments 0
You need to be logged in to leave comments. Login now