Merge branch 'portal-multi-U2F-registration' into 'master'
Portal multi u2f registration See merge request lemonldap-ng/lemonldap-ng!24
This commit is contained in:
commit
22e5cf5bf0
|
@ -3004,19 +3004,19 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'select' => [
|
'select' => [
|
||||||
{
|
{
|
||||||
'k' => '0',
|
'k' => 0,
|
||||||
'v' => 'unsecuredCookie'
|
'v' => 'unsecuredCookie'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'k' => '1',
|
'k' => 1,
|
||||||
'v' => 'securedCookie'
|
'v' => 'securedCookie'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'k' => '2',
|
'k' => 2,
|
||||||
'v' => 'doubleCookie'
|
'v' => 'doubleCookie'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'k' => '3',
|
'k' => 3,
|
||||||
'v' => 'doubleCookieForSingleSession'
|
'v' => 'doubleCookieForSingleSession'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -233,7 +233,6 @@ sub run {
|
||||||
return $self->p->sendError( $req, "Corrupted session", 500 );
|
return $self->p->sendError( $req, "Corrupted session", 500 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
$self->logger->debug("No 2F Device found");
|
$self->logger->debug("No 2F Device found");
|
||||||
$_2fDevices = [];
|
$_2fDevices = [];
|
||||||
|
|
|
@ -51,23 +51,47 @@ sub init {
|
||||||
sub run {
|
sub run {
|
||||||
my ( $self, $req, $token ) = @_;
|
my ( $self, $req, $token ) = @_;
|
||||||
|
|
||||||
my ( $kh, $uk );
|
|
||||||
|
|
||||||
# Check if user is registered
|
# Check if user is registered
|
||||||
if ( my $res = $self->loadUser( $req, $req->sessionInfo ) ) {
|
if ( my $res = $self->loadUser( $req, $req->sessionInfo ) ) {
|
||||||
return PE_ERROR if ( $res == -1 );
|
return PE_ERROR if ( $res == -1 );
|
||||||
return PE_U2FFAILED if ( $res == 0 );
|
return PE_U2FFAILED if ( $res == 0 );
|
||||||
|
|
||||||
my $challenge = $req->datas->{crypter}->authenticationChallenge;
|
# Get a challenge (from first key)
|
||||||
$self->ott->updateToken( $token,
|
my $data = eval {
|
||||||
__ch => JSON::from_json($challenge)->{challenge} );
|
from_json( $req->datas->{crypter}->[0]->authenticationChallenge );
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($@) {
|
||||||
|
$self->logger->error( Crypt::U2F::Server::u2fclib_getError() );
|
||||||
|
return PE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get registered keys
|
||||||
|
my @rk;
|
||||||
|
foreach ( @{ $req->datas->{crypter} } ) {
|
||||||
|
my $k = push @rk,
|
||||||
|
{ keyHandle => $_->{keyHandle}, version => $data->{version} };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->ott->updateToken( $token, __ch => $data->{challenge} );
|
||||||
|
|
||||||
|
# Serialize datas
|
||||||
|
$data = to_json(
|
||||||
|
{
|
||||||
|
challenge => $data->{challenge},
|
||||||
|
appId => $data->{appId},
|
||||||
|
registeredKeys => \@rk
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
my $tmp = $self->p->sendHtml(
|
my $tmp = $self->p->sendHtml(
|
||||||
$req,
|
$req,
|
||||||
'u2fcheck',
|
'u2fcheck',
|
||||||
params => {
|
params => {
|
||||||
SKIN => $self->conf->{portalSkin},
|
SKIN => $self->conf->{portalSkin},
|
||||||
CHALLENGE => $challenge,
|
DATA => $data,
|
||||||
TOKEN => $token
|
TOKEN => $token
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$self->logger->debug("Prepare U2F verification");
|
$self->logger->debug("Prepare U2F verification");
|
||||||
|
@ -91,19 +115,40 @@ sub verify {
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->logger->debug("Get challenge: $challenge");
|
$self->logger->debug("Get challenge: $challenge");
|
||||||
|
|
||||||
unless ( $session->{__ch} and $session->{__ch} eq $challenge ) {
|
unless ( $session->{__ch} and $session->{__ch} eq $challenge ) {
|
||||||
$self->userLogger->error("U2F challenge changes by user !!! $session->{__ch}/$challenge");
|
$self->userLogger->error(
|
||||||
|
"U2F challenge changes by user !!! $session->{__ch} / $challenge"
|
||||||
|
);
|
||||||
$req->error(PE_BADCREDENTIALS);
|
$req->error(PE_BADCREDENTIALS);
|
||||||
return $self->fail($req);
|
return $self->fail($req);
|
||||||
}
|
}
|
||||||
delete $session->{__ch};
|
delete $session->{__ch};
|
||||||
if ( not $req->datas->{crypter}->setChallenge($challenge) ) {
|
|
||||||
|
$self->logger->debug("Get signature: $resp");
|
||||||
|
my $data = eval { JSON::from_json($resp) };
|
||||||
|
if ($@) {
|
||||||
|
$self->logger->error("U2F response error: $@");
|
||||||
|
$req->error(PE_ERROR);
|
||||||
|
return $self->fail($req);
|
||||||
|
}
|
||||||
|
my $crypter;
|
||||||
|
foreach ( @{ $req->datas->{crypter} } ) {
|
||||||
|
$crypter = $_ if ( $_->{keyHandle} eq $data->{keyHandle} );
|
||||||
|
}
|
||||||
|
unless ($crypter) {
|
||||||
|
$self->userLogger->error("Unregistered U2F key");
|
||||||
|
$req->error(PE_BADCREDENTIALS);
|
||||||
|
return $self->fail($req);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( not $crypter->setChallenge($challenge) ) {
|
||||||
$self->logger->error(
|
$self->logger->error(
|
||||||
$@ ? $@ : Crypt::U2F::Server::Simple::lastError() );
|
$@ ? $@ : Crypt::U2F::Server::Simple::lastError() );
|
||||||
$req->error(PE_ERROR);
|
$req->error(PE_ERROR);
|
||||||
return $self->fail($req);
|
return $self->fail($req);
|
||||||
}
|
}
|
||||||
if ( $req->datas->{crypter}->authenticationVerify($resp) ) {
|
if ( $crypter->authenticationVerify($resp) ) {
|
||||||
$self->userLogger->info('U2F signature verified');
|
$self->userLogger->info('U2F signature verified');
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +158,6 @@ sub verify {
|
||||||
. Crypt::U2F::Server::u2fclib_getError()
|
. Crypt::U2F::Server::u2fclib_getError()
|
||||||
. ')' );
|
. ')' );
|
||||||
$req->error(PE_U2FFAILED);
|
$req->error(PE_U2FFAILED);
|
||||||
$req->authResult(PE_U2FFAILED);
|
|
||||||
return $self->fail($req);
|
return $self->fail($req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,34 +204,49 @@ sub loadUser {
|
||||||
$self->logger->debug("2F Device(s) found");
|
$self->logger->debug("2F Device(s) found");
|
||||||
|
|
||||||
foreach (@$_2fDevices) {
|
foreach (@$_2fDevices) {
|
||||||
$self->logger->debug("Reading U2F keys if exists ...");
|
$self->logger->debug("Looking for registered U2F key(s) ...");
|
||||||
if ( $_->{type} eq 'U2F' ) {
|
if ( $_->{type} eq 'U2F' ) {
|
||||||
$self->logger->debug( "_userKey = " . $_->{_userKey} );
|
unless ( $_->{_userKey} and $_->{_userKey} ) {
|
||||||
$self->logger->debug( "_keyHandle = " . $_->{_keyHandle} );
|
$self->logger->error(
|
||||||
|
"Missing required U2F attributes in storage ($session->{_2fDevices})"
|
||||||
|
);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$self->logger->debug( "Found U2F key -> _userKey = "
|
||||||
|
. $_->{_userKey}
|
||||||
|
. "/ _keyHandle = "
|
||||||
|
. $_->{_keyHandle} );
|
||||||
$_->{_userKey} = $self->decode_base64url( $_->{_userKey} );
|
$_->{_userKey} = $self->decode_base64url( $_->{_userKey} );
|
||||||
push @u2fs, $_;
|
push @u2fs, $_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#### TOTO : MANAGE MULTI U2F KEYS
|
# Manage multi u2f keys
|
||||||
if ( ( $kh = $u2fs[0]{_keyHandle} )
|
my @crypters;
|
||||||
and ( $uk = $u2fs[0]{_userKey} ) )
|
if (@u2fs) {
|
||||||
{
|
|
||||||
$self->logger->debug("kh & uk -> OK");
|
$self->logger->debug("kh & uk -> OK");
|
||||||
$req->datas->{crypter} = $self->crypter(
|
|
||||||
keyHandle => $kh,
|
foreach (@u2fs) {
|
||||||
publicKey => $uk
|
$kh = $_->{_keyHandle};
|
||||||
);
|
$uk = $_->{_userKey};
|
||||||
unless ( $req->datas->{crypter} ) {
|
my $c = $self->crypter( keyHandle => $kh, publicKey => $uk );
|
||||||
$self->logger->error(
|
if ($c) {
|
||||||
'U2F error: ' . Crypt::U2F::Server::u2fclib_getError() );
|
push @crypters, $c;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$self->logger->error(
|
||||||
|
'U2F error: ' . Crypt::U2F::Server::u2fclib_getError() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unless (@crypters) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
$req->datas->{crypter} = \@crypters;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->userLogger->info("U2F: user not registered");
|
$self->userLogger->info("U2F : user not registered");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,8 @@ LemonLDAP::NG U2F verify script
|
||||||
###
|
###
|
||||||
|
|
||||||
check = ->
|
check = ->
|
||||||
registeredKey = [
|
u2f.sign window.datas.appId, window.datas.challenge, window.datas.registeredKeys, (data) ->
|
||||||
keyHandle: window.datas.keyHandle
|
$('#verify-data').val JSON.stringify data
|
||||||
version: window.datas.version
|
|
||||||
]
|
|
||||||
console.log 'Key: ', registeredKey
|
|
||||||
u2f.sign window.datas.appId, window.datas.challenge, registeredKey, (data) ->
|
|
||||||
$('#verify-data').val JSON.stringify(data)
|
|
||||||
$('#verify-challenge').val window.datas.challenge
|
$('#verify-challenge').val window.datas.challenge
|
||||||
$('#verify-form').submit()
|
$('#verify-form').submit()
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ verify = ->
|
||||||
u2f.sign ch.appId, ch.challenge, request, (data) ->
|
u2f.sign ch.appId, ch.challenge, request, (data) ->
|
||||||
# Handle errors
|
# Handle errors
|
||||||
if data.errorCode
|
if data.errorCode
|
||||||
setMsg 'unableToGetU2FKey', 'warning'
|
setMsg 'unableToGetKey', 'warning'
|
||||||
else
|
else
|
||||||
# 3 send response
|
# 3 send response
|
||||||
$.ajax
|
$.ajax
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Generated by CoffeeScript 1.12.7
|
// Generated by CoffeeScript 1.9.3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LemonLDAP::NG U2F verify script
|
LemonLDAP::NG U2F verify script
|
||||||
|
@ -8,15 +8,7 @@ LemonLDAP::NG U2F verify script
|
||||||
var check;
|
var check;
|
||||||
|
|
||||||
check = function() {
|
check = function() {
|
||||||
var registeredKey;
|
return u2f.sign(window.datas.appId, window.datas.challenge, window.datas.registeredKeys, function(data) {
|
||||||
registeredKey = [
|
|
||||||
{
|
|
||||||
keyHandle: window.datas.keyHandle,
|
|
||||||
version: window.datas.version
|
|
||||||
}
|
|
||||||
];
|
|
||||||
console.log('Key: ', registeredKey);
|
|
||||||
return u2f.sign(window.datas.appId, window.datas.challenge, registeredKey, function(data) {
|
|
||||||
$('#verify-data').val(JSON.stringify(data));
|
$('#verify-data').val(JSON.stringify(data));
|
||||||
$('#verify-challenge').val(window.datas.challenge);
|
$('#verify-challenge').val(window.datas.challenge);
|
||||||
return $('#verify-form').submit();
|
return $('#verify-form').submit();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
(function(){var a;a=function(){var b;b=[{keyHandle:window.datas.keyHandle,version:window.datas.version}];console.log("Key: ",b);return u2f.sign(window.datas.appId,window.datas.challenge,b,function(c){$("#verify-data").val(JSON.stringify(c));$("#verify-challenge").val(window.datas.challenge);return $("#verify-form").submit()})};$(document).ready(function(){return setTimeout(a,1000)})}).call(this);
|
(function(){var a;a=function(){return u2f.sign(window.datas.appId,window.datas.challenge,window.datas.registeredKeys,function(b){$("#verify-data").val(JSON.stringify(b));$("#verify-challenge").val(window.datas.challenge);return $("#verify-form").submit()})};$(document).ready(function(){return setTimeout(a,1000)})}).call(this);
|
|
@ -92,7 +92,7 @@ LemonLDAP::NG U2F registration script
|
||||||
setMsg('touchU2fDevice', 'positive');
|
setMsg('touchU2fDevice', 'positive');
|
||||||
return u2f.sign(ch.appId, ch.challenge, request, function(data) {
|
return u2f.sign(ch.appId, ch.challenge, request, function(data) {
|
||||||
if (data.errorCode) {
|
if (data.errorCode) {
|
||||||
return setMsg('unableToGetU2FKey', 'warning');
|
return setMsg('unableToGetKey', 'warning');
|
||||||
} else {
|
} else {
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
(function(){var a,b,c,d;c=function(e,f){$("#msg").html(window.translate(e));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+f);if(f==="positive"){f="success"}return $("#color").addClass("alert-"+f)};a=function(f,e,h){var g;console.log("Error",h);g=JSON.parse(f.responseText);if(g&&g.error){g=g.error.replace(/.* /,"");console.log("Returned error",g);return c(g,"warning")}};b=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/register",data:{},dataType:"json",error:a,success:function(e){var f;f=[{challenge:e.challenge,version:e.version}];c("touchU2fDevice","positive");$("#u2fPermission").show();return u2f.register(e.appId,f,[],function(g){$("#u2fPermission").hide();if(g.errorCode){return c(g.error,"warning")}else{return $.ajax({type:"POST",url:portal+"2fregisters/u/registration",data:{registration:JSON.stringify(g),challenge:JSON.stringify(e),keyName:$("#keyName").val()},dataType:"json",success:function(h){if(h.error){return c("u2fFailed","warning")}else{if(h.result){return c("yourKeyIsRegistered","positive")}}},error:a})}})}})};d=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/verify",data:{},dataType:"json",error:a,success:function(e){var f;f=[{keyHandle:e.keyHandle,version:e.version}];c("touchU2fDevice","positive");return u2f.sign(e.appId,e.challenge,f,function(g){if(g.errorCode){return c("unableToGetU2FKey","warning")}else{return $.ajax({type:"POST",url:portal+"2fregisters/u/signature",data:{signature:JSON.stringify(g),challenge:e.challenge},dataType:"json",success:function(h){if(h.error){return c("u2fFailed","warning")}else{if(h.result){return c("yourKeyIsVerified","positive")}}},error:function(i,h,k){return console.log("error",k)}})}})}})};$(document).ready(function(){$("#u2fPermission").hide();$("#register").on("click",b);$("#verify").on("click",d);return $("#goback").attr("href",portal)})}).call(this);
|
(function(){var a,b,c,d;c=function(e,f){$("#msg").html(window.translate(e));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+f);if(f==="positive"){f="success"}return $("#color").addClass("alert-"+f)};a=function(f,e,h){var g;console.log("Error",h);g=JSON.parse(f.responseText);if(g&&g.error){g=g.error.replace(/.* /,"");console.log("Returned error",g);return c(g,"warning")}};b=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/register",data:{},dataType:"json",error:a,success:function(e){var f;f=[{challenge:e.challenge,version:e.version}];c("touchU2fDevice","positive");$("#u2fPermission").show();return u2f.register(e.appId,f,[],function(g){$("#u2fPermission").hide();if(g.errorCode){return c(g.error,"warning")}else{return $.ajax({type:"POST",url:portal+"2fregisters/u/registration",data:{registration:JSON.stringify(g),challenge:JSON.stringify(e),keyName:$("#keyName").val()},dataType:"json",success:function(h){if(h.error){return c("u2fFailed","warning")}else{if(h.result){return c("yourKeyIsRegistered","positive")}}},error:a})}})}})};d=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/verify",data:{},dataType:"json",error:a,success:function(e){var f;f=[{keyHandle:e.keyHandle,version:e.version}];c("touchU2fDevice","positive");return u2f.sign(e.appId,e.challenge,f,function(g){if(g.errorCode){return c("unableToGetKey","warning")}else{return $.ajax({type:"POST",url:portal+"2fregisters/u/signature",data:{signature:JSON.stringify(g),challenge:e.challenge},dataType:"json",success:function(h){if(h.error){return c("u2fFailed","warning")}else{if(h.result){return c("yourKeyIsVerified","positive")}}},error:function(i,h,k){return console.log("error",k)}})}})}})};$(document).ready(function(){$("#u2fPermission").hide();$("#register").on("click",b);$("#verify").on("click",d);return $("#goback").attr("href",portal)})}).call(this);
|
|
@ -82,7 +82,7 @@
|
||||||
"PE80":"This address is already used",
|
"PE80":"This address is already used",
|
||||||
"PE81":"Invalid authentication attempt",
|
"PE81":"Invalid authentication attempt",
|
||||||
"PE82":"Exceeded authentication timeout",
|
"PE82":"Exceeded authentication timeout",
|
||||||
"PE83":"U2F verification failed",
|
"PE83":"U2F verification failed. Retry or contact your administrator",
|
||||||
"PE84":"You're not authorized to access to this host",
|
"PE84":"You're not authorized to access to this host",
|
||||||
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
||||||
"2FManagment":"2ndF Managment",
|
"2FManagment":"2ndF Managment",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
"PE80":"Esta dirección ya está utilizada",
|
"PE80":"Esta dirección ya está utilizada",
|
||||||
"PE81":"Invalid authentication attempt",
|
"PE81":"Invalid authentication attempt",
|
||||||
"PE82":"Exceeded authentication timeout",
|
"PE82":"Exceeded authentication timeout",
|
||||||
"PE83":"U2F verification failed",
|
"PE83":"U2F verification failed. Retry or contact your administrator",
|
||||||
"PE84":"You're not authorized to access to this host",
|
"PE84":"You're not authorized to access to this host",
|
||||||
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
||||||
"2FManagment":"2ndF Managment",
|
"2FManagment":"2ndF Managment",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
"PE80":"Cette adresse est déjà utilisée",
|
"PE80":"Cette adresse est déjà utilisée",
|
||||||
"PE81":"Tentative d'authentification invalide",
|
"PE81":"Tentative d'authentification invalide",
|
||||||
"PE82":"Délai d'authentification dépassé",
|
"PE82":"Délai d'authentification dépassé",
|
||||||
"PE83":"La vérification U2F a échoué",
|
"PE83":"La vérification U2F a échoué. Réessayez ou contactez votre administrateur",
|
||||||
"PE84":"Vous n'êtes pas autorisé à accéder à ce site",
|
"PE84":"Vous n'êtes pas autorisé à accéder à ce site",
|
||||||
"PE85":"Le site souhaite une authentification plus récente (et le plugin UpgradeSession n'est pas chargé). Déconnectez-vous et réessayez",
|
"PE85":"Le site souhaite une authentification plus récente (et le plugin UpgradeSession n'est pas chargé). Déconnectez-vous et réessayez",
|
||||||
"2FManagment":"Gestionnaire 2ndF",
|
"2FManagment":"Gestionnaire 2ndF",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
"PE80":"Dit adres is al in gebruik",
|
"PE80":"Dit adres is al in gebruik",
|
||||||
"PE81":"Invalid authentication attempt",
|
"PE81":"Invalid authentication attempt",
|
||||||
"PE82":"Exceeded authentication timeout",
|
"PE82":"Exceeded authentication timeout",
|
||||||
"PE83":"U2F verification failed",
|
"PE83":"U2F verification failed. Retry or contact your administrator",
|
||||||
"PE84":"You're not authorized to access to this host",
|
"PE84":"You're not authorized to access to this host",
|
||||||
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
||||||
"2FManagment":"Gestionnaire 2ndF",
|
"2FManagment":"Gestionnaire 2ndF",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
"PE80":"Este endereço já é utilizado",
|
"PE80":"Este endereço já é utilizado",
|
||||||
"PE81":"Invalid authentication attempt",
|
"PE81":"Invalid authentication attempt",
|
||||||
"PE82":"Exceeded authentication timeout",
|
"PE82":"Exceeded authentication timeout",
|
||||||
"PE83":"U2F verification failed",
|
"PE83":"U2F verification failed. Retry or contact your administrator",
|
||||||
"PE84":"You're not authorized to access to this host",
|
"PE84":"You're not authorized to access to this host",
|
||||||
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
||||||
"2FManagment":"Gestionnaire 2ndF",
|
"2FManagment":"Gestionnaire 2ndF",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
"PE80":"This address is already used",
|
"PE80":"This address is already used",
|
||||||
"PE81":"Invalid authentication attempt",
|
"PE81":"Invalid authentication attempt",
|
||||||
"PE82":"Exceeded authentication timeout",
|
"PE82":"Exceeded authentication timeout",
|
||||||
"PE83":"U2F verification failed",
|
"PE83":"U2F verification failed. Retry or contact your administrator",
|
||||||
"PE84":"You're not authorized to access to this host",
|
"PE84":"You're not authorized to access to this host",
|
||||||
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
"PE85":"The remote site ask for a newer session (and UpgradeSession plugin isn't loaded). Logout and retry",
|
||||||
"2FManagment":"Gestionnaire 2ndF",
|
"2FManagment":"Gestionnaire 2ndF",
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
<span id="verify" class="btn btn-success" role="button">
|
<span id="verify" class="btn btn-success" role="button">
|
||||||
<span class="glyphicon glyphicon-check"></span>
|
<span class="glyphicon glyphicon-check"></span>
|
||||||
<span trspan="verify">Verify</span>
|
<span trspan="register">Register</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,12 +5,7 @@
|
||||||
<TMPL_IF NAME="AUTH_ERROR">
|
<TMPL_IF NAME="AUTH_ERROR">
|
||||||
<div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
|
<div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert"><span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span></div>
|
||||||
</TMPL_IF>
|
</TMPL_IF>
|
||||||
|
<TMPL_IF NAME="DATA">
|
||||||
<TMPL_IF NAME="FAILED">
|
|
||||||
<p trspan="u2fFailed"></p>
|
|
||||||
</TMPL_IF>
|
|
||||||
|
|
||||||
<TMPL_IF NAME="CHALLENGE">
|
|
||||||
<div class="message message-positive alert"><span trspan="touchU2fDevice"></span></div>
|
<div class="message message-positive alert"><span trspan="touchU2fDevice"></span></div>
|
||||||
<form id="verify-form" action="/u2fcheck" method="post">
|
<form id="verify-form" action="/u2fcheck" method="post">
|
||||||
<input type="hidden" id="verify-data" name="signature" value="">
|
<input type="hidden" id="verify-data" name="signature" value="">
|
||||||
|
@ -18,7 +13,7 @@
|
||||||
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">">
|
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">">
|
||||||
</form>
|
</form>
|
||||||
<script type="application/init">
|
<script type="application/init">
|
||||||
<TMPL_VAR NAME="CHALLENGE">
|
<TMPL_VAR NAME="DATA">
|
||||||
</script>
|
</script>
|
||||||
<!-- //if:jsminified
|
<!-- //if:jsminified
|
||||||
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/u2f-api.min.js"></script>
|
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">/common/js/u2f-api.min.js"></script>
|
||||||
|
|
|
@ -147,22 +147,22 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
|
||||||
( $host, $url, $query ) = expectForm( $res, undef, '/u2fcheck', 'token' );
|
( $host, $url, $query ) = expectForm( $res, undef, '/u2fcheck', 'token' );
|
||||||
|
|
||||||
# Get challenge
|
# Get challenge
|
||||||
ok( $res->[2]->[0] =~ /^.*"keyHandle".*$/m, ' get keyHandle' );
|
ok( $res->[2]->[0] =~ /^.*"keyHandle":.*$/m, ' get keyHandle' );
|
||||||
$data = $&;
|
$data = "$&";
|
||||||
eval { $data = JSON::from_json($data) };
|
eval { $data = JSON::from_json($data) };
|
||||||
ok( not($@), ' Content is JSON' )
|
ok( not($@), ' Content is JSON' )
|
||||||
or explain( [ $@, $data ], 'JSON content' );
|
or explain( [ $@, $data ], 'JSON content' );
|
||||||
|
|
||||||
# Build U2F signature
|
# Build U2F signature
|
||||||
$r =
|
$r =
|
||||||
$tester->sign( $data->{appId}, $data->{challenge}, $data->{keyHandle} );
|
$tester->sign( $data->{appId}, $data->{challenge}, $data->{registeredKeys}->[0]->{keyHandle} );
|
||||||
ok( $r->is_success, ' Good challenge value' ) or diag( $r->error_message );
|
ok( $r->is_success, ' Good challenge value' ) or diag( $r->error_message );
|
||||||
my $sign = JSON::to_json(
|
my $sign = JSON::to_json(
|
||||||
{
|
{
|
||||||
errorCode => 0,
|
errorCode => 0,
|
||||||
signatureData => $r->signature_data,
|
signatureData => $r->signature_data,
|
||||||
clientData => $r->client_data,
|
clientData => $r->client_data,
|
||||||
keyHandle => $data->{keyHandle},
|
keyHandle => $data->{registeredKeys}->[0]->{keyHandle},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$sign =
|
$sign =
|
||||||
|
|
Loading…
Reference in New Issue
Block a user