From 5e72df3f069cd28fdf87e01ca6649e33e1ffbcee Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 30 Aug 2022 11:47:13 +0200 Subject: [PATCH 1/3] Do not display login form after 2FA token timeout (#2791) --- .../lib/Lemonldap/NG/Portal/2F/Engines/Default.pm | 1 + .../lib/Lemonldap/NG/Portal/Main/SecondFactor.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm index a5123f49b..d516ca46c 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm @@ -433,6 +433,7 @@ sub _choice { my $session; unless ( $session = $self->ott->getToken($token) ) { $self->userLogger->info('Token expired'); + $req->noLoginDisplay(1); return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] ); } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm index 8328db79c..d56200f5e 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm @@ -101,7 +101,7 @@ sub _verify { my $session; unless ( $session = $self->ott->getToken($token) ) { $self->userLogger->info('Token expired'); - $self->setSecurity($req); + $req->noLoginDisplay(1); return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] ); } From 318e08ccc7e23fc057d8281367269e5c491d1182 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Fri, 2 Sep 2022 10:56:38 +0200 Subject: [PATCH 2/3] Make sure tokens handled by 2F modules are temporary sessions (#2791) --- .../lib/Lemonldap/NG/Portal/2F/Engines/Default.pm | 6 ++++++ .../lib/Lemonldap/NG/Portal/Main/SecondFactor.pm | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm index d516ca46c..de5b8673a 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm @@ -437,6 +437,12 @@ sub _choice { return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] ); } + unless ( $session->{_2fRealSession} ) { + $self->logger->error("Invalid 2FA session token"); + $req->noLoginDisplay(1); + return $self->p->do( $req, [ sub { PE_ERROR } ] ); + } + $req->sessionInfo($session); # New token diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm index d56200f5e..cb8da3519 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm @@ -5,6 +5,7 @@ use Mouse; use Lemonldap::NG::Portal::Main::Constants qw( PE_SENDRESPONSE PE_OK + PE_ERROR PE_NOTOKEN PE_TOKENEXPIRED PE_BADCREDENTIALS @@ -104,6 +105,11 @@ sub _verify { $req->noLoginDisplay(1); return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] ); } + unless ( $session->{_2fRealSession} ) { + $self->logger->error("Invalid 2FA session token"); + $req->noLoginDisplay(1); + return $self->p->do( $req, [ sub { PE_ERROR } ] ); + } # Launch second factor verification my $res = $self->verify( $req, $session ); From d6efecb6cc0256645d11b71de47127f25fb4c6b8 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 30 Aug 2022 11:47:42 +0200 Subject: [PATCH 3/3] Fix unit tests for #2791 --- .../t/70-2F-TOTP-8-with-global-storage.t | 9 ++++++--- lemonldap-ng-portal/t/70-2F-TOTP-encryption.t | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lemonldap-ng-portal/t/70-2F-TOTP-8-with-global-storage.t b/lemonldap-ng-portal/t/70-2F-TOTP-8-with-global-storage.t index fe4358272..a0ad0dc7e 100644 --- a/lemonldap-ng-portal/t/70-2F-TOTP-8-with-global-storage.t +++ b/lemonldap-ng-portal/t/70-2F-TOTP-8-with-global-storage.t @@ -3,7 +3,7 @@ use strict; use IO::String; require 't/test-lib.pm'; -my $maintests = 27; +my $maintests = 28; SKIP: { eval { require Convert::Base32 }; @@ -186,10 +186,13 @@ SKIP: { ), 'Post code' ); - ( $host, $url, $query ) = - expectForm( $res, '#', undef, 'user', 'password', 'token' ); ok( $res->[2]->[0] =~ /<\/span>/, 'Token expired' ) or print STDERR Dumper( $res->[2]->[0] ); + unlike( + $res->[2]->[0], + qr/input id="userfield"/, + 'Login form is not displayed' + ); # Try to sign-in ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', ); diff --git a/lemonldap-ng-portal/t/70-2F-TOTP-encryption.t b/lemonldap-ng-portal/t/70-2F-TOTP-encryption.t index 7ba1e65a2..8e61ab1ed 100644 --- a/lemonldap-ng-portal/t/70-2F-TOTP-encryption.t +++ b/lemonldap-ng-portal/t/70-2F-TOTP-encryption.t @@ -4,7 +4,7 @@ use IO::String; use JSON qw/from_json to_json/; require 't/test-lib.pm'; -my $maintests = 30; +my $maintests = 31; SKIP: { eval { require Convert::Base32 }; @@ -187,10 +187,14 @@ SKIP: { ), 'Post code' ); - ( $host, $url, $query ) = - expectForm( $res, '#', undef, 'user', 'password', 'token' ); + ok( $res->[2]->[0] =~ /<\/span>/, 'Token expired' ) or print STDERR Dumper( $res->[2]->[0] ); + unlike( + $res->[2]->[0], + qr/input id="userfield"/, + 'Login form is not displayed' + ); # Try to sign-in ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );