More security options in TOTP (#1359)

This commit is contained in:
Xavier Guimard 2018-03-18 14:26:45 +01:00
parent 799109caca
commit 9725a63396
25 changed files with 86 additions and 19 deletions

View File

@ -195,7 +195,7 @@ sub group {
sub sendError {
my ( $self, $req, $err, $code ) = @_;
$err ||= $req->error;
$err = '[' . $self->userId($req) . "] $err";
$self->userLogger->warn( '[' . $self->userId($req) . "] $err" );
return $self->Lemonldap::NG::Common::PSGI::sendError( $req, $err, $code );
}

View File

@ -3212,6 +3212,10 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => 6,
'type' => 'int'
},
'totp2fDisplayExistingSecret' => {
'default' => 0,
'type' => 'bool'
},
'totp2fInterval' => {
'default' => 30,
'type' => 'int'
@ -3227,6 +3231,10 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => 0,
'type' => 'bool'
},
'totp2fUserCanChangeKey' => {
'default' => 0,
'type' => 'bool'
},
'trustedDomains' => {
'type' => 'text'
},

View File

@ -1108,6 +1108,17 @@ sub attributes {
default => 6,
documentation => 'Number of digits for TOTP code',
},
totp2fDisplayExistingSecret => {
type => 'bool',
default => 0,
documentation =>
'Display existing TOTP secret in registration form',
},
totp2fUserCanChangeKey => {
type => 'bool',
default => 0,
documentation => 'Authorize users to change existing TOTP secret',
},
# UTOTP 2F
utotp2fActivation => {

View File

@ -673,10 +673,15 @@ sub tree {
help => 'totp2f.html',
form => 'simpleInputContainer',
nodes => [
'totp2fActivation', 'totp2fSelfRegistration',
'totp2fAuthnLevel', 'totp2fIssuer',
'totp2fInterval', 'totp2fRange',
'totp2fActivation',
'totp2fSelfRegistration',
'totp2fAuthnLevel',
'totp2fIssuer',
'totp2fInterval',
'totp2fRange',
'totp2fDigits',
'totp2fDisplayExistingSecret',
'totp2fUserCanChangeKey',
]
},
{

View File

@ -715,10 +715,12 @@
"totp2fActivation":"Activation",
"totp2fAuthnLevel":"TOTP authentication level",
"totp2fDigits":"Number of digits",
"totp2fDisplayExistingSecret":"Display existing secret",
"totp2fInterval":"Interval",
"totp2fIssuer":"TOTP Issuer name",
"totp2fRange":"Range of attempts",
"totp2fSelfRegistration":"Self registration",
"totp2fUserCanChangeKey":"Change existing secret",
"trustedDomains":"النطاقات الموثوق بها",
"trustedProxies":"عناوين الآي بي البروكسي الموثوق بها",
"twitterAppName":"اسم التطبيق",

View File

@ -715,10 +715,12 @@
"totp2fActivation":"Activation",
"totp2fAuthnLevel":"TOTP authentication level",
"totp2fDigits":"Number of digits",
"totp2fDisplayExistingSecret":"Display existing secret",
"totp2fInterval":"Interval",
"totp2fIssuer":"TOTP Issuer name",
"totp2fRange":"Range of attempts",
"totp2fSelfRegistration":"Self registration",
"totp2fUserCanChangeKey":"Change existing secret",
"trustedDomains":"Trusted domains",
"trustedProxies":"Trusted proxies IP",
"twitterAppName":"Application name",

View File

@ -715,10 +715,12 @@
"totp2fActivation":"Activation",
"totp2fAuthnLevel":"Niveau d'authentification TOTP",
"totp2fDigits":"Nombre de chiffres",
"totp2fDisplayExistingSecret":"Afficher la clef existante",
"totp2fInterval":"Intervalle",
"totp2fIssuer":"Nom du fournisseur TOTP",
"totp2fRange":"Nombre d'intervalles à tester",
"totp2fSelfRegistration":"Auto-enregistrement",
"totp2fUserCanChangeKey":"Changer une clef existante",
"trustedDomains":"Domaines approuvés",
"trustedProxies":"IP des proxys de confiance",
"twitterAppName":"Nom de l'application",

View File

@ -715,10 +715,12 @@
"totp2fActivation":"Activation",
"totp2fAuthnLevel":"TOTP authentication level",
"totp2fDigits":"Number of digits",
"totp2fDisplayExistingSecret":"Display existing secret",
"totp2fInterval":"Interval",
"totp2fIssuer":"TOTP Issuer name",
"totp2fRange":"Range of attempts",
"totp2fSelfRegistration":"Self registration",
"totp2fUserCanChangeKey":"Change existing secret",
"trustedDomains":"Domini attendibili",
"trustedProxies":"IP proxy attendibili",
"twitterAppName":"Nome dell'applicazione",

View File

@ -715,10 +715,12 @@
"totp2fActivation":"Activation",
"totp2fAuthnLevel":"TOTP authentication level",
"totp2fDigits":"Number of digits",
"totp2fDisplayExistingSecret":"Display existing secret",
"totp2fInterval":"Interval",
"totp2fIssuer":"TOTP Issuer name",
"totp2fRange":"Range of attempts",
"totp2fSelfRegistration":"Self registration",
"totp2fUserCanChangeKey":"Change existing secret",
"trustedDomains":"Miền tin cậy",
"trustedProxies":"proxies IP tin cậy",
"twitterAppName":"Tên ứng dụng",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -33,7 +33,7 @@ sub init {
sub run {
my ( $self, $req, $action ) = @_;
my $user = $req->userData->{ $self->conf->{whatToTrace} };
my $user = $req->userData->{ $self->conf->{whatToTrace} };
unless ($user) {
return $self->p->sendError( $req,
'No ' . $self->conf->{whatToTrace} . ' found in user data', 500 );
@ -98,13 +98,21 @@ sub run {
elsif ( $action eq 'getkey' ) {
my $nk = 0;
my $secret;
if ( $req->param('newkey') or not $req->userData->{_totp2fSecret} ) {
if ( ( $req->param('newkey') and $self->conf->{totp2fUserCanChangeKey} )
or not $req->userData->{_totp2fSecret} )
{
$secret = $self->newSecret;
$nk = 1;
}
else {
elsif ( $req->param('newkey') ) {
return $self->p->sendError( $req, 'notAutorizated', 200 );
}
elsif ( $self->conf->{totp2fDisplayExistingSecret} ) {
$secret = $req->userData->{_totp2fSecret};
}
else {
return $self->p->sendError( $req, 'totpExistingKey', 200 );
}
# Secret is stored in a token: we choose to not accept secret returned
# by Ajax request to avoid some attacks

View File

@ -29,8 +29,10 @@ getKey = (reset) ->
error: displayError
# Display key and QR code
success: (data) ->
if data.error
return setMsg data.error, 'warning'
unless data.portal and data.user and data.secret
return setMsg 'PE24', 'danger'
return setMsg('PE24', 'danger')
# Generate OTP url
s = "otpauth://totp/#{escape(data.portal)}:#{escape(data.user)}?secret=#{data.secret}&issuer=#{escape(data.portal)}"

View File

@ -41,6 +41,9 @@ LemonLDAP::NG TOTP registration script
error: displayError,
success: function(data) {
var qr, s;
if (data.error) {
return setMsg(data.error, 'warning');
}
if (!(data.portal && data.user && data.secret)) {
return setMsg('PE24', 'danger');
}

View File

@ -1 +1 @@
(function(){var a,b,e,d,c,f;e=function(g,h){$("#msg").html(window.translate(g));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+h);if(h==="positive"){h="success"}return $("#color").addClass("alert-"+h)};a=function(h,g,k){var i;console.log("Error",k);i=JSON.parse(h.responseText);if(i&&i.error){i=i.error.replace(/.* /,"");console.log("Returned error",i);return e(i,"warning")}};d="";b=function(g){return $.ajax({type:"POST",url:portal+"/2fregisters/totp/getkey",dataType:"json",data:{newkey:g},error:a,success:function(j){var h,i;if(!(j.portal&&j.user&&j.secret)){return e("PE24","danger")}i="otpauth://totp/"+(escape(j.portal))+":"+(escape(j.user))+"?secret="+j.secret+"&issuer="+(escape(j.portal));if(j.digits!==6){i+="&digits="+j.digits}if(j.interval!==30){i+="&period="+j.interval}h=new QRious({element:document.getElementById("qr"),value:i,size:150});$("#serialized").text(i);if(j.newkey){e("yourNewTotpKey","warning")}else{e("yourTotpKey","success")}return d=j.token}})};f=function(){var g;g=$("#code").val();if(!g){return e("fillTheForm","warning")}else{return $.ajax({type:"POST",url:portal+"/2fregisters/totp/verify",dataType:"json",data:{token:d,code:g},error:a,success:function(h){if(h.error){if(h.error.match(/badCode/)){return e("badCode","warning")}else{return e(h.error,"danger")}}else{return e("yourKeyIsRegistered","success")}}})}};c=function(){return $.ajax({type:"POST",url:portal+"/totpregister/unregister",data:{},dataType:"json",error:a,success:function(g){}},e("yourKeyIsUnregistered","success"))};$(document).ready(function(){b(0);$("#changekey").on("click",function(){return b(1)});$("#verify").on("click",function(){return f()});return $("#unregister").on("click",function(){return c()})})}).call(this);
(function(){var a,b,e,d,c,f;e=function(g,h){$("#msg").html(window.translate(g));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+h);if(h==="positive"){h="success"}return $("#color").addClass("alert-"+h)};a=function(h,g,k){var i;console.log("Error",k);i=JSON.parse(h.responseText);if(i&&i.error){i=i.error.replace(/.* /,"");console.log("Returned error",i);return e(i,"warning")}};d="";b=function(g){return $.ajax({type:"POST",url:portal+"/2fregisters/totp/getkey",dataType:"json",data:{newkey:g},error:a,success:function(j){var h,i;if(j.error){return e(j.error,"warning")}if(!(j.portal&&j.user&&j.secret)){return e("PE24","danger")}i="otpauth://totp/"+(escape(j.portal))+":"+(escape(j.user))+"?secret="+j.secret+"&issuer="+(escape(j.portal));if(j.digits!==6){i+="&digits="+j.digits}if(j.interval!==30){i+="&period="+j.interval}h=new QRious({element:document.getElementById("qr"),value:i,size:150});$("#serialized").text(i);if(j.newkey){e("yourNewTotpKey","warning")}else{e("yourTotpKey","success")}return d=j.token}})};f=function(){var g;g=$("#code").val();if(!g){return e("fillTheForm","warning")}else{return $.ajax({type:"POST",url:portal+"/2fregisters/totp/verify",dataType:"json",data:{token:d,code:g},error:a,success:function(h){if(h.error){if(h.error.match(/badCode/)){return e("badCode","warning")}else{return e(h.error,"danger")}}else{return e("yourKeyIsRegistered","success")}}})}};c=function(){return $.ajax({type:"POST",url:portal+"/totpregister/unregister",data:{},dataType:"json",error:a,success:function(g){}},e("yourKeyIsUnregistered","success"))};$(document).ready(function(){b(0);$("#changekey").on("click",function(){return b(1)});$("#verify").on("click",function(){return f()});return $("#unregister").on("click",function(){return c()})})}).call(this);

View File

@ -151,6 +151,7 @@
"newPassword":"كلمة مرور جديدة",
"newPwdSentTo":"تم إرسال تأكيد إلى عنوان بريدك الإلكتروني.",
"noHistory":"هذا هو أول اتصال، مرحبا بك!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "لم يتم العثور: محاولة الدخول إلى صفحة غير متوفرة",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"التطبيق ٪s هل ترغب في معرفة:",
@ -195,6 +196,7 @@
"SSOSessionInactive":"جلسة الدخول الموحد غير نشطة",
"stayConnected": "ابق على اتصال على هذا الجهاز",
"submit":"قدم",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "يرجى لمس جهاز U2F وامض الآن.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "فشل التحقق من U2F. أعد محاولة الاتصال بالمشرف أو اتصل به",

View File

@ -151,6 +151,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Not found: you try to access to an unavailable page",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
@ -195,12 +196,13 @@
"SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device",
"submit":"Submit",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Please touch the flashing U2F device now.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "U2F verification failed. Retry or contact your administrator",
"u2fPermission": "You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.",
"u2fRegistered": "Your key is registered",
"u2fUnregistered": "Your key has been registered",
"u2fRegistered": "Your key has been registered.",
"u2fUnregistered": "Your key has been unregistered",
"u2fSuccess": "Your key is successfully tested",
"u2fWelcome": "U2F device management",
"unableToGetU2FKey": "Unable to access to your key. Retry or contact your administrator",

View File

@ -151,6 +151,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Not found: you try to access to an unavailable page",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
@ -195,12 +196,13 @@
"SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device",
"submit":"Submit",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Please touch the flashing U2F device now.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "U2F verification failed. Retry or contact your administrator",
"u2fPermission": "You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.",
"u2fRegistered": "Your key has been registered.",
"u2fUnregistered": "Your key has been unregistered.",
"u2fUnregistered": "Your key has been unregistered",
"u2fSuccess": "Your key is successfully tested",
"u2fWelcome": "U2F device management",
"unableToGetU2FKey": "Unable to access to your key. Retry or contact your administrator",

View File

@ -151,6 +151,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Not found: you try to access to an unavailable page",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
@ -195,12 +196,13 @@
"SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device",
"submit":"Submit",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Please touch the flashing U2F device now.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "U2F verification failed. Retry or contact your administrator",
"u2fPermission": "You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.",
"u2fRegistered": "Your key is registered",
"u2fUnregistered": "Your key is unregistered",
"u2fRegistered": "Your key has been registered.",
"u2fUnregistered": "Your key has been unregistered",
"u2fSuccess": "Your key is successfully tested",
"u2fWelcome": "U2F device management",
"unableToGetU2FKey": "Unable to access to your key. Retry or contact your administrator",

View File

@ -151,6 +151,7 @@
"newPassword":"Nouveau mot de passe",
"newPwdSentTo":"Une confirmation a été envoyée à votre adresse mail.",
"noHistory":"Ceci est votre première connexion, bienvenue !",
"notAutorizated":"Vous n'êtes pas autorisé à faire cette requête",
"notFound": "Non trouvé: vous tentez d'accéder à une page non disponible",
"noU2FKeyFound": "Aucune clef U2F trouvée",
"oidcConsent":"L'application %s voudrait connaître :",
@ -195,6 +196,7 @@
"SSOSessionInactive":"Session SSO inactive",
"stayConnected": "Rester connecté sur cet appareil",
"submit":"Envoyer",
"totpExistingKey":"Un secret TOTP existe déjà",
"touchU2fDevice": "Posez votre doigt sur le périphérique U2F",
"touchU2fDeviceOrEnterTotp": "Posez votre doigt sur le périphérique U2F ou entrez le code TOTP",
"u2fFailed": "La vérification U2F a échoué, réessayez ou contactez votre administrateur",

View File

@ -151,6 +151,7 @@
"newPassword":"Nuova password",
"newPwdSentTo":"Una conferma è stata inviata all'indirizzo di posta elettronica.",
"noHistory":"Questa è la tua prima connessione, benvenuto!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Non trovato: si tenta di accedere ad una pagina non disponibile",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"L'applicazione %s vorrebbe sapere:",
@ -195,6 +196,7 @@
"SSOSessionInactive":"Sessione SSO inattiva",
"stayConnected": "Resta connesso su questo dispositivo",
"submit":"Invia",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Adesso tocca il dispositivo U2F lampeggiante.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "Verifica U2F non riuscita. Riprovare o contattare l'amministratore",

View File

@ -151,6 +151,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Not found: you try to access to an unavailable page",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
@ -195,11 +196,12 @@
"SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device",
"submit":"Submit",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Please touch the flashing U2F device now.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "U2F verification failed. Retry or contact your administrator",
"u2fPermission": "You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.",
"u2fRegistered": "Your key is registered",
"u2fRegistered": "Your key has been registered.",
"u2fUnregistered": "Your key has been unregistered",
"u2fSuccess": "Your key is successfully tested",
"u2fWelcome": "U2F device management",

View File

@ -151,6 +151,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Not found: you try to access to an unavailable page",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
@ -195,11 +196,12 @@
"SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device",
"submit":"Submit",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Please touch the flashing U2F device now.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "U2F verification failed. Retry or contact your administrator",
"u2fPermission": "You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.",
"u2fRegistered": "Your key is registered",
"u2fRegistered": "Your key has been registered.",
"u2fUnregistered": "Your key has been unregistered",
"u2fSuccess": "Your key is successfully tested",
"u2fWelcome": "U2F device management",

View File

@ -151,6 +151,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Not found: you try to access to an unavailable page",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:",
@ -195,11 +196,12 @@
"SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device",
"submit":"Submit",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Please touch the flashing U2F device now.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "U2F verification failed. Retry or contact your administrator",
"u2fPermission": "You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.",
"u2fRegistered": "Your key is registered",
"u2fRegistered": "Your key has been registered.",
"u2fUnregistered": "Your key has been unregistered",
"u2fSuccess": "Your key is successfully tested",
"u2fWelcome": "U2F device management",

View File

@ -151,6 +151,7 @@
"newPassword":"Mật khẩu mới",
"newPwdSentTo":"Một xác nhận đã được gửi đến địa chỉ thư của bạn.",
"noHistory":"Đây là kết nối đầu tiên của bạn, chào mừng!",
"notAutorizated":"You're not authorizated too do this",
"notFound": "Không tìm thấy: bạn cố gắng truy cập vào một trang không có sẵn",
"noU2FKeyFound": "No U2F key found",
"oidcConsent":"Ứng dụng % s muốn biết:",
@ -195,6 +196,7 @@
"SSOSessionInactive":"Phiên SSO không hoạt động",
"stayConnected": "Giữ kết nối trên thiết bị này",
"submit":"Gửi",
"totpExistingKey":"A TOTP secret already exists",
"touchU2fDevice": "Vui lòng chạm vào thiết bị U2F nhấp nháy ngay bây giờ.",
"touchU2fDeviceOrEnterTotp": "Please touch the flashing U2F device or enter TOTP code.",
"u2fFailed": "Xác minh U2F không thành công. Thử lại hoặc liên hệ với quản trị viên của bạn ",