2F engine works with 1 2F enabled (#1148)
This commit is contained in:
parent
e9e820ecd1
commit
06cb8a6e11
|
@ -25,7 +25,7 @@ staticPrefix = /static
|
|||
languages = fr, en, vi, it, ar
|
||||
templateDir = __pwd__/lemonldap-ng-portal/site/templates
|
||||
;totp2fActivation = 1
|
||||
;totpSelfRegistration = 1
|
||||
;totp2fSelfRegistration = 1
|
||||
|
||||
[handler]
|
||||
|
||||
|
|
|
@ -3010,7 +3010,8 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'type' => 'keyTextContainer'
|
||||
},
|
||||
'sfEngine' => {
|
||||
'default' => '::2F::Engine::Default'
|
||||
'default' => '::2F::Engine::Default',
|
||||
'type' => 'text'
|
||||
},
|
||||
'singleIP' => {
|
||||
'default' => 0,
|
||||
|
@ -3175,7 +3176,7 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
|||
'default' => 1,
|
||||
'type' => 'int'
|
||||
},
|
||||
'totpSelfRegistration' => {
|
||||
'totp2fSelfRegistration' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
},
|
||||
|
|
|
@ -1036,7 +1036,7 @@ sub attributes {
|
|||
default => 0,
|
||||
documentation => 'TOTP activation',
|
||||
},
|
||||
totpSelfRegistration => {
|
||||
totp2fSelfRegistration => {
|
||||
type => 'bool',
|
||||
default => 0,
|
||||
documentation => 'TOTP self registration activation',
|
||||
|
|
|
@ -663,7 +663,7 @@ sub tree {
|
|||
help => 'totp2f.html',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'totp2fActivation', 'totpSelfRegistration',
|
||||
'totp2fActivation', 'totp2fSelfRegistration',
|
||||
'totp2fAuthnLevel', 'totp2fIssuer',
|
||||
'totp2fInterval', 'totp2fRange',
|
||||
'totp2fDigits',
|
||||
|
|
|
@ -716,7 +716,7 @@
|
|||
"totp2fInterval":"Interval",
|
||||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totpSelfRegistration":"Self registration",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"trustedDomains":"النطاقات الموثوق بها",
|
||||
"trustedProxies":"عناوين الآي بي البروكسي الموثوق بها",
|
||||
"twitterAppName":"اسم التطبيق",
|
||||
|
|
|
@ -716,7 +716,7 @@
|
|||
"totp2fInterval":"Interval",
|
||||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totpSelfRegistration":"Self registration",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"trustedDomains":"Trusted domains",
|
||||
"trustedProxies":"Trusted proxies IP",
|
||||
"twitterAppName":"Application name",
|
||||
|
|
|
@ -716,7 +716,7 @@
|
|||
"totp2fInterval":"Intervalle",
|
||||
"totp2fIssuer":"Nom du fournisseur TOTP",
|
||||
"totp2fRange":"Nombre d'intervalles à tester",
|
||||
"totpSelfRegistration":"Auto-enregistrement",
|
||||
"totp2fSelfRegistration":"Auto-enregistrement",
|
||||
"trustedDomains":"Domaines approuvés",
|
||||
"trustedProxies":"IP des proxys de confiance",
|
||||
"twitterAppName":"Nom de l'application",
|
||||
|
|
|
@ -716,7 +716,7 @@
|
|||
"totp2fInterval":"Interval",
|
||||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totpSelfRegistration":"Self registration",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"trustedDomains":"Domini attendibili",
|
||||
"trustedProxies":"IP proxy attendibili",
|
||||
"twitterAppName":"Nome dell'applicazione",
|
||||
|
|
|
@ -716,7 +716,7 @@
|
|||
"totp2fInterval":"Interval",
|
||||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totpSelfRegistration":"Self registration",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"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
|
@ -16,6 +16,16 @@ has sfModules => ( is => 'rw', default => sub { [] } );
|
|||
|
||||
has sfRModules => ( is => 'rw', default => sub { [] } );
|
||||
|
||||
has ott => (
|
||||
is => 'rw',
|
||||
default => sub {
|
||||
my $ott =
|
||||
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
|
||||
$ott->timeout( $_[0]->{conf}->{formTimeout} );
|
||||
return $ott;
|
||||
}
|
||||
);
|
||||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
|
||||
|
@ -26,7 +36,7 @@ sub init {
|
|||
# Load 2F modules
|
||||
for my $i ( 0 .. 1 ) {
|
||||
foreach (
|
||||
split /,\s+/,
|
||||
split /,\s*/,
|
||||
$self->conf->{ $i ? 'available2FSelfRegistration' : 'available2F' }
|
||||
)
|
||||
{
|
||||
|
@ -34,10 +44,11 @@ sub init {
|
|||
$prefix =~ s/2f$//i;
|
||||
|
||||
# Activation parameter
|
||||
my $ap = $prefix. ( $i ? '2fSelfRegistration' : '2fActivation' );
|
||||
my $ap = $prefix . ( $i ? '2fSelfRegistration' : '2fActivation' );
|
||||
$self->logger->debug("Checking $ap");
|
||||
|
||||
# Unless $rule, skip loading
|
||||
if ($self->conf->{$ap}) {
|
||||
if ( $self->conf->{$ap} ) {
|
||||
$self->logger->debug("Trying to load $_ 2F");
|
||||
my $m =
|
||||
$self->p->loadPlugin( $i ? "::2F::Register::$_" : "::2F::$_" )
|
||||
|
@ -59,6 +70,9 @@ sub init {
|
|||
push @{ $self->{ $i ? 'sfRModules' : 'sfModules' } },
|
||||
{ m => $m, r => $rule };
|
||||
}
|
||||
else {
|
||||
$self->logger->debug(' -> not enabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,40 +83,44 @@ sub init {
|
|||
|
||||
# run is called at each authentication, just after sesionInfo populate
|
||||
sub run {
|
||||
my($self,$req)=@_;
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
# Skip 2F unless a module has been registered
|
||||
return PE_OK unless(@{$self->sfModules});
|
||||
return PE_OK unless ( @{ $self->sfModules } );
|
||||
|
||||
# Search for authorizated modules for this user
|
||||
my @am;
|
||||
foreach my $m (@{$self->sfModules}) {
|
||||
$self->logger->debug('Looking if '.$m->{m}->prefix.'2F is available');
|
||||
if($m->{r}->( $req, $req->sessionInfo ) ) {
|
||||
foreach my $m ( @{ $self->sfModules } ) {
|
||||
$self->logger->debug(
|
||||
'Looking if ' . $m->{m}->prefix . '2F is available' );
|
||||
if ( $m->{r}->( $req, $req->sessionInfo ) ) {
|
||||
$self->logger->debug(' -> OK');
|
||||
push @am,$m->{m};
|
||||
push @am, $m->{m};
|
||||
}
|
||||
}
|
||||
|
||||
# If no 2F modules are authorizated, skipping 2F
|
||||
# Note that a rule may forbid access after (GrantSession plugin)
|
||||
return PE_OK unless(@am);
|
||||
return PE_OK unless (@am);
|
||||
|
||||
# If only one 2F is authorizated, display it
|
||||
$self->userLogger->info( 'Second factor required for '
|
||||
. $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
||||
|
||||
# Store user data in a token
|
||||
$req->sessionInfo->{_2fRealSession} = $req->id;
|
||||
$req->sessionInfo->{_2fUrldc} = $req->urldc;
|
||||
my $token = $self->ott->createToken( $req->sessionInfo );
|
||||
unless($#am) {
|
||||
my $res = $am[0]->run($req, $token);
|
||||
|
||||
# If only one 2F is authorizated, display it
|
||||
unless ($#am) {
|
||||
my $res = $am[0]->run( $req, $token );
|
||||
delete $req->{authResult} if ($res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
# More than 1 2F has been found, display choice
|
||||
# TODO
|
||||
return PE_OK
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -10,6 +10,8 @@ extends 'Lemonldap::NG::Portal::Main::Plugin', 'Lemonldap::NG::Common::TOTP';
|
|||
|
||||
# INITIALIZATION
|
||||
|
||||
has prefix => ( is => 'rw', default => 'totp' );
|
||||
|
||||
has ott => (
|
||||
is => 'rw',
|
||||
lazy => 1,
|
||||
|
|
|
@ -10,6 +10,8 @@ extends 'Lemonldap::NG::Portal::Lib::U2F';
|
|||
|
||||
# INITIALIZATION
|
||||
|
||||
has prefix => ( is => 'rw', default => 'u' );
|
||||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
return 0 unless $self->SUPER::init;
|
||||
|
|
|
@ -24,7 +24,7 @@ sub init {
|
|||
|
||||
# If self registration is enabled and "activation" is simply set to
|
||||
# "enabled", replace the rule to detect if user has register its key
|
||||
if ( $self->conf->{totpSelfRegistration}
|
||||
if ( $self->conf->{totp2fSelfRegistration}
|
||||
and $self->conf->{totp2fActivation} eq '1' )
|
||||
{
|
||||
$self->conf->{totp2fActivation} = '$_totp2fSecret';
|
||||
|
|
|
@ -27,6 +27,7 @@ has menu => ( is => 'rw', default => sub { {} } );
|
|||
has _authentication => ( is => 'rw' );
|
||||
has _userDB => ( is => 'rw' );
|
||||
has _passwordDB => ( is => 'rw' );
|
||||
has _sfEngine => ( is => 'rw' );
|
||||
|
||||
has loadedModules => ( is => 'rw' );
|
||||
|
||||
|
@ -220,7 +221,8 @@ sub reloadConf {
|
|||
# Load second-factor engine
|
||||
$self->conf->{'sfEngine'} ||= '::2F::Engines::Default';
|
||||
return $self->fail
|
||||
unless $self->{sfEngine} = $self->loadPlugin( $self->conf->{'sfEngine'} );
|
||||
unless $self->{_sfEngine} =
|
||||
$self->loadPlugin( $self->conf->{'sfEngine'} );
|
||||
|
||||
# Initialize trusted domain regexp
|
||||
if ( $self->conf->{trustedDomains}
|
||||
|
|
|
@ -16,11 +16,6 @@ our @pList = (
|
|||
portalDisplayResetPassword => '::Plugins::MailReset',
|
||||
portalStatus => '::Plugins::Status',
|
||||
cda => '::Plugins::CDA',
|
||||
ext2fActivation => '::2F::External2F',
|
||||
totp2fActivation => '::2F::TOTP',
|
||||
totpSelfRegistration => '::2F::Register::TOTP',
|
||||
u2fActivation => '::2F::U2F',
|
||||
u2fSelfRegistration => '::2F::Register::U2F',
|
||||
notification => '::Plugins::Notifications',
|
||||
portalCheckLogins => '::Plugins::History',
|
||||
stayConnected => '::Plugins::StayConnected',
|
||||
|
|
|
@ -477,4 +477,9 @@ sub buildCookie {
|
|||
PE_OK;
|
||||
}
|
||||
|
||||
sub secondFactor {
|
||||
my ( $self, $req ) = @_;
|
||||
return $self->_sfEngine->run($req);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -20,7 +20,7 @@ sub authProcess { qw(extractFormInfo getUser authenticate) }
|
|||
|
||||
sub sessionDatas {
|
||||
qw(setAuthSessionInfo setSessionInfo setMacros setGroups setPersistentSessionInfo
|
||||
setLocalGroups store buildCookie);
|
||||
setLocalGroups store buildCookie secondFactor);
|
||||
}
|
||||
|
||||
# RESPONSE HANDLER
|
||||
|
|
|
@ -12,10 +12,6 @@ our $VERSION = '2.0.0';
|
|||
|
||||
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
||||
|
||||
# INTERFACE
|
||||
|
||||
sub afterDatas { '_run' }
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
has ott => (
|
||||
|
@ -28,22 +24,12 @@ has ott => (
|
|||
}
|
||||
);
|
||||
|
||||
has rule => ( is => 'rw' );
|
||||
|
||||
has prefix => ( is => 'rw' );
|
||||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
$self->addUnauthRoute( $self->prefix . '2fcheck' => '_verify', ['POST'] );
|
||||
$self->addUnauthRoute( $self->prefix . '2fcheck' => '_redirect', ['GET'] );
|
||||
my $rule = $self->conf->{ $self->prefix . '2fActivation' };
|
||||
$rule = $self->p->HANDLER->substitute($rule);
|
||||
unless ( $rule = $self->p->HANDLER->buildSub($rule) ) {
|
||||
$self->error( 'External 2F rule error: '
|
||||
. $self->p->HANDLER->tsv->{jail}->error );
|
||||
return 0;
|
||||
}
|
||||
$self->rule($rule);
|
||||
1;
|
||||
}
|
||||
|
||||
|
@ -55,23 +41,6 @@ sub _redirect {
|
|||
];
|
||||
}
|
||||
|
||||
sub _run {
|
||||
my ( $self, $req ) = @_;
|
||||
return PE_OK unless ( $self->rule->( $req, $req->sessionInfo ) );
|
||||
$self->userLogger->info( 'Second factor required ('
|
||||
. $self->prefix
|
||||
. ') for '
|
||||
. $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
||||
$req->sessionInfo->{_2fRealSession} = $req->id;
|
||||
$req->sessionInfo->{_2fUrldc} = $req->urldc;
|
||||
my $token = $self->ott->createToken( $req->sessionInfo );
|
||||
$req->id(0);
|
||||
$self->p->rebuildCookies($req);
|
||||
my $res = $self->run( $req, $token );
|
||||
delete $req->{authResult} if ($res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub _verify {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ SKIP: {
|
|||
my $client = LLNG::Manager::Test->new(
|
||||
{
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
totpSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
logLevel => 'error',
|
||||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user