Fix logins history update - Failed and Granted Access with and without SFA (#1501)

This commit is contained in:
Christophe Maudoux 2018-09-12 23:14:35 +02:00
parent 1791747281
commit 0ed8dbdde2
5 changed files with 218 additions and 211 deletions

View File

@ -13,11 +13,11 @@ use strict;
use Mouse; use Mouse;
use JSON qw(from_json to_json); use JSON qw(from_json to_json);
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_ERROR PE_ERROR
PE_NOTOKEN PE_NOTOKEN
PE_OK PE_OK
PE_SENDRESPONSE PE_SENDRESPONSE
PE_TOKENEXPIRED PE_TOKENEXPIRED
); );
our $VERSION = '2.0.0'; our $VERSION = '2.0.0';
@ -35,8 +35,8 @@ has sfReq => ( is => 'rw' );
has ott => ( has ott => (
is => 'rw', is => 'rw',
default => sub { default => sub {
my $ott = my $ott = $_[0]->{p}
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken'); ->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
$ott->timeout( $_[0]->{conf}->{formTimeout} ); $ott->timeout( $_[0]->{conf}->{formTimeout} );
return $ott; return $ott;
} }
@ -49,8 +49,10 @@ sub init {
for my $i ( 0 .. 1 ) { for my $i ( 0 .. 1 ) {
foreach ( foreach (
split /,\s*/, split /,\s*/,
$self->conf->{ $i ? 'available2FSelfRegistration' : 'available2F' } $self->conf->{ $i
) ? 'available2FSelfRegistration'
: 'available2F' }
)
{ {
my $prefix = lc($_); my $prefix = lc($_);
$prefix =~ s/2f$//i; $prefix =~ s/2f$//i;
@ -62,9 +64,10 @@ sub init {
# Unless $rule, skip loading # Unless $rule, skip loading
if ( $self->conf->{$ap} ) { if ( $self->conf->{$ap} ) {
$self->logger->debug("Trying to load $_ 2F"); $self->logger->debug("Trying to load $_ 2F");
my $m = my $m
$self->p->loadPlugin( $i ? "::2F::Register::$_" : "::2F::$_" ) = $self->p->loadPlugin(
or return 0; $i ? "::2F::Register::$_" : "::2F::$_" )
or return 0;
# Rule and prefix may be modified by 2F module, reread them # Rule and prefix may be modified by 2F module, reread them
my $rule = $self->conf->{$ap}; my $rule = $self->conf->{$ap};
@ -74,13 +77,13 @@ sub init {
$rule = $self->p->HANDLER->substitute($rule); $rule = $self->p->HANDLER->substitute($rule);
unless ( $rule = $self->p->HANDLER->buildSub($rule) ) { unless ( $rule = $self->p->HANDLER->buildSub($rule) ) {
$self->error( 'External 2F rule error: ' $self->error( 'External 2F rule error: '
. $self->p->HANDLER->tsv->{jail}->error ); . $self->p->HANDLER->tsv->{jail}->error );
return 0; return 0;
} }
# Store module # Store module
push @{ $self->{ $i ? 'sfRModules' : 'sfModules' } }, push @{ $self->{ $i ? 'sfRModules' : 'sfModules' } },
{ p => $prefix, m => $m, r => $rule }; { p => $prefix, m => $m, r => $rule };
} }
else { else {
$self->logger->debug(' -> not enabled'); $self->logger->debug(' -> not enabled');
@ -94,10 +97,10 @@ sub init {
$self->p->HANDLER->substitute( $self->conf->{sfRequired} ) $self->p->HANDLER->substitute( $self->conf->{sfRequired} )
) )
) )
) )
{ {
$self->error( 'Error in sfRequired rule' $self->error( 'Error in sfRequired rule'
. $self->p->HANDLER->tsv->{jail}->error ); . $self->p->HANDLER->tsv->{jail}->error );
return 0; return 0;
} }
@ -158,14 +161,14 @@ sub run {
if ( $self->sfReq->( $req, $req->sessionInfo ) ) { if ( $self->sfReq->( $req, $req->sessionInfo ) ) {
$self->logger->debug("2F is required..."); $self->logger->debug("2F is required...");
$self->logger->debug(" -> Register 2F"); $self->logger->debug(" -> Register 2F");
$req->pdata->{sfRegToken} = $req->pdata->{sfRegToken}
$self->ott->createToken( $req->sessionInfo ); = $self->ott->createToken( $req->sessionInfo );
$self->logger->debug("Just one 2F is enabled"); $self->logger->debug("Just one 2F is enabled");
$self->logger->debug(" -> Redirect to /2fregisters/"); $self->logger->debug(" -> Redirect to /2fregisters/");
$req->response( $req->response(
[ [ 302,
302, [ Location => $self->conf->{portal} . '/2fregisters/' ],
[ Location => $self->conf->{portal} . '/2fregisters/' ], [] []
] ]
); );
return PE_SENDRESPONSE; return PE_SENDRESPONSE;
@ -176,11 +179,12 @@ sub run {
} }
$self->userLogger->info( 'Second factor required for ' $self->userLogger->info( 'Second factor required for '
. $req->sessionInfo->{ $self->conf->{whatToTrace} } ); . $req->sessionInfo->{ $self->conf->{whatToTrace} } );
# Store user data in a token # Store user data in a token
$req->sessionInfo->{_2fRealSession} = $req->id; $req->sessionInfo->{_2fRealSession} = $req->id;
$req->sessionInfo->{_2fUrldc} = $req->urldc; $req->sessionInfo->{_2fUrldc} = $req->urldc;
$req->sessionInfo->{_2fUtime} = $req->{sessionInfo}->{_utime};
my $token = $self->ott->createToken( $req->sessionInfo ); my $token = $self->ott->createToken( $req->sessionInfo );
delete $req->{authResult}; delete $req->{authResult};
@ -197,9 +201,10 @@ sub run {
$req, $req,
'2fchoice', '2fchoice',
params => { params => {
SKIN => $self->conf->{portalSkin}, SKIN => $self->conf->{portalSkin},
TOKEN => $token, TOKEN => $token,
MODULES => [ map { { CODE => $_->prefix, LOGO => $_->logo } } @am ], MODULES =>
[ map { { CODE => $_->prefix, LOGO => $_->logo } } @am ],
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins
} }
); );
@ -225,15 +230,16 @@ sub _choice {
# Restore session # Restore session
unless ( $token = $req->param('token') ) { unless ( $token = $req->param('token') ) {
$self->userLogger->error( $self->prefix . ' 2F access without token' ); $self->userLogger->error(
$self->prefix . ' 2F access without token' );
$req->mustRedirect(1); $req->mustRedirect(1);
return $self->p->do( $req, [ sub { PE_NOTOKEN } ] ); return $self->p->do( $req, [ sub {PE_NOTOKEN} ] );
} }
my $session; my $session;
unless ( $session = $self->ott->getToken($token) ) { unless ( $session = $self->ott->getToken($token) ) {
$self->userLogger->info('Token expired'); $self->userLogger->info('Token expired');
return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] ); return $self->p->do( $req, [ sub {PE_TOKENEXPIRED} ] );
} }
$req->sessionInfo($session); $req->sessionInfo($session);
@ -248,8 +254,7 @@ sub _choice {
$req->authResult($res); $req->authResult($res);
return $self->p->do( return $self->p->do(
$req, $req,
[ [ sub {$res}, 'controlUrl',
sub { $res }, 'controlUrl',
'buildCookie', @{ $self->p->endAuth }, 'buildCookie', @{ $self->p->endAuth },
] ]
); );
@ -264,7 +269,8 @@ sub _redirect {
my $arg = $req->env->{QUERY_STRING}; my $arg = $req->env->{QUERY_STRING};
$self->logger->debug('Call sfEngine _redirect method'); $self->logger->debug('Call sfEngine _redirect method');
return [ return [
302, [ Location => $self->conf->{portal} . ( $arg ? "?$arg" : '' ) ], [] 302, [ Location => $self->conf->{portal} . ( $arg ? "?$arg" : '' ) ],
[]
]; ];
} }
@ -294,25 +300,26 @@ sub _displayRegister {
'Looking if ' . $m->{m}->prefix . '2F register is available' ); 'Looking if ' . $m->{m}->prefix . '2F register is available' );
if ( $m->{r}->( $req, $req->userData ) ) { if ( $m->{r}->( $req, $req->userData ) ) {
push @am, push @am,
{ {
CODE => $m->{m}->prefix, CODE => $m->{m}->prefix,
URL => '/2fregisters/' . $m->{m}->prefix, URL => '/2fregisters/' . $m->{m}->prefix,
LOGO => $m->{m}->logo, LOGO => $m->{m}->logo,
}; };
} }
} }
if ( @am == 1 if ( @am == 1
and not( $req->userData->{_2fDevices} or $req->data->{sfRegRequired} ) ) and
not( $req->userData->{_2fDevices} or $req->data->{sfRegRequired} ) )
{ {
return [ 302, [ Location => $self->conf->{portal} . $am[0]->{URL} ], return [ 302, [ Location => $self->conf->{portal} . $am[0]->{URL} ],
[] ]; [] ];
} }
my $_2fDevices = my $_2fDevices = $req->userData->{_2fDevices}
$req->userData->{_2fDevices} ? eval {
? eval { from_json( $req->userData->{_2fDevices}, from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } );
{ allow_nonref => 1 } ); } }
: undef; : undef;
unless ($_2fDevices) { unless ($_2fDevices) {
$self->logger->debug("No 2F Device found"); $self->logger->debug("No 2F Device found");
@ -358,11 +365,11 @@ sub register {
$self->logger->debug(' -> OK'); $self->logger->debug(' -> OK');
my $name = $m->{m}->prefix; my $name = $m->{m}->prefix;
push @am, push @am,
{ {
name => $name, name => $name,
logo => $m->{m}->logo, logo => $m->{m}->logo,
url => "/2fregisters/$name" url => "/2fregisters/$name"
}; };
} }
} }
return $self->p->sendJSONresponse( $req, \@am ); return $self->p->sendJSONresponse( $req, \@am );
@ -371,12 +378,12 @@ sub register {
sub restoreSession { sub restoreSession {
my ( $self, $req, @path ) = @_; my ( $self, $req, @path ) = @_;
my $token = $req->pdata->{sfRegToken} my $token = $req->pdata->{sfRegToken}
or return [ 302, [ Location => $self->conf->{portal} ], [] ]; or return [ 302, [ Location => $self->conf->{portal} ], [] ];
$req->userData( $self->ott->getToken( $token, 1 ) ); $req->userData( $self->ott->getToken( $token, 1 ) );
$req->data->{sfRegRequired} = 1; $req->data->{sfRegRequired} = 1;
return $req->method eq 'POST' return $req->method eq 'POST'
? $self->register( $req, @path ) ? $self->register( $req, @path )
: $self->_displayRegister( $req, @path ); : $self->_displayRegister( $req, @path );
} }
1; 1;

View File

@ -84,9 +84,8 @@ sub init {
my ( $self, $args ) = @_; my ( $self, $args ) = @_;
$args ||= {}; $args ||= {};
$self->localConfig( $self->localConfig(
{ { %{ Lemonldap::NG::Common::Conf->new( $args->{configStorage} )
%{ Lemonldap::NG::Common::Conf->new( $args->{configStorage} ) ->getLocalConf('portal')
->getLocalConf('portal')
}, },
%$args %$args
} }
@ -110,33 +109,33 @@ sub init {
# Handle requests (other path may be declared in enabled plugins) # Handle requests (other path may be declared in enabled plugins)
$self $self
# "/" or undeclared paths # "/" or undeclared paths
->addUnauthRoute( '*' => 'login', ['GET'] ) ->addUnauthRoute( '*' => 'login', ['GET'] )
->addUnauthRoute( '*' => 'postLogin', ['POST'] ) ->addUnauthRoute( '*' => 'postLogin', ['POST'] )
->addAuthRoute( '*' => 'authenticatedRequest', ['GET'] ) ->addAuthRoute( '*' => 'authenticatedRequest', ['GET'] )
->addAuthRoute( '*' => 'postAuthenticatedRequest', ['POST'] ) ->addAuthRoute( '*' => 'postAuthenticatedRequest', ['POST'] )
# psgi.js # psgi.js
->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] ) ->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] )
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] ) ->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
# portal.css # portal.css
->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] ) ->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] )
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] ) ->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
# lmerror # lmerror
->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) ->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) ->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
# Core REST API # Core REST API
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] ) ->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
->addAuthRoute( ping => 'authenticated', ['GET'] ) ->addAuthRoute( ping => 'authenticated', ['GET'] )
# Refresh session # Refresh session
->addAuthRoute( refresh => 'refresh', ['GET'] ) ->addAuthRoute( refresh => 'refresh', ['GET'] )
# Logout # Logout
->addAuthRoute( logout => 'logout', ['GET'] ); ->addAuthRoute( logout => 'logout', ['GET'] );
# Default routes must point to routines declared above # Default routes must point to routines declared above
$self->defaultAuthRoute(''); $self->defaultAuthRoute('');
@ -151,7 +150,7 @@ sub reloadConf {
%{ $self->{conf} } = %{ $self->localConfig }; %{ $self->{conf} } = %{ $self->localConfig };
# Reinitialize arrays # Reinitialize arrays
foreach ( qw(_macros _groups), @entryPoints) { foreach ( qw(_macros _groups), @entryPoints ) {
$self->{$_} = []; $self->{$_} = [];
} }
$self->spRules( {} ); $self->spRules( {} );
@ -170,8 +169,8 @@ sub reloadConf {
$self->csp($csp); $self->csp($csp);
# Initialize templateDir # Initialize templateDir
$self->{templateDir} = $self->{templateDir}
$self->conf->{templateDir} . '/' . $self->conf->{portalSkin}; = $self->conf->{templateDir} . '/' . $self->conf->{portalSkin};
unless ( -d $self->{templateDir} ) { unless ( -d $self->{templateDir} ) {
$self->error("Template dir $self->{templateDir} doesn't exist"); $self->error("Template dir $self->{templateDir} doesn't exist");
return $self->fail; return $self->fail;
@ -191,8 +190,8 @@ sub reloadConf {
# Initialize persistent session DB # Initialize persistent session DB
unless ( $self->conf->{persistentStorage} ) { unless ( $self->conf->{persistentStorage} ) {
$self->conf->{persistentStorage} = $self->conf->{globalStorage}; $self->conf->{persistentStorage} = $self->conf->{globalStorage};
$self->conf->{persistentStorageOptions} = $self->conf->{persistentStorageOptions}
$self->conf->{globalStorageOptions}; = $self->conf->{globalStorageOptions};
} }
# Initialize cookie domain # Initialize cookie domain
@ -216,19 +215,19 @@ sub reloadConf {
return $self->fail; return $self->fail;
} }
$mod = $self->conf->{$type} $mod = $self->conf->{$type}
unless ( $self->conf->{$type} eq 'Same' ); unless ( $self->conf->{$type} eq 'Same' );
my $module = '::' . ucfirst($type) . '::' . $mod; my $module = '::' . ucfirst($type) . '::' . $mod;
$module =~ s/Authentication/Auth/; $module =~ s/Authentication/Auth/;
# Launch and initialize module # Launch and initialize module
return $self->fail return $self->fail
unless ( $self->{"_$type"} = $self->loadPlugin($module) ); unless ( $self->{"_$type"} = $self->loadPlugin($module) );
} }
# Load second-factor engine # Load second-factor engine
return $self->fail return $self->fail
unless $self->{_sfEngine} = unless $self->{_sfEngine}
$self->loadPlugin( $self->conf->{'sfEngine'} ); = $self->loadPlugin( $self->conf->{'sfEngine'} );
# Initialize trusted domain regexp # Initialize trusted domain regexp
if ( $self->conf->{trustedDomains} if ( $self->conf->{trustedDomains}
@ -251,8 +250,8 @@ sub reloadConf {
# - $domainlabel.$td # - $domainlabel.$td
# $domainlabel is build looking RFC2396 # $domainlabel is build looking RFC2396
# (see Regexp::Common::URI::RFC2396) # (see Regexp::Common::URI::RFC2396)
$_ =~ $_
s/\*\\\./(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9]\\.)*/g; =~ s/\*\\\./(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9]\\.)*/g;
$re->add("$_"); $re->add("$_");
} }
} }
@ -263,8 +262,8 @@ sub reloadConf {
$self->logger->debug("Vhost $vhost added in trusted domains"); $self->logger->debug("Vhost $vhost added in trusted domains");
$re->add( quotemeta($vhost) ); $re->add( quotemeta($vhost) );
$self->conf->{vhostOptions} ||= {}; $self->conf->{vhostOptions} ||= {};
if ( my $tmp = if ( my $tmp
$self->conf->{vhostOptions}->{$vhost}->{vhostAliases} ) = $self->conf->{vhostOptions}->{$vhost}->{vhostAliases} )
{ {
foreach my $alias ( split /\s+/, $tmp ) { foreach my $alias ( split /\s+/, $tmp ) {
$self->logger->debug( $self->logger->debug(
@ -282,22 +281,22 @@ sub reloadConf {
$self->{"_$type"} = {}; $self->{"_$type"} = {};
if ( $self->conf->{$type} ) { if ( $self->conf->{$type} ) {
for my $name ( sort keys %{ $self->conf->{$type} } ) { for my $name ( sort keys %{ $self->conf->{$type} } ) {
my $sub = my $sub = HANDLER->buildSub(
HANDLER->buildSub(
HANDLER->substitute( $self->conf->{$type}->{$name} ) ); HANDLER->substitute( $self->conf->{$type}->{$name} ) );
if ($sub) { if ($sub) {
$self->{"_$type"}->{$name} = $sub; $self->{"_$type"}->{$name} = $sub;
} }
else { else {
$self->logger->error( "$type $name returns an error: " $self->logger->error( "$type $name returns an error: "
. HANDLER->tsv->{jail}->error ); . HANDLER->tsv->{jail}->error );
} }
} }
} }
} }
$self->{_jsRedirect} = $self->{_jsRedirect}
HANDLER->buildSub( HANDLER->substitute( $self->conf->{jsRedirect} ) ) = HANDLER->buildSub(
or $self->logger->error( HANDLER->substitute( $self->conf->{jsRedirect} ) )
or $self->logger->error(
'jsRedirect returns an error: ' . HANDLER->tsv->{jail}->error ); 'jsRedirect returns an error: ' . HANDLER->tsv->{jail}->error );
# Load plugins # Load plugins
@ -333,7 +332,7 @@ sub loadPlugin {
} }
my $obj; my $obj;
return 0 return 0
unless ( $obj = $self->loadModule("$plugin") ); unless ( $obj = $self->loadModule("$plugin") );
return $self->findEP( $plugin, $obj ); return $self->findEP( $plugin, $obj );
} }
@ -363,7 +362,7 @@ sub findEP {
if ( $obj->can('spRules') ) { if ( $obj->can('spRules') ) {
foreach my $k ( keys %{ $obj->{spRules} } ) { foreach my $k ( keys %{ $obj->{spRules} } ) {
$self->logger->info( $self->logger->info(
"$k is defined more than one time, it can have some bad effect on Menu display" "$k is defined more than one time, it can have some bad effect on Menu display"
) if ( $self->spRules->{$k} ); ) if ( $self->spRules->{$k} );
$self->spRules->{$k} = $obj->{spRules}->{$k}; $self->spRules->{$k} = $obj->{spRules}->{$k};
} }

View File

@ -99,12 +99,11 @@ sub controlUrl {
); );
# XSS attack # XSS attack
if ( if ($self->checkXSSAttack(
$self->checkXSSAttack(
$req->param('logout') ? 'HTTP Referer' : 'urldc', $req->param('logout') ? 'HTTP Referer' : 'urldc',
$req->{urldc} $req->{urldc}
) )
) )
{ {
delete $req->{urldc}; delete $req->{urldc};
return PE_BADURL; return PE_BADURL;
@ -113,9 +112,9 @@ sub controlUrl {
# Unprotected hosts # Unprotected hosts
if ( $tmp and !$self->isTrustedUrl($tmp) ) { if ( $tmp and !$self->isTrustedUrl($tmp) ) {
$self->userLogger->error( $self->userLogger->error(
"URL contains a non protected host (param: " "URL contains a non protected host (param: "
. ( $req->param('logout') ? 'HTTP Referer' : 'urldc' ) . ( $req->param('logout') ? 'HTTP Referer' : 'urldc' )
. " | value: $tmp)" ); . " | value: $tmp)" );
delete $req->{urldc}; delete $req->{urldc};
return PE_BADURL; return PE_BADURL;
} }
@ -166,7 +165,8 @@ sub deleteSession {
# TODO # TODO
# Collect logout services and build hidden iFrames # Collect logout services and build hidden iFrames
if ( $req->data->{logoutServices} and %{ $req->data->{logoutServices} } ) { if ( $req->data->{logoutServices} and %{ $req->data->{logoutServices} } )
{
$self->logger->debug("Create iFrames to forward logout to services"); $self->logger->debug("Create iFrames to forward logout to services");
@ -178,24 +178,25 @@ sub deleteSession {
foreach ( keys %{ $req->data->{logoutServices} } ) { foreach ( keys %{ $req->data->{logoutServices} } ) {
my $logoutServiceName = $_; my $logoutServiceName = $_;
my $logoutServiceUrl = my $logoutServiceUrl
$req->data->{logoutServices}->{$logoutServiceName}; = $req->data->{logoutServices}->{$logoutServiceName};
$self->logger->debug( $self->logger->debug(
"Find logout service $logoutServiceName ($logoutServiceUrl)"); "Find logout service $logoutServiceName ($logoutServiceUrl)");
my $iframe = my $iframe
qq'<iframe src="$logoutServiceUrl" alt="$logoutServiceName"' = qq'<iframe src="$logoutServiceUrl" alt="$logoutServiceName"'
. ' marginwidth="0" marginheight="0" scrolling="no"' . ' marginwidth="0" marginheight="0" scrolling="no"'
. ' class="hiddenFrame" width="0" height="0"' . ' class="hiddenFrame" width="0" height="0"'
. ' frameborder="0"></iframe>'; . ' frameborder="0"></iframe>';
$req->info($iframe); $req->info($iframe);
} }
# Redirect on logout page if no other target defined # Redirect on logout page if no other target defined
if ( !$req->urldc and !$req->postUrl ) { if ( !$req->urldc and !$req->postUrl ) {
$self->logger->debug('No other target defined, redirect on logout'); $self->logger->debug(
'No other target defined, redirect on logout');
$req->urldc( $req->script_name . "?logout=1" ); $req->urldc( $req->script_name . "?logout=1" );
} }
} }
@ -283,10 +284,15 @@ sub getUser {
sub authenticate { sub authenticate {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $ret = $req->authResult( $self->_authentication->authenticate($req) ); my $ret = $req->authResult( $self->_authentication->authenticate($req) );
$self->logger->debug(" -> authResult = $ret");
if ( $ret == PE_OK ) { if ( $ret == PE_OK ) {
$req->{sessionInfo}->{_lastAuthnUTime} = time(); $req->{sessionInfo}->{_lastAuthnUTime} = time();
return $ret;
} }
$self->setSessionInfo($req);
$self->setPersistentSessionInfo($req);
$self->setMacros($req);
$self->storeHistory($req);
return $ret; return $ret;
} }
@ -300,7 +306,8 @@ sub setAuthSessionInfo {
if ( $ret == PE_OK if ( $ret == PE_OK
and not( defined $req->sessionInfo->{authenticationLevel} ) ) and not( defined $req->sessionInfo->{authenticationLevel} ) )
{ {
$self->logger->error('Authentication level is not set by auth module'); $self->logger->error(
'Authentication level is not set by auth module');
} }
return $ret; return $ret;
} }
@ -320,15 +327,15 @@ sub setSessionInfo {
# Date and time # Date and time
if ( $self->conf->{updateSession} ) { if ( $self->conf->{updateSession} ) {
$req->{sessionInfo}->{_updateTime} = $req->{sessionInfo}->{_updateTime}
strftime( "%Y%m%d%H%M%S", localtime() ); = strftime( "%Y%m%d%H%M%S", localtime() );
} }
else { else {
$req->{sessionInfo}->{_utime} ||= time(); $req->{sessionInfo}->{_utime} ||= time();
$req->{sessionInfo}->{_startTime} = $req->{sessionInfo}->{_startTime}
strftime( "%Y%m%d%H%M%S", localtime() ); = strftime( "%Y%m%d%H%M%S", localtime() );
$req->{sessionInfo}->{_lastSeen} = time() $req->{sessionInfo}->{_lastSeen} = time()
if $self->conf->{timeoutActivity}; if $self->conf->{timeoutActivity};
} }
# Store URL origin in session # Store URL origin in session
@ -346,8 +353,8 @@ sub setSessionInfo {
sub setMacros { sub setMacros {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
foreach ( sort keys %{ $self->_macros } ) { foreach ( sort keys %{ $self->_macros } ) {
$req->{sessionInfo}->{$_} = $req->{sessionInfo}->{$_}
$self->_macros->{$_}->( $req, $req->sessionInfo ); = $self->_macros->{$_}->( $req, $req->sessionInfo );
} }
PE_OK; PE_OK;
} }
@ -387,16 +394,16 @@ sub setLocalGroups {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
foreach ( sort keys %{ $self->_groups } ) { foreach ( sort keys %{ $self->_groups } ) {
if ( $self->_groups->{$_}->( $req, $req->sessionInfo ) ) { if ( $self->_groups->{$_}->( $req, $req->sessionInfo ) ) {
$req->{sessionInfo}->{groups} .= $req->{sessionInfo}->{groups}
$self->conf->{multiValuesSeparator} . $_; .= $self->conf->{multiValuesSeparator} . $_;
$req->{sessionInfo}->{hGroups}->{$_}->{name} = $_; $req->{sessionInfo}->{hGroups}->{$_}->{name} = $_;
} }
} }
# Clear values separator at the beginning # Clear values separator at the beginning
if ( $req->{sessionInfo}->{groups} ) { if ( $req->{sessionInfo}->{groups} ) {
$req->{sessionInfo}->{groups} =~ $req->{sessionInfo}->{groups}
s/^$self->{conf}->{multiValuesSeparator}//o; =~ s/^$self->{conf}->{multiValuesSeparator}//o;
} }
PE_OK; PE_OK;
} }
@ -420,8 +427,8 @@ sub store {
# Compute unsecure cookie value if needed # Compute unsecure cookie value if needed
if ( $self->conf->{securedCookie} == 3 ) { if ( $self->conf->{securedCookie} == 3 ) {
$req->{sessionInfo}->{_httpSession} = $req->{sessionInfo}->{_httpSession}
$self->conf->{cipher}->encryptHex( $req->{id}, "http" ); = $self->conf->{cipher}->encryptHex( $req->{id}, "http" );
} }
# Fill session # Fill session

View File

@ -17,11 +17,11 @@ use strict;
use URI::Escape; use URI::Escape;
# List constants # List constants
sub authProcess { qw(extractFormInfo getUser authenticate) } sub authProcess {qw(extractFormInfo getUser authenticate)}
sub sessionData { sub sessionData {
qw(setAuthSessionInfo setSessionInfo setMacros setGroups setPersistentSessionInfo qw(setAuthSessionInfo setSessionInfo setMacros setGroups setPersistentSessionInfo
setLocalGroups store secondFactor); setLocalGroups store secondFactor);
} }
sub validSession { sub validSession {
@ -56,10 +56,11 @@ sub handler {
if ( $sp or %{ $req->pdata } ) { if ( $sp or %{ $req->pdata } ) {
my %v = ( my %v = (
name => $self->conf->{cookieName} . 'pdata', name => $self->conf->{cookieName} . 'pdata',
( ( %{ $req->pdata }
%{ $req->pdata }
? ( value => uri_escape( JSON::to_json( $req->pdata ) ) ) ? ( value => uri_escape( JSON::to_json( $req->pdata ) ) )
: ( value => '', expires => 'Wed, 21 Oct 2015 00:00:00 GMT' ) : ( value => '',
expires => 'Wed, 21 Oct 2015 00:00:00 GMT'
)
) )
); );
push @{ $res->[1] }, 'Set-Cookie', $self->cookie(%v); push @{ $res->[1] }, 'Set-Cookie', $self->cookie(%v);
@ -91,8 +92,7 @@ sub login {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ [ 'controlUrl', @{ $self->beforeAuth },
'controlUrl', @{ $self->beforeAuth },
$self->authProcess, @{ $self->betweenAuthAndData }, $self->authProcess, @{ $self->betweenAuthAndData },
$self->sessionData, @{ $self->afterData }, $self->sessionData, @{ $self->afterData },
$self->validSession, @{ $self->endAuth }, $self->validSession, @{ $self->endAuth },
@ -104,8 +104,7 @@ sub postLogin {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ [ 'restoreArgs', 'controlUrl',
'restoreArgs', 'controlUrl',
@{ $self->beforeAuth }, $self->authProcess, @{ $self->beforeAuth }, $self->authProcess,
@{ $self->betweenAuthAndData }, $self->sessionData, @{ $self->betweenAuthAndData }, $self->sessionData,
@{ $self->afterData }, $self->validSession, @{ $self->afterData }, $self->validSession,
@ -118,8 +117,7 @@ sub authenticatedRequest {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ [ 'importHandlerData', 'controlUrl',
'importHandlerData', 'controlUrl',
'checkLogout', @{ $self->forAuthUser } 'checkLogout', @{ $self->forAuthUser }
] ]
); );
@ -129,8 +127,7 @@ sub postAuthenticatedRequest {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ [ 'importHandlerData', 'restoreArgs',
'importHandlerData', 'restoreArgs',
'controlUrl', 'checkLogout', 'controlUrl', 'checkLogout',
@{ $self->forAuthUser } @{ $self->forAuthUser }
] ]
@ -148,8 +145,7 @@ sub refresh {
delete $data{$_} unless ( /^_/ or /^(?:startTime)$/ ); delete $data{$_} unless ( /^_/ or /^(?:startTime)$/ );
} }
$req->steps( $req->steps(
[ [ 'getUser',
'getUser',
@{ $self->betweenAuthAndData }, @{ $self->betweenAuthAndData },
'setAuthSessionInfo', 'setAuthSessionInfo',
'setSessionInfo', 'setSessionInfo',
@ -167,21 +163,21 @@ sub refresh {
if ($res) { if ($res) {
$req->info( $req->info(
$self->loadTemplate( $self->loadTemplate(
'simpleInfo', params => { trspan => 'rightsReloadNeedsLogout' } 'simpleInfo',
params => { trspan => 'rightsReloadNeedsLogout' }
) )
); );
$req->urldc( $self->conf->{portal} ); $req->urldc( $self->conf->{portal} );
return $self->do( $req, [ sub { PE_INFO } ] ); return $self->do( $req, [ sub {PE_INFO} ] );
} }
return $self->do( $req, [ sub { PE_OK } ] ); return $self->do( $req, [ sub {PE_OK} ] );
} }
sub logout { sub logout {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ [ 'controlUrl', @{ $self->beforeLogout },
'controlUrl', @{ $self->beforeLogout },
'authLogout', 'deleteSession' 'authLogout', 'deleteSession'
] ]
); );
@ -198,9 +194,9 @@ sub do {
# Update status # Update status
if ( my $p = $self->HANDLER->tsv->{statusPipe} ) { if ( my $p = $self->HANDLER->tsv->{statusPipe} ) {
$p->print( ( $req->user ? $req->user : $req->address ) . ' => ' $p->print(( $req->user ? $req->user : $req->address ) . ' => '
. $req->uri . $req->uri
. " $err\n" ); . " $err\n" );
} }
# Update history # Update history
@ -212,8 +208,7 @@ sub do {
if ( ( $err > 0 and !$req->id ) or $err eq PE_SESSIONNOTGRANTED ) { if ( ( $err > 0 and !$req->id ) or $err eq PE_SESSIONNOTGRANTED ) {
return [ return [
401, 401,
[ [ 'WWW-Authenticate' => "SSO " . $self->conf->{portal},
'WWW-Authenticate' => "SSO " . $self->conf->{portal},
'Access-Control-Allow-Origin' => '*' 'Access-Control-Allow-Origin' => '*'
], ],
[qq'{"result":0,"error":$err}'] [qq'{"result":0,"error":$err}']
@ -229,16 +224,14 @@ sub do {
else { else {
return $self->sendJSONresponse( return $self->sendJSONresponse(
$req, $req,
{ { result => 1,
result => 1,
code => $err code => $err
} }
); );
} }
} }
else { else {
if ( if ( $err
$err
and $err != PE_LOGOUT_OK and $err != PE_LOGOUT_OK
and ( and (
$err != PE_REDIRECT $err != PE_REDIRECT
@ -247,7 +240,7 @@ sub do {
and $req->data->{redirectFormMethod} eq 'post' ) and $req->data->{redirectFormMethod} eq 'post' )
or $req->info or $req->info
) )
) )
{ {
my ( $tpl, $prms ) = $self->display($req); my ( $tpl, $prms ) = $self->display($req);
$self->logger->debug("Calling sendHtml with template $tpl"); $self->logger->debug("Calling sendHtml with template $tpl");
@ -265,21 +258,20 @@ sub do {
sub getModule { sub getModule {
my ( $self, $req, $type ) = @_; my ( $self, $req, $type ) = @_;
if ( if (my $mod = {
my $mod = {
auth => '_authentication', auth => '_authentication',
user => '_userDB', user => '_userDB',
password => '_passwordDB' password => '_passwordDB'
}->{$type} }->{$type}
) )
{ {
if ( my $sub = $self->$mod->can('name') ) { if ( my $sub = $self->$mod->can('name') ) {
return $sub->( $self->$mod, $req, $type ); return $sub->( $self->$mod, $req, $type );
} }
else { else {
my $s = ref( $self->$mod ); my $s = ref( $self->$mod );
$s =~ $s
s/^Lemonldap::NG::Portal::(?:(?:Issuer|UserDB|Auth|Password)::)?//; =~ s/^Lemonldap::NG::Portal::(?:(?:Issuer|UserDB|Auth|Password)::)?//;
return $s; return $s;
} }
} }
@ -296,7 +288,7 @@ sub autoRedirect {
# Set redirection URL if needed # Set redirection URL if needed
$req->{urldc} ||= $self->conf->{portal} $req->{urldc} ||= $self->conf->{portal}
if ( $req->mustRedirect and not( $req->info ) ); if ( $req->mustRedirect and not( $req->info ) );
# Redirection should be made if urldc defined # Redirection should be made if urldc defined
if ( $req->{urldc} ) { if ( $req->{urldc} ) {
@ -306,8 +298,9 @@ sub autoRedirect {
$req->data->{redirectFormMethod} = "get"; $req->data->{redirectFormMethod} = "get";
} }
else { else {
return [ 302, return [
[ Location => $req->{urldc}, @{ $req->respHeaders } ], [] ]; 302, [ Location => $req->{urldc}, @{ $req->respHeaders } ], []
];
} }
} }
my ( $tpl, $prms ) = $self->display($req); my ( $tpl, $prms ) = $self->display($req);
@ -329,8 +322,7 @@ sub getApacheSession {
} }
my $as = Lemonldap::NG::Common::Session->new( my $as = Lemonldap::NG::Common::Session->new(
{ { storageModule => $self->conf->{globalStorage},
storageModule => $self->conf->{globalStorage},
storageModuleOptions => $self->conf->{globalStorageOptions}, storageModuleOptions => $self->conf->{globalStorageOptions},
cacheModule => $self->conf->{localSessionStorage}, cacheModule => $self->conf->{localSessionStorage},
cacheModuleOptions => $self->conf->{localSessionStorageOptions}, cacheModuleOptions => $self->conf->{localSessionStorageOptions},
@ -344,8 +336,7 @@ sub getApacheSession {
if ( my $err = $as->error ) { if ( my $err = $as->error ) {
$self->lmLog( $self->lmLog(
$err, $err,
( ( $err =~ /(?:Object does not exist|Invalid session ID)/
$err =~ /(?:Object does not exist|Invalid session ID)/
? 'notice' ? 'notice'
: 'error' : 'error'
) )
@ -359,17 +350,16 @@ sub getApacheSession {
} }
my $now = time; my $now = time;
if ( if ( $id
$id
and defined $as->data->{_utime} and defined $as->data->{_utime}
and ( and (
$now - $as->data->{_utime} > $self->conf->{timeout} $now - $as->data->{_utime} > $self->conf->{timeout}
or ( $self->conf->{timeoutActivity} or ( $self->conf->{timeoutActivity}
and $as->data->{_lastSeen} and $as->data->{_lastSeen}
and $now - $as->data->{_lastSeen} > and $now - $as->data->{_lastSeen}
$self->conf->{timeoutActivity} ) > $self->conf->{timeoutActivity} )
)
) )
)
{ {
$self->logger->debug("Session $args{kind} $id expired"); $self->logger->debug("Session $args{kind} $id expired");
return; return;
@ -392,8 +382,7 @@ sub getPersistentSession {
$info->{_session_uid} = $uid; $info->{_session_uid} = $uid;
my $ps = Lemonldap::NG::Common::Session->new( my $ps = Lemonldap::NG::Common::Session->new(
{ { storageModule => $self->conf->{persistentStorage},
storageModule => $self->conf->{persistentStorage},
storageModuleOptions => $self->conf->{persistentStorageOptions}, storageModuleOptions => $self->conf->{persistentStorageOptions},
id => $pid, id => $pid,
force => 1, force => 1,
@ -433,11 +422,12 @@ sub updatePersistentSession {
# Return if no infos to update # Return if no infos to update
return () unless ( ref $infos eq 'HASH' and %$infos ); return () unless ( ref $infos eq 'HASH' and %$infos );
$uid ||= $req->{sessionInfo}->{ $self->conf->{whatToTrace} } $uid ||= $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|| $req->userData->{ $self->conf->{whatToTrace} }; || $req->userData->{ $self->conf->{whatToTrace} };
$self->logger->debug("Found 'whatToTrace' -> $uid");
unless ($uid) { unless ($uid) {
$self->logger->debug('No uid found, skipping updatePersistentSession'); $self->logger->debug(
'No uid found, skipping updatePersistentSession');
return (); return ();
} }
$self->logger->debug("Update $uid persistent session"); $self->logger->debug("Update $uid persistent session");
@ -479,14 +469,14 @@ sub updateSession {
foreach ( keys %$infos ) { foreach ( keys %$infos ) {
$self->logger->debug( $self->logger->debug(
"Update sessionInfo $_ with " . $infos->{$_} ); "Update sessionInfo $_ with " . $infos->{$_} );
$req->{sessionInfo}->{$_} = $self->HANDLER->data->{$_} = $req->{sessionInfo}->{$_} = $self->HANDLER->data->{$_}
$infos->{$_}; = $infos->{$_};
} }
# Update session in global storage with _updateTime # Update session in global storage with _updateTime
$infos->{_updateTime} = strftime( "%Y%m%d%H%M%S", localtime() ); $infos->{_updateTime} = strftime( "%Y%m%d%H%M%S", localtime() );
if ( my $apacheSession = if ( my $apacheSession
$self->getApacheSession( $id, info => $infos ) ) = $self->getApacheSession( $id, info => $infos ) )
{ {
if ( $apacheSession->error ) { if ( $apacheSession->error ) {
$self->logger->error("Cannot update session $id"); $self->logger->error("Cannot update session $id");
@ -569,8 +559,10 @@ sub isTrustedUrl {
sub stamp { sub stamp {
my $self = shift; my $self = shift;
my $res = my $res
$self->conf->{cipher} ? $self->conf->{cipher}->encrypt( time() ) : 1; = $self->conf->{cipher}
? $self->conf->{cipher}->encrypt( time() )
: 1;
$res =~ s/\+/%2B/g; $res =~ s/\+/%2B/g;
return $res; return $res;
} }
@ -702,7 +694,7 @@ sub cookie {
$h{path} ||= '/'; $h{path} ||= '/';
$h{HttpOnly} //= $self->conf->{httpOnly}; $h{HttpOnly} //= $self->conf->{httpOnly};
$h{max_age} //= $self->conf->{cookieExpiration} $h{max_age} //= $self->conf->{cookieExpiration}
if ( $self->conf->{cookieExpiration} ); if ( $self->conf->{cookieExpiration} );
foreach (qw(domain path expires max_age HttpOnly)) { foreach (qw(domain path expires max_age HttpOnly)) {
my $f = $_; my $f = $_;
$f =~ s/_/-/g; $f =~ s/_/-/g;
@ -725,8 +717,8 @@ sub sendHtml {
my ( $self, $req, $template, %args ) = @_; my ( $self, $req, $template, %args ) = @_;
my $res = $self->SUPER::sendHtml( $req, $template, %args ); my $res = $self->SUPER::sendHtml( $req, $template, %args );
push @{ $res->[1] }, push @{ $res->[1] },
'X-XSS-Protection' => '1; mode=block', 'X-XSS-Protection' => '1; mode=block',
'X-Content-Type-Options' => 'nosniff'; 'X-Content-Type-Options' => 'nosniff';
# Set authorized URL for POST # Set authorized URL for POST
my $csp = $self->csp . "form-action 'self'"; my $csp = $self->csp . "form-action 'self'";
@ -740,13 +732,14 @@ sub sendHtml {
if ( defined $url ) { if ( defined $url ) {
$self->logger->debug("Required Params URL : $url"); $self->logger->debug("Required Params URL : $url");
if ( $url =~ s#(https?://[^/]+).*#$1# ) { if ( $url =~ s#(https?://[^/]+).*#$1# ) {
$self->logger->debug("Set CSP form-action with Params URL : $url"); $self->logger->debug(
"Set CSP form-action with Params URL : $url");
$csp .= " $url"; $csp .= " $url";
} }
} }
if ( defined $req->{cspFormAction} ) { if ( defined $req->{cspFormAction} ) {
$self->logger->debug( $self->logger->debug( "Set CSP form-action with request URL: "
"Set CSP form-action with request URL: " . $req->{cspFormAction} ); . $req->{cspFormAction} );
$csp .= " " . $req->{cspFormAction}; $csp .= " " . $req->{cspFormAction};
} }
$csp .= ';'; $csp .= ';';
@ -761,7 +754,7 @@ sub sendHtml {
my @url; my @url;
if ( $req->info ) { if ( $req->info ) {
@url = map { s#https?://([^/]+).*#$1#; $_ } @url = map { s#https?://([^/]+).*#$1#; $_ }
( $req->info =~ /<iframe.*?src="(.*?)"/sg ); ( $req->info =~ /<iframe.*?src="(.*?)"/sg );
} }
if (@url) { if (@url) {
$csp .= join( ' ', 'child-src', @url ) . ';'; $csp .= join( ' ', 'child-src', @url ) . ';';
@ -775,17 +768,16 @@ sub sendHtml {
sub sendCss { sub sendCss {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $s = my $s
'html,body{background:url("' = 'html,body{background:url("'
. $self->staticPrefix . $self->staticPrefix
. '/common/backgrounds/' . '/common/backgrounds/'
. $self->conf->{portalSkinBackground} . $self->conf->{portalSkinBackground}
. '") no-repeat center fixed;' . '") no-repeat center fixed;'
. 'background-size:cover;}'; . 'background-size:cover;}';
return [ return [
200, 200,
[ [ 'Content-Type' => 'text/css',
'Content-Type' => 'text/css',
'Content-Length' => length($s), 'Content-Length' => length($s),
'Cache-Control' => 'public,max-age=3600', 'Cache-Control' => 'public,max-age=3600',
], ],
@ -807,16 +799,16 @@ sub lmError {
# Error code # Error code
$templateParams{"ERROR$_"} = ( $httpError == $_ ? 1 : 0 ) $templateParams{"ERROR$_"} = ( $httpError == $_ ? 1 : 0 )
foreach ( 403, 404, 500, 502, 503 ); foreach ( 403, 404, 500, 502, 503 );
return $self->sendHtml( $req, 'error', params => \%templateParams ); return $self->sendHtml( $req, 'error', params => \%templateParams );
} }
sub rebuildCookies { sub rebuildCookies {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my @tmp; my @tmp;
for ( my $i = 0 ; $i < @{ $req->{respHeaders} } ; $i += 2 ) { for ( my $i = 0; $i < @{ $req->{respHeaders} }; $i += 2 ) {
push @tmp, $req->respHeaders->[0], $req->respHeaders->[1] push @tmp, $req->respHeaders->[0], $req->respHeaders->[1]
unless ( $req->respHeaders->[0] eq 'Set-Cookie' ); unless ( $req->respHeaders->[0] eq 'Set-Cookie' );
} }
$req->{respHeaders} = \@tmp; $req->{respHeaders} = \@tmp;
$self->buildCookie($req); $self->buildCookie($req);
@ -839,7 +831,7 @@ sub tplParams {
sub registerLogin { sub registerLogin {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return return
unless ( $self->conf->{loginHistoryEnabled} unless ( $self->conf->{loginHistoryEnabled}
and defined $req->authResult ); and defined $req->authResult );
my $history = $req->sessionInfo->{_loginHistory} ||= {}; my $history = $req->sessionInfo->{_loginHistory} ||= {};
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login'; my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
@ -849,14 +841,15 @@ sub registerLogin {
# Gather current login's parameters # Gather current login's parameters
my $login = $self->_sumUpSession( $req->{sessionInfo}, 1 ); my $login = $self->_sumUpSession( $req->{sessionInfo}, 1 );
$login->{error} = $self->error( $req->authResult ) $login->{error} = $self->error( $req->authResult )
if ( $req->authResult ); if ( $req->authResult );
# Add current login into history # Add current login into history
unshift @{ $history->{$type} }, $login; unshift @{ $history->{$type} }, $login;
# Forget oldest logins # Forget oldest logins
splice @{ $history->{$type} }, $self->conf->{ $type . "Number" } splice @{ $history->{$type} }, $self->conf->{ $type . "Number" }
if ( scalar @{ $history->{$type} } > $self->conf->{ $type . "Number" } ); if (
scalar @{ $history->{$type} } > $self->conf->{ $type . "Number" } );
# Save into persistent session # Save into persistent session
$self->updatePersistentSession( $req, { _loginHistory => $history, } ); $self->updatePersistentSession( $req, { _loginHistory => $history, } );
@ -867,12 +860,12 @@ sub registerLogin {
# @return hashref # @return hashref
sub _sumUpSession { sub _sumUpSession {
my ( $self, $session, $withoutUser ) = @_; my ( $self, $session, $withoutUser ) = @_;
my $res = my $res
$withoutUser = $withoutUser
? {} ? {}
: { user => $session->{ $self->conf->{whatToTrace} } }; : { user => $session->{ $self->conf->{whatToTrace} } };
$res->{$_} = $session->{$_} $res->{$_} = $session->{$_}
foreach ( "_utime", "ipAddr", foreach ( "_utime", "ipAddr",
keys %{ $self->conf->{sessionDataToRemember} } ); keys %{ $self->conf->{sessionDataToRemember} } );
return $res; return $res;
} }
@ -881,11 +874,12 @@ sub _sumUpSession {
sub loadTemplate { sub loadTemplate {
my ( $self, $name, %prm ) = @_; my ( $self, $name, %prm ) = @_;
$name .= '.tpl'; $name .= '.tpl';
my $file = my $file
$self->conf->{templateDir} . '/' = $self->conf->{templateDir} . '/'
. $self->conf->{portalSkin} . '/' . $self->conf->{portalSkin} . '/'
. $name; . $name;
$file = $self->conf->{templateDir} . '/common/' . $name unless ( -e $file ); $file = $self->conf->{templateDir} . '/common/' . $name
unless ( -e $file );
unless ( -e $file ) { unless ( -e $file ) {
die "Unable to find $name in $self->conf->{templateDir}"; die "Unable to find $name in $self->conf->{templateDir}";
} }

View File

@ -1,6 +1,5 @@
package Lemonldap::NG::Portal::Main::SecondFactor; package Lemonldap::NG::Portal::Main::SecondFactor;
use Data::Dumper;
use strict; use strict;
use Mouse; use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
@ -88,7 +87,6 @@ sub _verify {
$req->sessionInfo($session); $req->sessionInfo($session);
$req->id( delete $req->sessionInfo->{_2fRealSession} ); $req->id( delete $req->sessionInfo->{_2fRealSession} );
$req->urldc( delete $req->sessionInfo->{_2fUrldc} ); $req->urldc( delete $req->sessionInfo->{_2fUrldc} );
$self->logger->debug("req badcredentials -> " . Dumper($req));
$req->authResult(PE_BADCREDENTIALS); $req->authResult(PE_BADCREDENTIALS);
return $self->p->do( $req, return $self->p->do( $req,
[ $self->p->storeHistory($req), sub {$res} ] ); [ $self->p->storeHistory($req), sub {$res} ] );
@ -98,11 +96,13 @@ sub _verify {
$req->sessionInfo($session); $req->sessionInfo($session);
$req->id( delete $req->sessionInfo->{_2fRealSession} ); $req->id( delete $req->sessionInfo->{_2fRealSession} );
$req->urldc( delete $req->sessionInfo->{_2fUrldc} ); $req->urldc( delete $req->sessionInfo->{_2fUrldc} );
$req->{sessionInfo}->{_utime} = delete $req->{sessionInfo}->{_2fUtime};
$self->p->rebuildCookies($req); $self->p->rebuildCookies($req);
$req->mustRedirect(1); $req->mustRedirect(1);
$self->userLogger->notice( $self->prefix $self->userLogger->notice( $self->prefix
. '2F verification for ' . '2F verification for '
. $req->sessionInfo->{ $self->conf->{whatToTrace} } ); . $req->sessionInfo->{ $self->conf->{whatToTrace} } );
if ( my $l = $self->conf->{ $self->prefix . '2fAuthnLevel' } ) { if ( my $l = $self->conf->{ $self->prefix . '2fAuthnLevel' } ) {
$self->p->updateSession( $req, { authenticationLevel => $l } ); $self->p->updateSession( $req, { authenticationLevel => $l } );
} }