2017-01-23 12:28:13 +01:00
|
|
|
package Lemonldap::NG::Portal::Lib::OneTimeToken;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use Mouse;
|
2017-03-11 19:11:57 +01:00
|
|
|
use JSON qw(from_json to_json);
|
2017-01-23 12:28:13 +01:00
|
|
|
|
2017-02-28 21:53:19 +01:00
|
|
|
our $VERSION = '2.0.0';
|
|
|
|
|
2017-01-23 12:28:13 +01:00
|
|
|
extends 'Lemonldap::NG::Common::Module';
|
|
|
|
|
|
|
|
has timeout => (
|
|
|
|
is => 'rw',
|
|
|
|
default => sub {
|
|
|
|
$_[0]->{conf}->{timeout};
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-03-11 19:11:57 +01:00
|
|
|
has cache => (
|
|
|
|
is => 'rw',
|
|
|
|
default => sub {
|
|
|
|
my $c = $_[0]->{conf};
|
|
|
|
if ( !$c->{tokenUseGlobalStorage} ) {
|
|
|
|
if ( $c->{localSessionStorage} ) {
|
|
|
|
eval "use $c->{localSessionStorage}";
|
|
|
|
if ($@) {
|
|
|
|
$_[0]->{p}->logger->error($@);
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
return $c->{localSessionStorage}
|
|
|
|
->new( $c->{localSessionStorageOptions} );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$_[0]->{p}->logger->error(
|
|
|
|
'Local storage not defined, token will be store in global storage'
|
|
|
|
);
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2017-01-23 12:28:13 +01:00
|
|
|
sub createToken {
|
|
|
|
my ( $self, $infos ) = @_;
|
|
|
|
|
|
|
|
# Set _utime for session autoremove
|
|
|
|
# Use default session timeout and register session timeout to compute it
|
|
|
|
my $time = time();
|
|
|
|
|
|
|
|
# Set _utime to remove token after $self->timeout
|
|
|
|
$infos->{_utime} = $time + ( $self->timeout - $self->conf->{timeout} );
|
|
|
|
|
|
|
|
# Store expiration timestamp for further use
|
|
|
|
$infos->{tokenTimeoutTimestamp} = $time + $self->timeout;
|
|
|
|
|
|
|
|
# Store start timestamp for further use
|
|
|
|
$infos->{tokenSessionStartTimestamp} = $time;
|
|
|
|
|
|
|
|
# Store type
|
|
|
|
$infos->{_type} ||= "token";
|
|
|
|
|
2017-03-11 19:11:57 +01:00
|
|
|
if ( $self->cache ) {
|
|
|
|
my $id = $infos->{_utime} . '_' . int( rand(10000) );
|
2017-01-23 12:28:13 +01:00
|
|
|
|
2017-03-11 19:11:57 +01:00
|
|
|
# Dereference $infos
|
|
|
|
my %h = %$infos;
|
|
|
|
$self->cache->set( $id, to_json( \%h ) );
|
|
|
|
return $id;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
# Create a new session
|
|
|
|
my $tsession = $self->p->getApacheSession( undef, info => $infos );
|
|
|
|
return $tsession->id;
|
|
|
|
}
|
2017-01-23 12:28:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub getToken {
|
|
|
|
my ( $self, $id ) = @_;
|
|
|
|
unless ($id) {
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->error('getToken called without id');
|
2017-01-23 12:28:13 +01:00
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
2017-03-11 19:11:57 +01:00
|
|
|
if ( $self->cache ) {
|
|
|
|
my $data;
|
|
|
|
my @t = split /_/, $id;
|
|
|
|
if ( $t[0] > time ) {
|
|
|
|
$self->logger->notice("Expired token $id");
|
|
|
|
$self->cache->remove($id);
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
unless ( $data = $self->cache->get($id) ) {
|
|
|
|
$self->logger->notice("Bad (or expired) token $id");
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
$self->cache->remove($id);
|
|
|
|
return from_json($data);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
# Get token session
|
|
|
|
my $tsession = $self->p->getApacheSession($id);
|
|
|
|
unless ($tsession) {
|
|
|
|
$self->logger->notice("Bad (or expired) token $id");
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
my %h = %{ $tsession->{data} };
|
|
|
|
$tsession->remove;
|
|
|
|
return \%h;
|
2017-01-23 12:28:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-26 22:42:42 +01:00
|
|
|
sub setToken {
|
2017-01-29 14:06:28 +01:00
|
|
|
my ( $self, $req, $info ) = @_;
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->debug('Prepare token');
|
2017-01-29 14:06:28 +01:00
|
|
|
$req->token( $self->createToken($info) );
|
2017-01-26 22:42:42 +01:00
|
|
|
}
|
|
|
|
|
2017-01-23 12:28:13 +01:00
|
|
|
1;
|