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

302 lines
9.5 KiB
Perl
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package Lemonldap::NG::Common::Session::REST;
use strict;
use Mouse;
use Lemonldap::NG::Common::Conf::Constants;
use JSON qw(from_json to_json);
our $VERSION = '2.0.14';
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";
}
sub separator {
$_[0]->{multiValuesSeparator} || $_[0]->conf->{multiValuesSeparator};
}
sub hAttr {
$_[0]->{hiddenAttributes} || $_[0]->conf->{hiddenAttributes};
}
### SEE LEMONLDAP::NG::COMMON::SESSION FOR AVAILABLE FUNCTIONS
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 );
$self->logger->debug("Delete session : $id");
$session->remove;
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 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}
or
return $self->sendError( $req, 'OIDC Consent "RP" parameter is missing',
400 );
my $epoch = $params->{epoch}
or return $self->sendError( $req,
'OIDC Consent "epoch" parameter is missing', 400 );
# 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;
$self->logger->debug(
"Searching for OIDC Consent to delete -> $rp / $epoch ...");
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 } );
}
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
$self->logger->debug("Loading session : $id");
my $session = $self->getApacheSession( $mod, $id )
or return $self->sendError( $req, undef, 400 );
# Try to read 2F parameters
$self->logger->debug("Reading parameters ...");
my $params = $req->parameters();
my $type = $params->{type}
or return $self->sendError( $req, '2F device "type" parameter is missing',
400 );
my $epoch = $params->{epoch}
or
return $self->sendError( $req, '2F device "epoch" parameter is missing',
400 );
# Try to load 2F Device(s) from session
$self->logger->debug("Looking for 2F Device(s) ...");
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 = [];
}
# Delete 2F device
$self->logger->debug("Reading 2F device(s) ...");
my @keep = ();
while (@$_2fDevices) {
my $element = shift @$_2fDevices;
$self->logger->debug(
"Searching for 2F device to delete -> $type / $epoch ...");
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");
}
}
# Update session
$self->logger->debug("Saving 2F Devices ...");
$session->data->{_2fDevices} = 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 } );
}
sub _session {
my ( $self, $raw, $req, $id, $skey ) = @_;
my ( %h, $res );
return $self->sendError( $req, 'Bad request', 400 ) unless ($id);
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/ );
}
}
if ($skey) {
if ( $skey =~ s/^\[(.*)\]$/$1/ ) {
my @sk = split /,/, $skey;
my $res = {};
$res->{$_} = $session{$_} foreach (@sk);
return $self->sendJSONresponse( $req, $res );
}
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, @_ );
}
sub getApacheSession {
my ( $self, $mod, $id, $info, $force ) = @_;
my $apacheSession = Lemonldap::NG::Common::Session->new( {
storageModule => $mod->{module},
storageModuleOptions => $mod->{options},
cacheModule =>
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheModule},
cacheModuleOptions =>
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
id => $id,
force => $force,
( $id ? () : ( kind => $mod->{kind} ) ),
( $info ? ( info => $info ) : () ),
}
);
if ( $apacheSession->error ) {
$self->error( $apacheSession->error );
return undef;
}
$self->logger->debug("Get session $id from Common::Session::REST") if ($id);
return $apacheSession;
}
sub getMod {
my ( $self, $req ) = @_;
my ( $s, $m );
unless ( $s = $req->params('sessionType') ) {
$self->error( $req->error('Session type is required') );
return ();
}
unless ( $m = $self->sessionTypes->{$s} ) {
$self->error( $req->error('Unknown (or unconfigured) session type') );
return ();
}
if ( my $kind = $req->params('kind') ) {
$m->{kind} = $kind;
}
return $m;
}
sub getGlobal {
my ($self) = @_;
return $self->sessionTypes->{global};
}
1;