Test 2F TTL (#1782)
This commit is contained in:
parent
bbe18393a5
commit
e3c2766809
|
@ -3524,6 +3524,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'boolOrExpr'
|
'type' => 'boolOrExpr'
|
||||||
},
|
},
|
||||||
|
'totp2fTTL' => {
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'totp2fUserCanChangeKey' => {
|
'totp2fUserCanChangeKey' => {
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
|
@ -3563,6 +3566,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'boolOrExpr'
|
'type' => 'boolOrExpr'
|
||||||
},
|
},
|
||||||
|
'u2fTTL' => {
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'u2fUserCanRemoveKey' => {
|
'u2fUserCanRemoveKey' => {
|
||||||
'default' => 1,
|
'default' => 1,
|
||||||
'type' => 'bool'
|
'type' => 'bool'
|
||||||
|
@ -3764,6 +3770,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'type' => 'boolOrExpr'
|
'type' => 'boolOrExpr'
|
||||||
},
|
},
|
||||||
|
'yubikey2fTTL' => {
|
||||||
|
'type' => 'int'
|
||||||
|
},
|
||||||
'yubikey2fUrl' => {
|
'yubikey2fUrl' => {
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
|
|
@ -1369,7 +1369,10 @@ sub attributes {
|
||||||
default => 1,
|
default => 1,
|
||||||
documentation => 'Authorize users to remove existing U2F key',
|
documentation => 'Authorize users to remove existing U2F key',
|
||||||
},
|
},
|
||||||
|
u2fTTL => {
|
||||||
|
type => 'int',
|
||||||
|
documentation => 'U2F device time to live',
|
||||||
|
},
|
||||||
# TOTP second factor
|
# TOTP second factor
|
||||||
totp2fActivation => {
|
totp2fActivation => {
|
||||||
type => 'boolOrExpr',
|
type => 'boolOrExpr',
|
||||||
|
@ -1421,6 +1424,10 @@ sub attributes {
|
||||||
default => 1,
|
default => 1,
|
||||||
documentation => 'Authorize users to remove existing TOTP secret',
|
documentation => 'Authorize users to remove existing TOTP secret',
|
||||||
},
|
},
|
||||||
|
totp2fTTL => {
|
||||||
|
type => 'int',
|
||||||
|
documentation => 'TOTP device time to live ',
|
||||||
|
},
|
||||||
|
|
||||||
# UTOTP 2F
|
# UTOTP 2F
|
||||||
utotp2fActivation => {
|
utotp2fActivation => {
|
||||||
|
@ -1578,6 +1585,10 @@ sub attributes {
|
||||||
default => 1,
|
default => 1,
|
||||||
documentation => 'Authorize users to remove existing Yubikey',
|
documentation => 'Authorize users to remove existing Yubikey',
|
||||||
},
|
},
|
||||||
|
yubikey2fTTL => {
|
||||||
|
type => 'int',
|
||||||
|
documentation => 'Yubikey device time to live',
|
||||||
|
},
|
||||||
|
|
||||||
# Single session
|
# Single session
|
||||||
notifyDeleted => {
|
notifyDeleted => {
|
||||||
|
|
|
@ -689,6 +689,7 @@ sub tree {
|
||||||
'totp2fDisplayExistingSecret',
|
'totp2fDisplayExistingSecret',
|
||||||
'totp2fUserCanChangeKey',
|
'totp2fUserCanChangeKey',
|
||||||
'totp2fUserCanRemoveKey',
|
'totp2fUserCanRemoveKey',
|
||||||
|
'totp2fTTL',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -698,6 +699,7 @@ sub tree {
|
||||||
nodes => [
|
nodes => [
|
||||||
'u2fActivation', 'u2fSelfRegistration',
|
'u2fActivation', 'u2fSelfRegistration',
|
||||||
'u2fAuthnLevel', 'u2fUserCanRemoveKey',
|
'u2fAuthnLevel', 'u2fUserCanRemoveKey',
|
||||||
|
'u2fTTL',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -745,6 +747,7 @@ sub tree {
|
||||||
'yubikey2fUrl',
|
'yubikey2fUrl',
|
||||||
'yubikey2fPublicIDSize',
|
'yubikey2fPublicIDSize',
|
||||||
'yubikey2fUserCanRemoveKey',
|
'yubikey2fUserCanRemoveKey',
|
||||||
|
'yubikey2fTTL',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'sfRequired',
|
'sfRequired',
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -20,7 +20,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_TOKENEXPIRED
|
PE_TOKENEXPIRED
|
||||||
);
|
);
|
||||||
|
|
||||||
our $VERSION = '2.0.2';
|
our $VERSION = '2.0.5';
|
||||||
|
|
||||||
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
||||||
|
|
||||||
|
@ -126,7 +126,6 @@ sub init {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +136,6 @@ sub init {
|
||||||
# run() is called at each authentication, just after sessionInfo populated
|
# run() is called at each authentication, just after sessionInfo populated
|
||||||
sub run {
|
sub run {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
|
|
||||||
my $checkLogins = $req->param('checkLogins');
|
my $checkLogins = $req->param('checkLogins');
|
||||||
my $spoofId = $req->param('spoofId') || '';
|
my $spoofId = $req->param('spoofId') || '';
|
||||||
$self->logger->debug("2F checkLogins set") if ($checkLogins);
|
$self->logger->debug("2F checkLogins set") if ($checkLogins);
|
||||||
|
@ -145,6 +143,71 @@ sub run {
|
||||||
# Skip 2F unless a module has been registered
|
# Skip 2F unless a module has been registered
|
||||||
return PE_OK unless ( @{ $self->sfModules } );
|
return PE_OK unless ( @{ $self->sfModules } );
|
||||||
|
|
||||||
|
# Remove expired 2F devices
|
||||||
|
my $session = $req->sessionInfo;
|
||||||
|
if ( $session->{_2fDevices} ) {
|
||||||
|
$self->logger->debug("Loading 2F Devices ...");
|
||||||
|
|
||||||
|
# Read existing 2FDevices
|
||||||
|
my $_2fDevices =
|
||||||
|
eval { from_json( $session->{_2fDevices}, { allow_nonref => 1 } ); };
|
||||||
|
if ($@) {
|
||||||
|
$self->logger->error("Bad encoding in _2fDevices: $@");
|
||||||
|
return PE_ERROR;
|
||||||
|
}
|
||||||
|
$self->logger->debug(" -> 2F Device(s) found");
|
||||||
|
|
||||||
|
my $u2fTTL = $self->conf->{u2fTTL}
|
||||||
|
&& $self->conf->{u2fTTL} > 0 ? $self->conf->{u2fTTL} : 0;
|
||||||
|
my $totpTTL = $self->conf->{totp2fTTL}
|
||||||
|
&& $self->conf->{totp2fTTL} > 0 ? $self->conf->{totp2fTTL} : 0;
|
||||||
|
my $ubkTTL = $self->conf->{yubikey2fTTL}
|
||||||
|
&& $self->conf->{yubikey2fTTL} > 0 ? $self->conf->{yubikey2fTTL} : 0;
|
||||||
|
|
||||||
|
if ( $u2fTTL || $totpTTL || $ubkTTL ) {
|
||||||
|
my $now = time();
|
||||||
|
my $removed = 0;
|
||||||
|
$self->logger->debug("Looking for expired 2F device(s)...");
|
||||||
|
foreach (@$_2fDevices) {
|
||||||
|
if ( $_->{type} eq 'U2F' ) {
|
||||||
|
if ( $u2fTTL && $now - $_->{epoch} > $u2fTTL ) {
|
||||||
|
$self->logger->debug(
|
||||||
|
"Remove U2F -> $_->{name} / $_->{epoch}");
|
||||||
|
$self->userLogger->info("Remove expired U2F");
|
||||||
|
$_->{type} = 'EXPIRED';
|
||||||
|
$removed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $_->{type} eq 'UBK' ) {
|
||||||
|
if ( $ubkTTL && $now - $_->{epoch} > $ubkTTL ) {
|
||||||
|
$self->logger->debug(
|
||||||
|
"Remove Yubikey -> $_->{name} / $_->{epoch}");
|
||||||
|
$self->userLogger->info("Remove expired Yubiked");
|
||||||
|
$_->{type} = 'EXPIRED';
|
||||||
|
$removed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $_->{type} eq 'TOTP' ) {
|
||||||
|
if ( $totpTTL && $now - $_->{epoch} > $totpTTL ) {
|
||||||
|
$self->logger->debug(
|
||||||
|
"Remove TOTP -> $_->{name} / $_->{epoch}");
|
||||||
|
$self->userLogger->info("Remove expired TOTP");
|
||||||
|
$_->{type} = 'EXPIRED';
|
||||||
|
$removed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($removed) {
|
||||||
|
$self->logger->debug(
|
||||||
|
"Found EXPIRED 2F device(s) => Update persistent session");
|
||||||
|
@$_2fDevices =
|
||||||
|
map { $_->{type} =~ /\bEXPIRED\b/ ? () : $_ } @$_2fDevices;
|
||||||
|
$self->p->updatePersistentSession( $req,
|
||||||
|
{ _2fDevices => to_json($_2fDevices) } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Search for authorized modules for this user
|
# Search for authorized modules for this user
|
||||||
my @am;
|
my @am;
|
||||||
foreach my $m ( @{ $self->sfModules } ) {
|
foreach my $m ( @{ $self->sfModules } ) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user