Fix some mistakes & Self unregistration both U2F key and TOTP without controle challenge

This commit is contained in:
Christophe Maudoux 2018-03-09 22:32:42 +01:00
parent b38a49083f
commit 983400e0fa
19 changed files with 126 additions and 125 deletions

View File

@ -137,6 +137,24 @@ sub selfRegister {
}
);
}
# Get or generate master key
elsif ( $action eq 'unregister' ) {
$self->p->updatePersistentSession( $req,
{ _totp2fSecret => '' }
);
$self->userLogger->notice('TOTP unregistration succeed');
return [ 200, [ 'Content-Type' => 'application/json' ],
['{"result":1}'] ];
}
}
1;

View File

@ -74,24 +74,24 @@ sub run {
return [ 200, [ 'Content-Type' => 'application/json' ], [$challenge] ];
}
if ( $action eq 'unregistration' ) {
my ( $resp, $challenge );
unless ($resp = $req->param('registration')
and $challenge = $req->param('challenge') )
{
return $self->p->sendError( $req, 'Missing registration parameter',
400 );
}
$self->logger->debug("Get unregistration data $resp");
$self->logger->debug("Get challenge $challenge");
eval { $challenge = JSON::from_json($challenge)->{challenge} };
if ($@) {
$self->userLogger->error("Bad challenge: $@");
return $self->p->sendError( $req, 'Bad challenge', 400 );
}
my $c = $self->crypter;
if ( $c->setChallenge($challenge) ) {
my ( $keyHandle, $userKey ) = $c->registrationVerify($resp);
if ( $keyHandle and $userKey ) {
#my ( $resp, $challenge );
#unless ($resp = $req->param('registration')
#and $challenge = $req->param('challenge') )
#{
#return $self->p->sendError( $req, 'Missing registration parameter',
#400 );
#}
#$self->logger->debug("Get unregistration data $resp");
#$self->logger->debug("Get challenge $challenge");
#eval { $challenge = JSON::from_json($challenge)->{challenge} };
#if ($@) {
#$self->userLogger->error("Bad challenge: $@");
#return $self->p->sendError( $req, 'Bad challenge', 400 );
#}
#my $c = $self->crypter;
#if ( $c->setChallenge($challenge) ) {
#my ( $keyHandle, $userKey ) = $c->registrationVerify($resp);
#if ( $keyHandle and $userKey ) {
$self->p->updatePersistentSession(
$req,
{
@ -99,12 +99,13 @@ sub run {
_u2fUserKey => ''
}
);
$self->userLogger->notice('U2F key unregistration succeed');
return [
200, [ 'Content-Type' => 'application/json' ],
['{"result":1}']
];
}
}
#}
#}
my $err = Crypt::U2F::Server::Simple::lastError();
$self->userLogger->warn("U2F Unregistration failed: $err");
return $self->p->sendError( $req, $err, 200 );

View File

@ -52,7 +52,7 @@ getKey = (reset) ->
verify = ->
val = $('#code').val()
unless val
setMsg 'fillTheForm', 'danger'
setMsg 'fillTheForm', 'warning'
else
$.ajax
type: "POST",
@ -70,10 +70,22 @@ verify = ->
setMsg data.error, 'danger'
else
setMsg 'yourKeyIsRegistered', 'success'
unregister = ->
$.ajax
type: "POST",
url: "#{portal}/totpregister/unregister"
data: {}
dataType: 'json'
error: displayError
success: (data) ->
setMsg 'yourKeyIsUnregistered', 'success'
$(document).ready ->
getKey(0)
$('#changekey').on 'click', () ->
getKey(1)
$('#verify').on 'click', () ->
verify()
$('#unregister').on 'click', () ->
unregister()

View File

@ -55,43 +55,20 @@ register = ->
setMsg 'u2fRegistered', 'positive'
error: displayError
# Registration function (launched by "register" button)
# Unregistration function (launched by "unregister" button)
unregister = ->
# 1 get registration token
$.ajax
type: "POST",
url: "#{portal}u2fregister/unregister"
data: {}
dataType: 'json'
error: displayError
success: (ch) ->
# 2 build response
request = [
challenge: ch.challenge
version: ch.version
]
setMsg 'touchU2fDevice', 'positive'
$('#u2fPermission').show()
u2f.register ch.appId, request, [], (data) ->
$('#u2fPermission').hide()
# Handle errors
if data.errorCode
setMsg 'unableToGetU2FKey', 'warning'
else
# 3 send response
$.ajax
type: "POST"
url: "#{portal}u2fregister/unregistration"
data:
registration: JSON.stringify data
challenge: JSON.stringify ch
dataType: 'json'
success: (resp) ->
if resp.error
setMsg 'u2fFailed', 'warning'
else if resp.result
setMsg 'u2fUnregistered', 'positive'
error: displayError
$.ajax
type: "POST"
url: "#{portal}u2fregister/unregistration"
data: {}
dataType: 'json'
error: displayError
success: (resp) ->
if resp.error
setMsg 'u2fFailed', 'warning'
else if resp.result
setMsg 'u2fUnregistered', 'positive'
error: displayError
# Verification function (launched by "verify" button)
verify = ->

View File

@ -1,11 +1,11 @@
// Generated by CoffeeScript 1.10.0
// Generated by CoffeeScript 1.9.3
/*
LemonLDAP::NG TOTP registration script
*/
(function() {
var displayError, getKey, setMsg, token, verify;
var displayError, getKey, setMsg, token, unregister, verify;
setMsg = function(msg, level) {
$('#msg').html(window.translate(msg));
@ -68,7 +68,7 @@ LemonLDAP::NG TOTP registration script
var val;
val = $('#code').val();
if (!val) {
return setMsg('fillTheForm', 'danger');
return setMsg('fillTheForm', 'warning');
} else {
return $.ajax({
type: "POST",
@ -94,14 +94,28 @@ LemonLDAP::NG TOTP registration script
}
};
unregister = function() {
return $.ajax({
type: "POST",
url: portal + "/totpregister/unregister",
data: {},
dataType: 'json',
error: displayError,
success: function(data) {}
}, setMsg('yourKeyIsUnregistered', 'success'));
};
$(document).ready(function() {
getKey(0);
$('#changekey').on('click', function() {
return getKey(1);
});
return $('#verify').on('click', function() {
$('#verify').on('click', function() {
return verify();
});
return $('#unregister').on('click', function() {
return unregister();
});
});
}).call(this);

View File

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

@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.12.7
// Generated by CoffeeScript 1.9.3
/*
LemonLDAP::NG U2F registration script
@ -76,45 +76,18 @@ LemonLDAP::NG U2F registration script
unregister = function() {
return $.ajax({
type: "POST",
url: portal + "u2fregister/unregister",
url: portal + "u2fregister/unregistration",
data: {},
dataType: 'json',
error: displayError,
success: function(ch) {
var request;
request = [
{
challenge: ch.challenge,
version: ch.version
}
];
setMsg('touchU2fDevice', 'positive');
$('#u2fPermission').show();
return u2f.register(ch.appId, request, [], function(data) {
$('#u2fPermission').hide();
if (data.errorCode) {
return setMsg('unableToGetU2FKey', 'warning');
} else {
return $.ajax({
type: "POST",
url: portal + "u2fregister/unregistration",
data: {
registration: JSON.stringify(data),
challenge: JSON.stringify(ch)
},
dataType: 'json',
success: function(resp) {
if (resp.error) {
return setMsg('u2fFailed', 'warning');
} else if (resp.result) {
return setMsg('u2fUnregistered', 'positive');
}
},
error: displayError
});
}
});
}
success: function(resp) {
if (resp.error) {
return setMsg('u2fFailed', 'warning');
} else if (resp.result) {
return setMsg('u2fUnregistered', 'positive');
}
},
error: displayError
});
};

View File

@ -1 +1 @@
(function(){var a,c,d,b,e;d=function(f,g){$("#msg").html(window.translate(f));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+g);if(g==="positive"){g="success"}return $("#color").addClass("alert-"+g)};a=function(g,f,i){var h;console.log("Error",i);h=JSON.parse(g.responseText);if(h&&h.error){h=h.error.replace(/.* /,"");console.log("Returned error",h);return d(h,"warning")}};c=function(){return $.ajax({type:"POST",url:portal+"u2fregister/register",data:{},dataType:"json",error:a,success:function(f){var g;g=[{challenge:f.challenge,version:f.version}];d("touchU2fDevice","positive");$("#u2fPermission").show();return u2f.register(f.appId,g,[],function(h){$("#u2fPermission").hide();if(h.errorCode){return d("unableToGetU2FKey","warning")}else{return $.ajax({type:"POST",url:portal+"u2fregister/registration",data:{registration:JSON.stringify(h),challenge:JSON.stringify(f)},dataType:"json",success:function(i){if(i.error){return d("u2fFailed","warning")}else{if(i.result){return d("u2fRegistered","positive")}}},error:a})}})}})};b=function(){return $.ajax({type:"POST",url:portal+"u2fregister/unregister",data:{},dataType:"json",error:a,success:function(f){var g;g=[{challenge:f.challenge,version:f.version}];d("touchU2fDevice","positive");$("#u2fPermission").show();return u2f.register(f.appId,g,[],function(h){$("#u2fPermission").hide();if(h.errorCode){return d("unableToGetU2FKey","warning")}else{return $.ajax({type:"POST",url:portal+"u2fregister/unregistration",data:{registration:JSON.stringify(h),challenge:JSON.stringify(f)},dataType:"json",success:function(i){if(i.error){return d("u2fFailed","warning")}else{if(i.result){return d("u2fUnregistered","positive")}}},error:a})}})}})};e=function(){return $.ajax({type:"POST",url:portal+"u2fregister/verify",data:{},dataType:"json",error:a,success:function(f){var g;g=[{keyHandle:f.keyHandle,version:f.version}];d("touchU2fDevice","positive");return u2f.sign(f.appId,f.challenge,g,function(h){if(h.errorCode){return d("unableToGetU2FKey","warning")}else{return $.ajax({type:"POST",url:portal+"u2fregister/signature",data:{signature:JSON.stringify(h)},dataType:"json",success:function(i){if(i.error){return d("u2fFailed","warning")}else{if(i.result){return d("u2fSuccess","positive")}}},error:function(k,i,l){return console.log("error",l)}})}})}})};$(document).ready(function(){$("#u2fPermission").hide();$("#register").on("click",c);$("#unregister").on("click",b);$("#verify").on("click",e);return $("#goback").attr("href",portal)})}).call(this);
(function(){var a,c,d,b,e;d=function(f,g){$("#msg").html(window.translate(f));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+g);if(g==="positive"){g="success"}return $("#color").addClass("alert-"+g)};a=function(g,f,i){var h;console.log("Error",i);h=JSON.parse(g.responseText);if(h&&h.error){h=h.error.replace(/.* /,"");console.log("Returned error",h);return d(h,"warning")}};c=function(){return $.ajax({type:"POST",url:portal+"u2fregister/register",data:{},dataType:"json",error:a,success:function(f){var g;g=[{challenge:f.challenge,version:f.version}];d("touchU2fDevice","positive");$("#u2fPermission").show();return u2f.register(f.appId,g,[],function(h){$("#u2fPermission").hide();if(h.errorCode){return d("unableToGetU2FKey","warning")}else{return $.ajax({type:"POST",url:portal+"u2fregister/registration",data:{registration:JSON.stringify(h),challenge:JSON.stringify(f)},dataType:"json",success:function(i){if(i.error){return d("u2fFailed","warning")}else{if(i.result){return d("u2fRegistered","positive")}}},error:a})}})}})};b=function(){return $.ajax({type:"POST",url:portal+"u2fregister/unregistration",data:{},dataType:"json",error:a,success:function(f){if(f.error){return d("u2fFailed","warning")}else{if(f.result){return d("u2fUnregistered","positive")}}},error:a})};e=function(){return $.ajax({type:"POST",url:portal+"u2fregister/verify",data:{},dataType:"json",error:a,success:function(f){var g;g=[{keyHandle:f.keyHandle,version:f.version}];d("touchU2fDevice","positive");return u2f.sign(f.appId,f.challenge,g,function(h){if(h.errorCode){return d("unableToGetU2FKey","warning")}else{return $.ajax({type:"POST",url:portal+"u2fregister/signature",data:{signature:JSON.stringify(h)},dataType:"json",success:function(i){if(i.error){return d("u2fFailed","warning")}else{if(i.result){return d("u2fSuccess","positive")}}},error:function(k,i,l){return console.log("error",l)}})}})}})};$(document).ready(function(){$("#u2fPermission").hide();$("#register").on("click",c);$("#unregister").on("click",b);$("#verify").on("click",e);return $("#goback").attr("href",portal)})}).call(this);

View File

@ -218,6 +218,7 @@
"yourIdentity":"هويتك",
"yourIdentityIs":"هويتك هي",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"رقم هاتفك",
"yourProfile":"ملفك الشخصي",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Votre identité",
"yourIdentityIs":"Votre identité est",
"yourKeyIsRegistered":"Votre clef est enregistrée",
"yourKeyIsUnregistered":"Votre clef a été supprimée",
"yourNewTotpKey":"Votre nouvelle clef TOTP, testez-la et entrez le code",
"yourPhone":"Votre numéro de téléphone",
"yourProfile":"Vos informations personnelles",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Identità",
"yourIdentityIs":"La tua identità é",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Numero di telefono",
"yourProfile":"Il tuo profilo",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Your phone number",
"yourProfile":"Your profile",

View File

@ -218,6 +218,7 @@
"yourIdentity":"Nhận dạng của bạn",
"yourIdentityIs":"Nhận dạng của bạn là",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",
"yourPhone":"Số điện thoại của bạn",
"yourProfile":"Profile của bạn",

View File

@ -1,37 +1,33 @@
<TMPL_INCLUDE NAME="header.tpl">
<div class="container">
<div id="color" class="message message-positive alert"><span id="msg" trspan="u2fWelcome"></span></div>
<div id="color" class="message message-positive alert"><span id="msg" trspan="u2fWelcome"></span></div>
</div>
<main id="menucontent" class="container">
<div class="panel panel-info">
<div class="panel-body">
<div id="u2fPermission" trspan="u2fPermission" class="alert alert-info">You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.</div>
<div class="buttons">
<span id="register" class="btn btn-warning" role="button">
<span class="glyphicon glyphicon-plus-sign"></span>&nbsp;
<span trspan="register">Register</span>
</span>
<span id="verify" class="btn btn-success" role="button">
<span class="glyphicon glyphicon-check"></span>&nbsp;
<span trspan="verify">Verify</span>
</span>
<span id="unregister" class="btn btn-danger" role="button">
<span class="glyphicon glyphicon-minus-sign"></span>&nbsp;
<span trspan="unregister">Unregister</span>
</span>
</div>
</div>
</div>
<div class="panel panel-info">
<div class="panel-body">
<div id="u2fPermission" trspan="u2fPermission" class="alert alert-info">You may be prompted to allow the site permission to access your security keys. After granting permission, the device will start to blink.</div>
<div class="buttons">
<span id="register" class="btn btn-warning" role="button">
<span class="glyphicon glyphicon-plus-sign"></span>&nbsp;
<span trspan="register">Register</span>
</span>
<span id="verify" class="btn btn-success" role="button">
<span class="glyphicon glyphicon-check"></span>&nbsp;
<span trspan="verify">Verify</span>
</span>
<span id="unregister" class="btn btn-danger" role="button">
<span class="glyphicon glyphicon-minus-sign"></span>&nbsp;
<span trspan="unregister">Unregister</span>
</span>
</div>
</div>
</div>
</main>
<div class="buttons">
<a id="goback" href="<TMPL_VAR NAME="PORTAL_URL"><TMPL_IF NAME="AUTH_URL">/?url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>" class="btn btn-primary" role="button">
<!--
<a id="goback" href="" class="btn btn-primary" role="button">
-->
<span class="glyphicon glyphicon-home"></span>&nbsp;
<span trspan="goToPortal">Go to portal</span>
</a>