@@ -1025,130 +1025,6 @@ | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"OTP App\" && doc.send_barcode_as_email==1", | |||
"fieldname": "qr_code_email_subject", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "QR Code Email Subject", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"OTP App\" && doc.send_barcode_as_email==1", | |||
"fieldname": "qr_code_email_body", | |||
"fieldtype": "Small Text", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "QR Code Email Body", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"Email\"", | |||
"fieldname": "two_factor_email_subject", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Two factor Email Subject", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "eval:doc.enable_two_factor_auth==1 && doc.two_factor_method == \"Email\"", | |||
"fieldname": "two_factor_email_body", | |||
"fieldtype": "Small Text", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Two factor Email Body", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
@@ -1281,8 +1157,8 @@ | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2017-07-28 07:21:12.520227", | |||
"modified_by": "Administrator", | |||
"modified": "2017-07-29 13:33:49.201189", | |||
"modified_by": "chude.osiegbu@manqala.com", | |||
"module": "Core", | |||
"name": "System Settings", | |||
"name_case": "", | |||
@@ -269,18 +269,12 @@ var continue_otp_app = function(setup, qrcode){ | |||
request_otp(); | |||
var qrcode_div = $('<div>').attr({'id':'qrcode_div','style':'text-align:center;padding-bottom:15px;'}); | |||
if (!setup){ | |||
direction = $('<div>').attr('id','qr_info').text('Scan QR Code and enter the resulting code displayed. \ | |||
You can use apps such as Google Authenticator, Lastpass Authenticator, Authy, Duo Mobile and others.'), | |||
qrimg = $('<img>').attr({ | |||
'src':'data:image/svg+xml;base64,' + qrcode, | |||
'style':'width:250px;height:250px;'}); | |||
if (setup){ | |||
direction = $('<div>').attr('id','qr_info').text('Enter Code displayed in OTP App.'); | |||
qrcode_div.append(direction); | |||
qrcode_div.append(qrimg); | |||
$('#otp_div').prepend(qrcode_div); | |||
} else { | |||
direction = $('<div>').attr('id','qr_info').text('Enter Code displayed in OTP App'); | |||
direction = $('<div>').attr('id','qr_info').text('OTP setup using OTP App was not completed. Please contact Administrator.'); | |||
qrcode_div.append(direction); | |||
$('#otp_div').prepend(qrcode_div); | |||
} | |||
@@ -291,36 +285,10 @@ var continue_sms = function(setup, prompt){ | |||
var sms_div = $('<div>').attr({'id':'sms_div','style':'padding-bottom:15px;text-align:center;'}); | |||
if (setup){ | |||
direction = $('<div>').attr('id','sms_info').text('Enter phone number to send verification code'); | |||
sms_div.append(direction); | |||
sms_div.append($('<div>').attr({'id':'sms_code_div'}).html( | |||
'<div class="form-group text-center">\ | |||
<input type="text" id="phone_no" class="form-control" placeholder="2347001234567" required="" autofocus="">\ | |||
<button class="btn btn-sm btn-primary" id="submit_phone_no" >Send SMS</button>\ | |||
</div><hr>')); | |||
sms_div.append(prompt) | |||
$('#otp_div').prepend(sms_div); | |||
$('#submit_phone_no').on('click',function(){ | |||
frappe.call({ | |||
method: "frappe.core.doctype.user.user.send_token_via_sms", | |||
args: {'phone_no': $('#phone_no').val(), 'tmp_id':data.tmp_id }, | |||
freeze: true, | |||
callback: function(r) { | |||
if (r.message){ | |||
$('#sms_div').empty().append( | |||
'<p class="lead">SMS sent.<br><small><small>Enter verification code received</small></small></p><hr>' | |||
); | |||
} else { | |||
$('#sms_div').empty().append( | |||
'<p class="lead">SMS not sent</p><hr>' | |||
); | |||
} | |||
} | |||
}); | |||
}) | |||
} else { | |||
direction = $('<div>').attr('id','qr_info').text(prompt || 'SMS not sent'); | |||
direction = $('<div>').attr('id','qr_info').text(prompt || 'SMS was not sent. Please contact Administrator.'); | |||
sms_div.append(direction); | |||
$('#otp_div').prepend(sms_div) | |||
} | |||
@@ -331,22 +299,10 @@ var continue_email = function(setup, prompt){ | |||
var email_div = $('<div>').attr({'id':'email_div','style':'padding-bottom:15px;text-align:center;'}); | |||
if (setup){ | |||
email_div.append('<p>Verification code email will be sent to registered email address. Enter code received below</p>') | |||
email_div.append(prompt) | |||
$('#otp_div').prepend(email_div); | |||
frappe.call({ | |||
method: "frappe.core.doctype.user.user.send_token_via_email", | |||
args: {'tmp_id':data.tmp_id }, | |||
callback: function(r) { | |||
if (r.message){ | |||
} else { | |||
$('#email_div').empty().append( | |||
'<p>Email not sent</p><hr>' | |||
); | |||
} | |||
} | |||
}); | |||
} else { | |||
var direction = $('<div>').attr('id','qr_info').text(prompt || 'Verification code email not sent'); | |||
var direction = $('<div>').attr('id','qr_info').text(prompt || 'Verification code email not sent. Please contact Administrator.'); | |||
email_div.append(direction); | |||
$('#otp_div').prepend(email_div); | |||
} |
@@ -130,12 +130,13 @@ def get_verification_obj(user,token,otp_secret): | |||
if verification_method == 'SMS': | |||
verification_obj = process_2fa_for_sms(user,token,otp_secret) | |||
elif verification_method == 'OTP App': | |||
if should_send_barcode_as_email(): | |||
verification_obj = process_2fa_for_email(user,token,otp_secret,otp_issuer,method='otp_app') | |||
#check if this if the first time that the user is trying to login. If so, send an email | |||
if not frappe.db.get_default(user + '_otplogin'): | |||
verification_obj = process_2fa_for_email(user,token,otp_secret,otp_issuer,method='OTP App') | |||
else: | |||
verification_obj = process_2fa_for_otp_app(user,otp_secret,otp_issuer) | |||
elif verification_method == 'Email': | |||
process_2fa_for_email(user,token,otp_secret,otp_issuer) | |||
verification_obj = process_2fa_for_email(user,token,otp_secret,otp_issuer) | |||
return verification_obj | |||
@@ -146,7 +147,8 @@ def process_2fa_for_sms(user,token,otp_secret): | |||
status = send_token_via_sms(otp_secret,token=token, phone_no=phone) | |||
verification_obj = {'token_delivery': status, | |||
'prompt': status and 'Enter verification code sent to {}'.format(phone[:4] + '******' + phone[-3:]), | |||
'method': 'SMS'} | |||
'method': 'SMS', | |||
'setup': status} | |||
return verification_obj | |||
def process_2fa_for_otp_app(user,otp_secret,otp_issuer): | |||
@@ -163,55 +165,50 @@ def process_2fa_for_otp_app(user,otp_secret,otp_issuer): | |||
'setup': otp_setup_completed } | |||
return verification_obj | |||
def process_2fa_for_email(user,token,otp_secret,otp_issuer,method='email'): | |||
def process_2fa_for_email(user,token,otp_secret,otp_issuer,method='Email'): | |||
'''Process Email method for 2fa.''' | |||
subject = None | |||
message = None | |||
status = True | |||
if method == 'otp_app' and not frappe.db.get_default(user + '_otplogin'): | |||
prompt = '' | |||
if method == 'OTP App' and not frappe.db.get_default(user + '_otplogin'): | |||
'''Sending one-time email for OTP App''' | |||
totp_uri = pyotp.TOTP(otp_secret).provisioning_uri(user, issuer_name=otp_issuer) | |||
qrcode_link = get_link_for_qrcode(user,totp_uri) | |||
message = get_email_body_for_qr_code({'qrcode_link':qrcode_link}) | |||
subject = get_email_subject_for_qr_code({'qrcode_link':qrcode_link}) | |||
if method == 'email' or message: | |||
status = send_token_via_email(user,token,otp_secret,otp_issuer,subject=subject,message=message) | |||
prompt = 'Please check your registered email address for instructions on how to proceed. Do not close this window as you will have to return to it!!' | |||
else: | |||
'''Sending email verification''' | |||
prompt = 'Verification code has been sent to your registered email address.' | |||
status = send_token_via_email(user,token,otp_secret,otp_issuer,subject=subject,message=message) | |||
verification_obj = {'token_delivery': status, | |||
'prompt': status and 'Verification code has been sent to your registered email address', | |||
'method': 'Email'} | |||
'prompt': status and prompt, | |||
'method': 'Email', | |||
'setup': status} | |||
return verification_obj | |||
def get_email_subject_for_2fa(kwargs_dict): | |||
'''Get email subject for 2fa.''' | |||
subject_template = 'Verifcation Code from Frappe Framework' | |||
template = frappe.get_value('System Settings','System Settings','two_factor_email_subject') | |||
if not template == '': | |||
subject_template = template | |||
subject_template = 'Verifcation Code from {}'.format(frappe.db.get_value('System Settings', 'System Settings', 'otp_issuer_name')) | |||
subject = render_string_template(subject_template,kwargs_dict) | |||
return subject | |||
def get_email_body_for_2fa(kwargs_dict): | |||
'''Get email body for 2fa.''' | |||
body_template = 'Use this token to login <br> {{otp}}' | |||
template = frappe.get_value('System Settings','System Settings','two_factor_email_body') | |||
if not template == '': | |||
subject_template = template | |||
body = render_string_template(body_template,kwargs_dict) | |||
return body | |||
def get_email_subject_for_qr_code(kwargs_dict): | |||
'''Get QRCode email subject.''' | |||
subject_template = 'Verification Code from Frappe Framework' | |||
template = frappe.get_value('System Settings','System Settings','qr_code_email_subject') | |||
if not template == '': | |||
subject_template = template | |||
subject_template = 'OTP Registration Code from {}'.format(frappe.db.get_value('System Settings', 'System Settings', 'otp_issuer_name')) | |||
subject = render_string_template(subject_template,kwargs_dict) | |||
return subject | |||
def get_email_body_for_qr_code(kwargs_dict): | |||
'''Get QRCode email body.''' | |||
body_template = 'Scan the QRCode on this link to get token <br> {{qrcode_link}}' | |||
template = frappe.get_value('System Settings','System Settings','qr_code_email_body') | |||
if not template == '': | |||
body_template = template | |||
body_template = 'Please click on the following link and follow the instructions on the page.<br> {{qrcode_link}}' | |||
body = render_string_template(body_template,kwargs_dict) | |||
return body | |||
@@ -1,12 +1,31 @@ | |||
{% extends "templates/web.html" %} | |||
{% block title %}Register OTP Secret{% endblock %} | |||
{% block page_content %} | |||
<div> | |||
<div style="text-align:center"> | |||
<div style="width:400px;margin:auto;text-align:center;"> | |||
<strong style="padding:10px;">Hi {{qr_code_user.first_name}}, Please scan QR Code and enter the resulting code displayed. | |||
You can use apps such as Google Authenticator, Lastpass Authenticator, Authy, Duo Mobile and others. | |||
</strong> | |||
</div> | |||
<div style="margin-top:10px;"> | |||
<img src="data:image/svg+xml;base64,{{qrcode_svg}}"> | |||
</div> | |||
<table> | |||
<tr> | |||
<td width="50%"> | |||
<div style="margin:auto;text-align:left;"> | |||
<p> | |||
Hi {{qr_code_user.first_name}}, please perform the following actions: | |||
<li> Open your authentication app on your mobile phone, | |||
<li> Scan the QR Code and enter the resulting code displayed | |||
<li> Return to the Verification screen and enter the code displayed by your authentication app | |||
</p> | |||
<p>Examples of Authentication Apps you can use are Google Authenticator, Lastpass Authenticator, Authy and Duo Mobile. | |||
</p> | |||
</div> | |||
</td> | |||
<td> | |||
<div style="padding:10px;"> | |||
<img src="data:image/svg+xml;base64,{{qrcode_svg}}"> | |||
</div> | |||
</td> | |||
</tr> | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
{% endblock %} |
@@ -14,10 +14,6 @@ no_cache = 1 | |||
def get_context(context): | |||
context.qr_code_user,context.qrcode_svg = get_user_svg_from_cache() | |||
def get_query_key(): | |||
'''Return query string arg.''' | |||
query_string = frappe.local.request.query_string | |||