lemonldap-ng/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session/REST.pm

302 lines
9.5 KiB
Perl
Raw Normal View History

2017-01-06 10:04:00 +01:00
package Lemonldap::NG::Common::Session::REST;
use strict;
use Mouse;
2017-01-08 09:42:19 +01:00
use Lemonldap::NG::Common::Conf::Constants;
2018-04-16 19:55:52 +02:00
use JSON qw(from_json to_json);
2017-01-08 09:42:19 +01:00
2022-01-26 22:49:13 +01:00
our $VERSION = '2.0.14';
2017-02-28 21:53:19 +01:00
2017-01-08 09:42:19 +01:00
has sessionTypes => ( is => 'rw' );
sub setTypes {
my ( $self, $conf ) = @_;
foreach my $type (@sessionTypes) {
if ( my $tmp =
$self->{ $type . 'Storage' } || $conf->{ $type . 'Storage' } )
{
$self->{sessionTypes}->{$type}->{module} = $tmp;
$self->{sessionTypes}->{$type}->{options} =
$self->{ $type . 'StorageOptions' }
|| $conf->{ $type . 'StorageOptions' }
|| {};
$self->{sessionTypes}->{$type}->{kind} =
( $type eq 'global' ? 'SSO' : ucfirst($type) );
}
}
my $offlinebackend = $self->{sessionTypes}->{oidc} ? 'oidc' : 'global';
$self->{sessionTypes}->{offline}->{module} =
$self->{sessionTypes}->{$offlinebackend}->{module};
$self->{sessionTypes}->{offline}->{options} =
$self->{sessionTypes}->{$offlinebackend}->{options};
$self->{sessionTypes}->{offline}->{kind} = "OIDCI";
2017-01-08 09:42:19 +01:00
}
2017-01-06 10:04:00 +01:00
sub separator {
$_[0]->{multiValuesSeparator} || $_[0]->conf->{multiValuesSeparator};
}
sub hAttr {
$_[0]->{hiddenAttributes} || $_[0]->conf->{hiddenAttributes};
}
### SEE LEMONLDAP::NG::COMMON::SESSION FOR AVAILABLE FUNCTIONS
2017-01-06 10:04:00 +01:00
sub delSession {
my ( $self, $req ) = @_;
return $self->sendJSONresponse( $req, { result => 1 } )
if ( $self->{demoMode} );
my $mod = $self->getMod($req)
or return $self->sendError( $req, undef, 400 );
my $id = $req->params('sessionId')
or return $self->sendError( $req, 'sessionId is missing', 400 );
my $session = $self->getApacheSession( $mod, $id );
2018-04-16 19:55:52 +02:00
$self->logger->debug("Delete session : $id");
2017-01-06 10:04:00 +01:00
$session->remove;
Lemonldap::NG::Handler::PSGI::Main->localUnlog( $req, $id );
2018-04-16 22:12:51 +02:00
2017-01-06 10:04:00 +01:00
if ( $session->error ) {
return $self->sendError( $req, $session->error, 200 );
}
return $self->sendJSONresponse( $req, { result => 1 } );
}
sub deleteOIDCConsent {
my ( $self, $req ) = @_;
return $self->sendJSONresponse( $req, { result => 1 } )
if ( $self->{demoMode} );
my $mod = $self->getMod($req)
or return $self->sendError( $req, undef, 400 );
my $id = $req->params('sessionId')
or return $self->sendError( $req, 'sessionId is missing', 400 );
# Try to read session
$self->logger->debug("Loading session : $id");
my $session = $self->getApacheSession( $mod, $id )
or return $self->sendError( $req, undef, 400 );
# Try to read OIDC Consent parameters
$self->logger->debug("Reading parameters ...");
my $params = $req->parameters();
my $rp = $params->{rp}
2018-08-30 23:21:20 +02:00
or
return $self->sendError( $req, 'OIDC Consent "RP" parameter is missing',
400 );
my $epoch = $params->{epoch}
2018-08-30 23:21:20 +02:00
or return $self->sendError( $req,
'OIDC Consent "epoch" parameter is missing', 400 );
2018-07-22 23:15:01 +02:00
# Try to load OIDC Consents from session
$self->logger->debug("Looking for OIDC Consent(s) ...");
my $_oidcConsents;
if ( $session->data->{_oidcConsents} ) {
$_oidcConsents = eval {
from_json( $session->data->{_oidcConsents}, { allow_nonref => 1 } );
};
if ($@) {
$self->logger->error("Corrupted session (_oidcConsents) : $@");
return $self->p->sendError( $req, "Corrupted session", 500 );
}
}
else {
$self->logger->debug("No OIDC Consent found");
$_oidcConsents = [];
}
# Delete OIDC Consent
$self->logger->debug("Reading OIDC Consent(s) ...");
my @keep = ();
while (@$_oidcConsents) {
my $element = shift @$_oidcConsents;
2018-08-30 23:21:20 +02:00
$self->logger->debug(
"Searching for OIDC Consent to delete -> $rp / $epoch ...");
2018-08-30 23:21:20 +02:00
if ( defined $element->{rp} && defined $element->{epoch} ) {
push @keep, $element
unless ( ( $element->{rp} eq $rp )
and ( $element->{epoch} eq $epoch ) );
}
else {
$self->logger->error("Corrupted OIDC Consent");
}
}
# Update session
$self->logger->debug("Saving OIDC Consents ...");
$session->data->{_oidcConsents} = to_json( \@keep );
$self->logger->debug("Updating session ...");
$session->update( \%{ $session->data } );
Lemonldap::NG::Handler::PSGI::Main->localUnlog( $req, $id );
if ( $session->error ) {
return $self->sendError( $req, $session->error, 200 );
}
return $self->sendJSONresponse( $req, { result => 1 } );
}
2018-04-16 17:07:38 +02:00
sub delete2F {
my ( $self, $req ) = @_;
return $self->sendJSONresponse( $req, { result => 1 } )
if ( $self->{demoMode} );
my $mod = $self->getMod($req)
or return $self->sendError( $req, undef, 400 );
my $id = $req->params('sessionId')
or return $self->sendError( $req, 'sessionId is missing', 400 );
# Try to read session
2018-04-16 22:12:51 +02:00
$self->logger->debug("Loading session : $id");
my $session = $self->getApacheSession( $mod, $id )
or return $self->sendError( $req, undef, 400 );
2018-04-16 22:12:51 +02:00
# Try to read 2F parameters
$self->logger->debug("Reading parameters ...");
my $params = $req->parameters();
my $type = $params->{type}
2018-08-30 23:21:20 +02:00
or return $self->sendError( $req, '2F device "type" parameter is missing',
400 );
2018-04-16 22:12:51 +02:00
my $epoch = $params->{epoch}
2018-08-30 23:21:20 +02:00
or
return $self->sendError( $req, '2F device "epoch" parameter is missing',
400 );
2018-04-16 22:12:51 +02:00
# Try to load 2F Device(s) from session
2018-04-16 19:55:52 +02:00
$self->logger->debug("Looking for 2F Device(s) ...");
2018-04-16 22:12:51 +02:00
my $_2fDevices;
if ( $session->data->{_2fDevices} ) {
$_2fDevices = eval {
from_json( $session->data->{_2fDevices}, { allow_nonref => 1 } );
};
if ($@) {
$self->logger->error("Corrupted session (_2fDevices) : $@");
return $self->p->sendError( $req, "Corrupted session", 500 );
}
}
else {
$self->logger->debug("No 2F Device found");
$_2fDevices = [];
}
2018-04-16 19:55:52 +02:00
# Delete 2F device
2018-04-16 22:12:51 +02:00
$self->logger->debug("Reading 2F device(s) ...");
my @keep = ();
while (@$_2fDevices) {
my $element = shift @$_2fDevices;
2018-08-30 23:21:20 +02:00
2018-04-16 22:12:51 +02:00
$self->logger->debug(
"Searching for 2F device to delete -> $type / $epoch ...");
2018-08-25 18:17:43 +02:00
if ( defined $element->{type} && defined $element->{epoch} ) {
push @keep, $element
unless ( ( $element->{type} eq $type )
and ( $element->{epoch} eq $epoch ) );
}
else {
$self->logger->error("Corrupted _2fDevice");
}
2018-04-16 22:12:51 +02:00
}
# Update session
$self->logger->debug("Saving 2F Devices ...");
$session->data->{_2fDevices} = to_json( \@keep );
$self->logger->debug("Updating session ...");
2018-03-03 09:32:01 +01:00
$session->update( \%{ $session->data } );
2018-03-11 23:33:55 +01:00
Lemonldap::NG::Handler::PSGI::Main->localUnlog( $req, $id );
if ( $session->error ) {
return $self->sendError( $req, $session->error, 200 );
}
return $self->sendJSONresponse( $req, { result => 1 } );
}
sub _session {
my ( $self, $raw, $req, $id, $skey ) = @_;
2017-01-06 10:04:00 +01:00
my ( %h, $res );
2017-01-08 09:42:19 +01:00
return $self->sendError( $req, 'Bad request', 400 ) unless ($id);
2017-01-06 10:04:00 +01:00
my $mod = $self->getMod($req)
or return $self->sendError( $req, undef, 400 );
# Try to read session
my $apacheSession = $self->getApacheSession( $mod, $id )
or return $self->sendError( $req, undef, 400 );
my %session = %{ $apacheSession->data };
unless ($raw) {
foreach my $k ( keys %session ) {
$session{$k} = '**********'
if ( $self->hAttr =~ /\b$k\b/ );
}
2017-01-06 10:04:00 +01:00
}
if ($skey) {
2017-01-10 22:43:34 +01:00
if ( $skey =~ s/^\[(.*)\]$/$1/ ) {
2019-07-02 20:03:40 +02:00
my @sk = split /,/, $skey;
2017-01-10 22:43:34 +01:00
my $res = {};
$res->{$_} = $session{$_} foreach (@sk);
return $self->sendJSONresponse( $req, $res );
}
2017-01-06 10:04:00 +01:00
return $self->sendJSONresponse( $req, $session{$skey} );
}
else {
return $self->sendJSONresponse( $req, \%session );
}
# TODO: check for utf-8 problems
}
sub session {
my $self = shift;
return $self->_session( 0, @_ );
}
sub rawSession {
my $self = shift;
return $self->_session( 1, @_ );
}
2017-01-06 10:04:00 +01:00
sub getApacheSession {
2017-02-27 20:30:43 +01:00
my ( $self, $mod, $id, $info, $force ) = @_;
2019-02-07 09:27:56 +01:00
my $apacheSession = Lemonldap::NG::Common::Session->new( {
2017-01-06 10:04:00 +01:00
storageModule => $mod->{module},
storageModuleOptions => $mod->{options},
2022-02-16 17:43:29 +01:00
cacheModule =>
2017-02-11 08:47:22 +01:00
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheModule},
2017-01-06 10:04:00 +01:00
cacheModuleOptions =>
2017-02-11 08:47:22 +01:00
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
2017-02-27 20:30:43 +01:00
id => $id,
force => $force,
2022-02-16 17:43:29 +01:00
( $id ? () : ( kind => $mod->{kind} ) ),
( $info ? ( info => $info ) : () ),
2017-01-06 10:04:00 +01:00
}
);
if ( $apacheSession->error ) {
$self->error( $apacheSession->error );
return undef;
}
2018-11-26 14:40:21 +01:00
$self->logger->debug("Get session $id from Common::Session::REST") if ($id);
2017-01-06 10:04:00 +01:00
return $apacheSession;
}
sub getMod {
my ( $self, $req ) = @_;
my ( $s, $m );
unless ( $s = $req->params('sessionType') ) {
2020-02-20 23:34:02 +01:00
$self->error( $req->error('Session type is required') );
2017-01-06 10:04:00 +01:00
return ();
}
2017-01-08 09:42:19 +01:00
unless ( $m = $self->sessionTypes->{$s} ) {
2020-02-20 23:34:02 +01:00
$self->error( $req->error('Unknown (or unconfigured) session type') );
2017-01-06 10:04:00 +01:00
return ();
}
if ( my $kind = $req->params('kind') ) {
2019-05-11 09:32:50 +02:00
$m->{kind} = $kind;
}
2017-01-06 10:04:00 +01:00
return $m;
}
sub getGlobal {
2022-02-16 17:43:29 +01:00
my ($self) = @_;
return $self->sessionTypes->{global};
}
2017-01-06 10:04:00 +01:00
1;