214 lines
6.3 KiB
Perl
214 lines
6.3 KiB
Perl
# Plugin to enable "stay connected on this device" feature
|
|
|
|
package Lemonldap::NG::Portal::Plugins::StayConnected;
|
|
|
|
use 5.16.0;
|
|
use strict;
|
|
use Mouse;
|
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
|
PE_OK
|
|
PE_SENDRESPONSE
|
|
);
|
|
|
|
our $VERSION = '2.0.0';
|
|
|
|
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
|
|
|
# INTERFACE
|
|
|
|
use constant afterDatas => 'newDevice';
|
|
|
|
use constant beforeAuth => 'check';
|
|
|
|
use constant beforeLogout => 'logout';
|
|
|
|
# INITIALIZATION
|
|
|
|
has ott => (
|
|
is => 'rw',
|
|
lazy => 1,
|
|
default => sub {
|
|
my $ott =
|
|
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
|
|
$ott->timeout( $_[0]->conf->{formTimeout} );
|
|
return $ott;
|
|
}
|
|
);
|
|
|
|
# Default timeout: 1 month
|
|
has timeout => (
|
|
is => 'rw',
|
|
lazy => 1,
|
|
default => sub {
|
|
$_[0]->{conf}->{stayConnectedTimeout} || 2678400;
|
|
}
|
|
);
|
|
|
|
sub init {
|
|
my ($self) = @_;
|
|
$self->addAuthRoute( registerbrowser => 'storeBrowser', ['POST'] );
|
|
|
|
}
|
|
|
|
# RUNNING METHODS
|
|
|
|
# Registration: detect if user wants to stay connected. Then ask for
|
|
# fingerprint
|
|
sub newDevice {
|
|
my ( $self, $req ) = @_;
|
|
|
|
if ( $req->param('stayconnected') ) {
|
|
my $token = $self->ott->createToken(
|
|
{
|
|
name => $req->sessionInfo->{ $self->conf->{whatToTrace} }
|
|
}
|
|
);
|
|
$req->response(
|
|
$self->p->sendHtml(
|
|
$req,
|
|
'../common/registerBrowser',
|
|
params => {
|
|
URL => $req->urldc,
|
|
TOKEN => $token,
|
|
ACTION => '/registerbrowser',
|
|
}
|
|
)
|
|
);
|
|
return PE_SENDRESPONSE;
|
|
}
|
|
return PE_OK;
|
|
}
|
|
|
|
# Store datas in a long-time session
|
|
sub storeBrowser {
|
|
my ( $self, $req ) = @_;
|
|
$req->urldc( $req->param('url') );
|
|
$req->mustRedirect(1);
|
|
if ( my $token = $req->param('token') ) {
|
|
if ( my $tmp = $self->ott->getToken($token) ) {
|
|
my $uid = $req->userData->{ $self->conf->{whatToTrace} };
|
|
if ( $tmp->{name} eq $uid ) {
|
|
if ( my $fg = $req->param('fg') ) {
|
|
my $ps = Lemonldap::NG::Common::Session->new(
|
|
storageModule => $self->conf->{globalStorage},
|
|
storageModuleOptions =>
|
|
$self->conf->{globalStorageOptions},
|
|
kind => "SSO",
|
|
info => {
|
|
_utime => time + $self->timeout,
|
|
_session_uid => $uid,
|
|
_connectedSince => time,
|
|
dataKeep => $req->datas->{dataToKeep},
|
|
fingerprint => $fg,
|
|
},
|
|
);
|
|
|
|
# Cookie available 30 days
|
|
$req->addCookie(
|
|
$self->p->cookie(
|
|
name => 'llngconnexion',
|
|
value => $ps->id,
|
|
max_age => 2592000,
|
|
)
|
|
);
|
|
}
|
|
else {
|
|
$self->logger->warn("Browser hasn't return fingerprint");
|
|
}
|
|
}
|
|
else {
|
|
$self->userLogger->error(
|
|
"StayConnected: mismatch UID: $tmp->{name} / $uid");
|
|
}
|
|
}
|
|
else {
|
|
$self->userLogger->error("StayConnected call with expired token");
|
|
}
|
|
}
|
|
else {
|
|
$self->userLogger->error('StayConnected call without token');
|
|
}
|
|
|
|
# Deliver cookie llngbrowser
|
|
return $self->p->do( $req, [ sub { PE_OK } ] );
|
|
}
|
|
|
|
# Check for:
|
|
# - persistent connection cookie
|
|
# - valid session
|
|
# - uniq id is kept
|
|
# Then delete authentication methods from "steps" array.
|
|
sub check {
|
|
my ( $self, $req ) = @_;
|
|
if ( my $cid = $req->cookies->{llngconnexion} ) {
|
|
my $ps = Lemonldap::NG::Common::Session->new(
|
|
storageModule => $self->conf->{globalStorage},
|
|
storageModuleOptions => $self->conf->{globalStorageOptions},
|
|
kind => "SSO",
|
|
id => $cid,
|
|
);
|
|
if ( $ps and my $uid = $ps->data->{_session_uid} ) {
|
|
$self->logger->debug('Persistent connection found');
|
|
if ( my $fg = $req->param('fg')
|
|
and my $token = $req->param('token') )
|
|
{
|
|
if ( my $prm = $self->ott->getToken($token) ) {
|
|
$req->datas->{dataKeep} = $ps->data->{dataKeep};
|
|
$self->logger->debug('Persistent connection found');
|
|
if ( $fg eq $ps->data->{fingerprint} ) {
|
|
$req->user($uid);
|
|
my @steps =
|
|
grep {
|
|
!ref $_
|
|
and $_ !~ /^(?:extractFormInfo|authenticate)$/
|
|
} @{ $req->steps };
|
|
$req->steps( \@steps );
|
|
$self->userLogger->notice(
|
|
"$uid connected by StayConnected cookie");
|
|
return PE_OK;
|
|
}
|
|
else {
|
|
$self->userLogger->warn("Fingerprint changed for $uid");
|
|
}
|
|
}
|
|
else {
|
|
$self->userLogger->notice(
|
|
"StayConnected: expired token for $uid");
|
|
}
|
|
}
|
|
else {
|
|
my $token = $self->ott->createToken( $req->parameters );
|
|
$req->response(
|
|
$self->p->sendHtml(
|
|
$req,
|
|
'../common/registerBrowser',
|
|
params => {
|
|
TOKEN => $token,
|
|
ACTION => '#',
|
|
}
|
|
)
|
|
);
|
|
return PE_SENDRESPONSE;
|
|
}
|
|
}
|
|
else {
|
|
$self->userLogger->notice('Persistent connection expired');
|
|
}
|
|
}
|
|
return PE_OK;
|
|
}
|
|
|
|
sub logout {
|
|
my ( $self, $req ) = @_;
|
|
$req->addCookie(
|
|
$self->p->cookie(
|
|
name => 'llngconnexion',
|
|
value => 0,
|
|
expires => 'Wed, 21 Oct 2015 00:00:00 GMT'
|
|
)
|
|
);
|
|
PE_OK;
|
|
}
|
|
|
|
1;
|