Improve unit test (#1515)

test main logo link
environments/ppa-mbqj77/deployments/393
Christophe Maudoux 7 years ago
parent e81bd64876
commit 25ca799302
  1. 39
      lemonldap-ng-portal/t/61-GrantSession.t
  2. 23
      lemonldap-ng-portal/t/63-History.t
  3. 37
      lemonldap-ng-portal/t/70-2F-TOTP.t
  4. 66
      lemonldap-ng-portal/t/71-2F-U2F.t
  5. 26
      lemonldap-ng-portal/t/72-2F-REST-with-HISTORY.t
  6. 105
      lemonldap-ng-portal/t/73-2F-UTOTP-TOTP-and-U2F.t
  7. 65
      lemonldap-ng-portal/t/75-2F-Registers.t

@ -10,11 +10,11 @@ BEGIN {
my $res; my $res;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
logLevel => 'error', logLevel => 'error',
authentication => 'Demo', authentication => 'Demo',
userdb => 'Same', userdb => 'Same',
portalMainLogo => 'common/logos/test.png',
grantSessionRules => { grantSessionRules => {
'$uid . " not allowed"##rule1' => '$uid ne "dwho"', '$uid . " not allowed"##rule1' => '$uid ne "dwho"',
'Rtyler_Allowed##rule3' => '$uid eq "rtyler"', 'Rtyler_Allowed##rule3' => '$uid eq "rtyler"',
@ -24,8 +24,7 @@ my $client = LLNG::Manager::Test->new(
} }
); );
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
accept => 'text/html', accept => 'text/html',
@ -35,16 +34,18 @@ ok(
); );
count(1); count(1);
ok( $res->[2]->[0] =~ /<h3 trspan="dwho not allowed">dwho not allowed<\/h3>/, ok( $res->[2]->[0] =~ /<h3 trspan="dwho not allowed">dwho not allowed<\/h3>/,
'dwho rejected with custom message and session data' ) 'dwho rejected with custom message and session data'
or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res->[2]->[0] =~ qr%src="/static/common/js/info.(?:min\.)?js"></script>%, ok( $res->[2]->[0] =~ qr%src="/static/common/js/info.(?:min\.)?js"></script>%,
'Found INFO js' ) 'Found INFO js'
or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
ok( 'Found custom Main Logo' )
$res = $client->_post( or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok( $res = $client->_post(
'/', '/',
IO::String->new('user=rtyler&password=rtyler'), IO::String->new('user=rtyler&password=rtyler'),
length => 27 length => 27
@ -55,8 +56,7 @@ count(1);
expectOK($res); expectOK($res);
expectCookie($res); expectCookie($res);
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=mrsmith&password=mrsmith'), IO::String->new('user=mrsmith&password=mrsmith'),
accept => 'text/html', accept => 'text/html',
@ -65,11 +65,14 @@ ok(
'Auth query' 'Auth query'
); );
count(1); count(1);
ok( ok( $res->[2]->[0] =~ /<span trmsg="4"><\/span><\/div>/,
$res->[2]->[0] =~ /<span trmsg="4"><\/span><\/div>/,
'rtyler rejected with PE_SESSIONNOTGRANTED' 'rtyler rejected with PE_SESSIONNOTGRANTED'
) or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
my $c = getCookies($res); my $c = getCookies($res);
ok( not(%$c), 'No cookie' ); ok( not(%$c), 'No cookie' );
@ -77,8 +80,7 @@ count(1);
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 ); &Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
$client = LLNG::Manager::Test->new( $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
authentication => 'Demo', authentication => 'Demo',
userdb => 'Same', userdb => 'Same',
grantSessionRules => { '' => '$uid eq "dwho"', } grantSessionRules => { '' => '$uid eq "dwho"', }
@ -86,8 +88,7 @@ $client = LLNG::Manager::Test->new(
} }
); );
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23

@ -10,11 +10,12 @@ my $res;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { { ini => {
logLevel => 'error', logLevel => 'error',
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
loginHistoryEnabled => 1, loginHistoryEnabled => 1,
brutForceProtection => 0, brutForceProtection => 0,
portalMainLogo => 'common/logos/test.png',
sessionDataToRemember => sessionDataToRemember =>
{ uid => 'identity', _auth => 'AuthModule' }, { uid => 'identity', _auth => 'AuthModule' },
} }
@ -33,6 +34,10 @@ ok( $res = $client->_post(
count(1); count(1);
expectOK($res); expectOK($res);
my $id1 = expectCookie($res); my $id1 = expectCookie($res);
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' ) ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' )
or explain( $res->[2]->[0], 'trspan="noHistory"' ); or explain( $res->[2]->[0], 'trspan="noHistory"' );
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs ); my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
@ -107,15 +112,15 @@ $id1 = expectCookie($res);
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' ); ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' );
@c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs ); @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
my @cf = ( $res->[2]->[0] =~ /PE5<\/td>/gs ); my @cf = ( $res->[2]->[0] =~ /PE5<\/td>/gs );
my @ccv1 = ( $res->[2]->[0] =~ /<td>dwho<\/td>/gs ); my @ccv1 = ( $res->[2]->[0] =~ /<td>dwho<\/td>/gs );
my @ccv2 = ( $res->[2]->[0] =~ /<td>Demo<\/td>/gs ); my @ccv2 = ( $res->[2]->[0] =~ /<td>Demo<\/td>/gs );
# History with 5 entries and 10 custom values # History with 5 entries and 10 custom values
ok( @c == 5, ' -> Five entries found' ); ok( @c == 5, ' -> Five entries found' );
ok( @cf == 2, " -> Two 'failedLogin' entries found" ); ok( @cf == 2, " -> Two 'failedLogin' entries found" );
ok( @ccv1 + @ccv2 == 10, " -> Ten custom value entries found" ) ok( @ccv1 + @ccv2 == 10, " -> Ten custom value entries found" )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(4); count(4);
$client->logout($id1); $client->logout($id1);

@ -13,11 +13,11 @@ SKIP: {
require Lemonldap::NG::Common::TOTP; require Lemonldap::NG::Common::TOTP;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
logLevel => 'error', logLevel => 'error',
totp2fSelfRegistration => 1, totp2fSelfRegistration => 1,
totp2fActivation => 1, totp2fActivation => 1,
portalMainLogo => 'common/logos/test.png',
} }
} }
); );
@ -25,8 +25,7 @@ SKIP: {
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23
@ -36,8 +35,7 @@ SKIP: {
my $id = expectCookie($res); my $id = expectCookie($res);
# TOTP form # TOTP form
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -45,8 +43,7 @@ SKIP: {
'Form registration' 'Form registration'
); );
expectRedirection( $res, qr#/2fregisters/totp$# ); expectRedirection( $res, qr#/2fregisters/totp$# );
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters/totp', '/2fregisters/totp',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -54,10 +51,13 @@ SKIP: {
'Form registration' 'Form registration'
); );
ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' ); ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' );
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
# JS query # JS query
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/getkey', IO::String->new(''), '/2fregisters/totp/getkey', IO::String->new(''),
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
length => 0, length => 0,
@ -66,7 +66,7 @@ SKIP: {
); );
eval { $res = JSON::from_json( $res->[2]->[0] ) }; eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' ) ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' ); or explain( $res->[2]->[0], 'JSON content' );
my ( $key, $token ); my ( $key, $token );
ok( $key = $res->{secret}, 'Found secret' ); ok( $key = $res->{secret}, 'Found secret' );
ok( $token = $res->{token}, 'Found token' ); ok( $token = $res->{token}, 'Found token' );
@ -78,8 +78,7 @@ SKIP: {
'Code' ); 'Code' );
ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' ); ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' );
my $s = "code=$code&token=$token"; my $s = "code=$code&token=$token";
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/verify', '/2fregisters/totp/verify',
IO::String->new($s), IO::String->new($s),
length => length($s), length => length($s),
@ -89,13 +88,12 @@ SKIP: {
); );
eval { $res = JSON::from_json( $res->[2]->[0] ) }; eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' ) ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' ); or explain( $res->[2]->[0], 'JSON content' );
ok( $res->{result} == 1, 'Key is registered' ); ok( $res->{result} == 1, 'Key is registered' );
# Try to sign-in # Try to sign-in
$client->logout($id); $client->logout($id);
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -103,13 +101,12 @@ SKIP: {
), ),
'Auth query' 'Auth query'
); );
my ( $host, $url, $query ) = my ( $host, $url, $query )
expectForm( $res, undef, '/totp2fcheck', 'token' ); = expectForm( $res, undef, '/totp2fcheck', 'token' );
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ), ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
'Code' ); 'Code' );
$query =~ s/code=/code=$code/; $query =~ s/code=/code=$code/;
ok( ok( $res = $client->_post(
$res = $client->_post(
'/totp2fcheck', IO::String->new($query), '/totp2fcheck', IO::String->new($query),
length => length($query), length => length($query),
), ),

@ -13,11 +13,11 @@ SKIP: {
use_ok('Lemonldap::NG::Common::FormEncode'); use_ok('Lemonldap::NG::Common::FormEncode');
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
logLevel => 'error', logLevel => 'error',
u2fSelfRegistration => 1, u2fSelfRegistration => 1,
u2fActivation => 1, u2fActivation => 1,
portalMainLogo => 'common/logos/test.png',
} }
} }
); );
@ -25,8 +25,7 @@ SKIP: {
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23
@ -36,8 +35,7 @@ SKIP: {
my $id = expectCookie($res); my $id = expectCookie($res);
# U2F form # U2F form
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -46,8 +44,7 @@ SKIP: {
); );
expectRedirection( $res, qr#/2fregisters/u$# ); expectRedirection( $res, qr#/2fregisters/u$# );
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters/u', '/2fregisters/u',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -55,10 +52,13 @@ SKIP: {
'Form registration' 'Form registration'
); );
ok( $res->[2]->[0] =~ /u2fregistration\.(?:min\.)?js/, 'Found U2F js' ); ok( $res->[2]->[0] =~ /u2fregistration\.(?:min\.)?js/, 'Found U2F js' );
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
# Ajax registration request # Ajax registration request
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/u/register', IO::String->new(''), '/2fregisters/u/register', IO::String->new(''),
accept => 'application/json', accept => 'application/json',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
@ -70,9 +70,10 @@ SKIP: {
my $data; my $data;
eval { $data = JSON::from_json( $res->[2]->[0] ) }; eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' ) ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' ); or explain( [ $@, $res->[2] ], 'JSON content' );
ok( ( $data->{challenge} and $data->{appId} ), ' Get challenge and appId' ) ok( ( $data->{challenge} and $data->{appId} ),
or explain( $data, 'challenge and appId' ); ' Get challenge and appId' )
or explain( $data, 'challenge and appId' );
# Build U2F tester # Build U2F tester
my $tester = Authen::U2F::Tester->new( my $tester = Authen::U2F::Tester->new(
@ -100,11 +101,11 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
), ),
); );
my $r = $tester->register( $data->{appId}, $data->{challenge} ); my $r = $tester->register( $data->{appId}, $data->{challenge} );
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 $registrationData = JSON::to_json( my $registrationData = JSON::to_json(
{ { clientData => $r->client_data,
clientData => $r->client_data,
errorCode => 0, errorCode => 0,
registrationData => $r->registration_data, registrationData => $r->registration_data,
version => "U2F_V2" version => "U2F_V2"
@ -116,8 +117,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
challenge => $res->[2]->[0], challenge => $res->[2]->[0],
); );
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/u/registration', IO::String->new($query), '/2fregisters/u/registration', IO::String->new($query),
length => length($query), length => length($query),
accept => 'application/json', accept => 'application/json',
@ -128,14 +128,13 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
expectOK($res); expectOK($res);
eval { $data = JSON::from_json( $res->[2]->[0] ) }; eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' ) ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' ); or explain( [ $@, $res->[2] ], 'JSON content' );
ok( $data->{result} == 1, 'Key is registered' ) ok( $data->{result} == 1, 'Key is registered' )
or explain( $data, '"result":1' ); or explain( $data, '"result":1' );
# Try to sign-in # Try to sign-in
$client->logout($id); $client->logout($id);
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -151,31 +150,28 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
$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},
$tester->sign( $data->{appId}, $data->{challenge},
$data->{registeredKeys}->[0]->{keyHandle} ); $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->{registeredKeys}->[0]->{keyHandle}, keyHandle => $data->{registeredKeys}->[0]->{keyHandle},
} }
); );
$sign = $sign = Lemonldap::NG::Common::FormEncode::build_urlencoded(
Lemonldap::NG::Common::FormEncode::build_urlencoded( signature => $sign ); signature => $sign );
$query =~ s/signature=/$sign/e; $query =~ s/signature=/$sign/e;
$query =~ s/challenge=/challenge=$data->{challenge}/; $query =~ s/challenge=/challenge=$data->{challenge}/;
# POST result # POST result
ok( ok( $res = $client->_post(
$res = $client->_post( '/u2fcheck', IO::String->new($query),
'/u2fcheck',
IO::String->new($query),
length => length($query), length => length($query),
), ),
'Push U2F signature' 'Push U2F signature'
@ -188,7 +184,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
else { else {
count(1); count(1);
pass( pass(
'Authen::2F::Tester-0.02 signatures are not recognized by Yubico library' 'Authen::2F::Tester-0.02 signatures are not recognized by Yubico library'
); );
} }
} }

@ -14,11 +14,11 @@ LWP::Protocol::PSGI->register(
my $req = Plack::Request->new(@_); my $req = Plack::Request->new(@_);
if ( $req->path_info eq '/init' ) { if ( $req->path_info eq '/init' ) {
ok( $req->content eq '{"name":"dwho"}', ' Init req gives dwho' ) ok( $req->content eq '{"name":"dwho"}', ' Init req gives dwho' )
or explain( $req->content, '{"name":"dwho"}' ); or explain( $req->content, '{"name":"dwho"}' );
} }
elsif ( $req->path_info eq '/vrfy' ) { elsif ( $req->path_info eq '/vrfy' ) {
ok( $req->content eq '{"code":"1234"}', ' Code is 1234' ) ok( $req->content eq '{"code":"1234"}', ' Code is 1234' )
or explain( $req->content, '{"code":"1234"}' ); or explain( $req->content, '{"code":"1234"}' );
} }
else { else {
fail( ' Bad REST call ' . $req->path_info ); fail( ' Bad REST call ' . $req->path_info );
@ -32,8 +32,7 @@ LWP::Protocol::PSGI->register(
); );
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
logLevel => 'error', logLevel => 'error',
rest2fActivation => 1, rest2fActivation => 1,
rest2fInitUrl => 'http://auth.example.com/init', rest2fInitUrl => 'http://auth.example.com/init',
@ -43,6 +42,7 @@ my $client = LLNG::Manager::Test->new(
loginHistoryEnabled => 1, loginHistoryEnabled => 1,
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
portalMainLogo => 'common/logos/test.png',
} }
} }
); );
@ -50,8 +50,7 @@ my $res;
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,
@ -59,12 +58,17 @@ ok(
), ),
'Auth query' 'Auth query'
); );
my ( $host, $url, $query ) = ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
expectForm( $res, undef, '/rest2fcheck', 'token', 'code', 'checkLogins' ); 'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
my ( $host, $url, $query )
= expectForm( $res, undef, '/rest2fcheck', 'token', 'code',
'checkLogins' );
$query =~ s/code=/code=1234/; $query =~ s/code=/code=1234/;
ok( ok( $res = $client->_post(
$res = $client->_post(
'/rest2fcheck', '/rest2fcheck',
IO::String->new($query), IO::String->new($query),
length => length($query), length => length($query),
@ -75,7 +79,7 @@ ok(
my $id = expectCookie($res); my $id = expectCookie($res);
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' ) ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs ); my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
ok( @c == 1, 'One entry found' ); ok( @c == 1, 'One entry found' );

@ -18,14 +18,14 @@ SKIP: {
require Lemonldap::NG::Common::TOTP; require Lemonldap::NG::Common::TOTP;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
logLevel => 'error', logLevel => 'error',
utotp2fActivation => 1, utotp2fActivation => 1,
totp2fSelfRegistration => 1, totp2fSelfRegistration => 1,
u2fSelfRegistration => 1, u2fSelfRegistration => 1,
portalMainLogo => 'common/logos/test.png',
u2fSelfRegistration => u2fSelfRegistration =>
'$_2fDevices =~ /"type":\s*"(?:TOTP|U2F)"/s', '$_2fDevices =~ /"type":\s*"(?:TOTP|U2F)"/s',
} }
} }
); );
@ -33,8 +33,7 @@ SKIP: {
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23
@ -44,8 +43,7 @@ SKIP: {
my $id = expectCookie($res); my $id = expectCookie($res);
# TOTP form # TOTP form
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -53,8 +51,7 @@ SKIP: {
'Form registration' 'Form registration'
); );
expectRedirection( $res, qr#/2fregisters/totp$# ); expectRedirection( $res, qr#/2fregisters/totp$# );
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters/totp', '/2fregisters/totp',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -62,10 +59,13 @@ SKIP: {
'Form registration' 'Form registration'
); );
ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' ); ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' );
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
# JS query # JS query
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/getkey', IO::String->new(''), '/2fregisters/totp/getkey', IO::String->new(''),
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
length => 0, length => 0,
@ -74,7 +74,7 @@ SKIP: {
); );
eval { $res = JSON::from_json( $res->[2]->[0] ) }; eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' ) ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' ); or explain( $res->[2]->[0], 'JSON content' );
my ( $key, $token ); my ( $key, $token );
ok( $key = $res->{secret}, 'Found secret' ); ok( $key = $res->{secret}, 'Found secret' );
ok( $token = $res->{token}, 'Found token' ); ok( $token = $res->{token}, 'Found token' );
@ -86,8 +86,7 @@ SKIP: {
'Code' ); 'Code' );
ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' ); ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' );
my $s = "code=$code&token=$token"; my $s = "code=$code&token=$token";
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/verify', '/2fregisters/totp/verify',
IO::String->new($s), IO::String->new($s),
length => length($s), length => length($s),
@ -97,13 +96,12 @@ SKIP: {
); );
eval { $res = JSON::from_json( $res->[2]->[0] ) }; eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' ) ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' ); or explain( $res->[2]->[0], 'JSON content' );
ok( $res->{result} = 1, 'Key is registered' ); ok( $res->{result} = 1, 'Key is registered' );
# Try to sing-in # Try to sing-in
$client->logout($id); $client->logout($id);
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -111,13 +109,12 @@ SKIP: {
), ),
'Auth query' 'Auth query'
); );
my ( $host, $url, $query ) = my ( $host, $url, $query )
expectForm( $res, undef, '/utotp2fcheck', 'token' ); = expectForm( $res, undef, '/utotp2fcheck', 'token' );
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ), ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
'Code' ); 'Code' );
$query =~ s/code=/code=$code/; $query =~ s/code=/code=$code/;
ok( ok( $res = $client->_post(
$res = $client->_post(
'/utotp2fcheck', IO::String->new($query), '/utotp2fcheck', IO::String->new($query),
length => length($query), length => length($query),
), ),
@ -126,8 +123,7 @@ SKIP: {
$id = expectCookie($res); $id = expectCookie($res);
# U2F form # U2F form
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -137,8 +133,7 @@ SKIP: {
expectOK($res); expectOK($res);
ok( $res->[2]->[0] =~ m#<a.*href="/2fregisters/u"#, 'Get U2F choice' ); ok( $res->[2]->[0] =~ m#<a.*href="/2fregisters/u"#, 'Get U2F choice' );
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters/u', '/2fregisters/u',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -148,8 +143,7 @@ SKIP: {
ok( $res->[2]->[0] =~ /u2fregistration\.(?:min\.)?js/, 'Found U2F js' ); ok( $res->[2]->[0] =~ /u2fregistration\.(?:min\.)?js/, 'Found U2F js' );
# Ajax registration request # Ajax registration request
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/u/register', IO::String->new(''), '/2fregisters/u/register', IO::String->new(''),
accept => 'application/json', accept => 'application/json',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
@ -161,9 +155,10 @@ SKIP: {
my $data; my $data;
eval { $data = JSON::from_json( $res->[2]->[0] ) }; eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' ) ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' ); or explain( [ $@, $res->[2] ], 'JSON content' );
ok( ( $data->{challenge} and $data->{appId} ), ' Get challenge and appId' ) ok( ( $data->{challenge} and $data->{appId} ),
or explain( $data, 'challenge and appId' ); ' Get challenge and appId' )
or explain( $data, 'challenge and appId' );
# Build U2F tester # Build U2F tester
my $tester = Authen::U2F::Tester->new( my $tester = Authen::U2F::Tester->new(
@ -191,11 +186,11 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
), ),
); );
my $r = $tester->register( $data->{appId}, $data->{challenge} ); my $r = $tester->register( $data->{appId}, $data->{challenge} );
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 $registrationData = JSON::to_json( my $registrationData = JSON::to_json(
{ { clientData => $r->client_data,
clientData => $r->client_data,
errorCode => 0, errorCode => 0,
registrationData => $r->registration_data, registrationData => $r->registration_data,
version => "U2F_V2" version => "U2F_V2"
@ -206,8 +201,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
challenge => $res->[2]->[0], challenge => $res->[2]->[0],
); );
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/u/registration', IO::String->new($query), '/2fregisters/u/registration', IO::String->new($query),
length => length($query), length => length($query),
accept => 'application/json', accept => 'application/json',
@ -218,15 +212,14 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
expectOK($res); expectOK($res);
eval { $data = JSON::from_json( $res->[2]->[0] ) }; eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' ) ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' ); or explain( [ $@, $res->[2] ], 'JSON content' );
ok( $data->{result} == 1, 'Key is registered' ) ok( $data->{result} == 1, 'Key is registered' )
or explain( $data, '"result":1' ); or explain( $data, '"result":1' );
# Try to sign-in with TOTP # Try to sign-in with TOTP
$client->logout($id); $client->logout($id);
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -235,16 +228,15 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
), ),
'Auth query' 'Auth query'
); );
( $host, $url, $query ) = ( $host, $url, $query )
expectForm( $res, undef, '/utotp2fcheck', 'token' ); = expectForm( $res, undef, '/utotp2fcheck', 'token' );
ok( $res->[2]->[0] =~ /input name="code"/, ' get TOTP form' ); ok( $res->[2]->[0] =~ /input name="code"/, ' get TOTP form' );
# Use TOTP # Use TOTP
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ), ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
'Code' ); 'Code' );
$query =~ s/code=/code=$code/; $query =~ s/code=/code=$code/;
ok( ok( $res = $client->_post(
$res = $client->_post(
'/utotp2fcheck', IO::String->new($query), '/utotp2fcheck', IO::String->new($query),
length => length($query), length => length($query),
), ),
@ -254,8 +246,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
$client->logout($id); $client->logout($id);
# Try to sign-in with U2F # Try to sign-in with U2F
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -264,37 +255,35 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
), ),
'Auth query' 'Auth query'
); );
( $host, $url, $query ) = ( $host, $url, $query )
expectForm( $res, undef, '/utotp2fcheck', 'token' ); = expectForm( $res, undef, '/utotp2fcheck', '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},
$tester->sign( $data->{appId}, $data->{challenge},
$data->{registeredKeys}->[0]->{keyHandle} ); $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->{registeredKeys}->[0]->{keyHandle}, keyHandle => $data->{registeredKeys}->[0]->{keyHandle},
} }
); );
$sign = $sign = Lemonldap::NG::Common::FormEncode::build_urlencoded(
Lemonldap::NG::Common::FormEncode::build_urlencoded( signature => $sign ); signature => $sign );
$query =~ s/signature=/$sign/e; $query =~ s/signature=/$sign/e;
$query =~ s/challenge=/challenge=$data->{challenge}/; $query =~ s/challenge=/challenge=$data->{challenge}/;
# POST result # POST result
ok( ok( $res = $client->_post(
$res = $client->_post(
'/utotp2fcheck', IO::String->new($query), '/utotp2fcheck', IO::String->new($query),
length => length($query), length => length($query),
), ),
@ -308,7 +297,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
else { else {
count(1); count(1);
pass( pass(
'Authen::2F::Tester-0.02 signatures are not recognized by Yubico library' 'Authen::2F::Tester-0.02 signatures are not recognized by Yubico library'
); );
} }
} }

@ -20,13 +20,13 @@ SKIP: {
require Lemonldap::NG::Common::TOTP; require Lemonldap::NG::Common::TOTP;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ { ini => {
ini => {
logLevel => 'error', logLevel => 'error',
totp2fSelfRegistration => 1, totp2fSelfRegistration => 1,
totp2fActivation => 1, totp2fActivation => 1,
u2fSelfRegistration => 1, u2fSelfRegistration => 1,
u2fActivation => 1, u2fActivation => 1,
portalMainLogo => 'common/logos/test.png',
} }
} }
); );
@ -34,8 +34,7 @@ SKIP: {
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23
@ -45,8 +44,7 @@ SKIP: {
my $id = expectCookie($res); my $id = expectCookie($res);
# TOTP form # TOTP form
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -55,8 +53,7 @@ SKIP: {
); );
#expectRedirection( $res, qr#/2fregisters/totp$# ); #expectRedirection( $res, qr#/2fregisters/totp$# );
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters/totp', '/2fregisters/totp',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -64,10 +61,13 @@ SKIP: {
'Form registration' 'Form registration'
); );
ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' ); ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' );
ok( $res->[2]->[0] =~ qr%<img src="/static/common/logos/test.png"%,
'Found custom Main Logo' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
# JS query # JS query
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/getkey', IO::String->new(''), '/2fregisters/totp/getkey', IO::String->new(''),
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
length => 0, length => 0,
@ -76,7 +76,7 @@ SKIP: {
); );
eval { $res = JSON::from_json( $res->[2]->[0] ) }; eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' ) ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' ); or explain( $res->[2]->[0], 'JSON content' );
my ( $key, $token ); my ( $key, $token );
ok( $key = $res->{secret}, 'Found secret' ); ok( $key = $res->{secret}, 'Found secret' );
ok( $token = $res->{token}, 'Found token' ); ok( $token = $res->{token}, 'Found token' );
@ -88,8 +88,7 @@ SKIP: {
'Code' ); 'Code' );
ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' ); ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' );
my $s = "code=$code&token=$token"; my $s = "code=$code&token=$token";
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/verify', '/2fregisters/totp/verify',
IO::String->new($s), IO::String->new($s),
length => length($s), length => length($s),
@ -99,13 +98,12 @@ SKIP: {
); );
eval { $res = JSON::from_json( $res->[2]->[0] ) }; eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' ) ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' ); or explain( $res->[2]->[0], 'JSON content' );
ok( $res->{result} == 1, 'Key is registered' ); ok( $res->{result} == 1, 'Key is registered' );
# Try to sign-in # Try to sign-in
$client->logout($id); $client->logout($id);
ok( ok( $res = $client->_post(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -113,13 +111,12 @@ SKIP: {
), ),
'Auth query' 'Auth query'
); );
my ( $host, $url, $query ) = my ( $host, $url, $query )
expectForm( $res, undef, '/totp2fcheck', 'token' ); = expectForm( $res, undef, '/totp2fcheck', 'token' );
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ), ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
'Code' ); 'Code' );
$query =~ s/code=/code=$code/; $query =~ s/code=/code=$code/;
ok( ok( $res = $client->_post(
$res = $client->_post(
'/totp2fcheck', IO::String->new($query), '/totp2fcheck', IO::String->new($query),
length => length($query), length => length($query),
), ),
@ -127,8 +124,7 @@ SKIP: {
); );
$id = expectCookie($res); $id = expectCookie($res);
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -140,21 +136,20 @@ SKIP: {
ok( $res->[2]->[0] =~ qr%<img src="/static/bootstrap/totp.png".*?/>%, ok( $res->[2]->[0] =~ qr%<img src="/static/bootstrap/totp.png".*?/>%,
'Found totp.png' ) 'Found totp.png' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ qr%<img src="/static/bootstrap/u2f.png".*?/>%, ok( $res->[2]->[0] =~ qr%<img src="/static/bootstrap/u2f.png".*?/>%,
'Found u2f.png' ) 'Found u2f.png' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/u".*?>%, ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/u".*?>%,
'Found 2fregisters/u link' ) 'Found 2fregisters/u link' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/totp".*?>%, ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/totp".*?>%,
'Found 2fregisters/totp link' ) 'Found 2fregisters/totp link' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ qr%TOTP.*epoch.*(\d{10})%m, "TOTP epoch $1 found" ) ok( $res->[2]->[0] =~ qr%TOTP.*epoch.*(\d{10})%m, "TOTP epoch $1 found" )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
ok( ok( $res = $client->_post(
$res = $client->_post(
'/2fregisters/totp/delete', '/2fregisters/totp/delete',
IO::String->new("epoch=$1"), IO::String->new("epoch=$1"),
length => 16, length => 16,
@ -163,8 +158,7 @@ SKIP: {
'Delete TOTP query' 'Delete TOTP query'
); );
ok( ok( $res = $client->_get(
$res = $client->_get(
'/2fregisters', '/2fregisters',
cookie => "lemonldap=$id", cookie => "lemonldap=$id",
accept => 'text/html', accept => 'text/html',
@ -176,13 +170,12 @@ SKIP: {
'Found 2f registration js' ); 'Found 2f registration js' );
ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/u" class="nodecor">%, ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/u" class="nodecor">%,
'Found 2fregisters/u link' ) 'Found 2fregisters/u link' )
or print STDERR Dumper($res); or print STDERR Dumper($res);
ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/totp" class="nodecor">%, ok( $res->[2]->[0] =~ qr%<a href="/2fregisters/totp" class="nodecor">%,
'Found 2fregisters/totp link' ) 'Found 2fregisters/totp link' )
or print STDERR Dumper($res); or print STDERR Dumper($res);
ok( ok( $res->[2]->[0]
$res->[2]->[0] !~ !~ qr%<td class="align-middle" >TOTP</td><td class="align-middle">(\d{10})</td><td class="data-epoch">\d{10}</td>%,
qr%<td class="align-middle" >TOTP</td><td class="align-middle">(\d{10})</td><td class="data-epoch">\d{10}</td>%,
"TOTP deleted" "TOTP deleted"
) or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );

Loading…
Cancel
Save