2017-01-06 11:57:51 +01:00
|
|
|
# Session server plugin for REST requests
|
|
|
|
#
|
|
|
|
# This plugin adds the following entry points:
|
2017-02-28 06:30:47 +01:00
|
|
|
# - Sessions backend (if restSessionServer is on)
|
2018-07-05 22:56:16 +02:00
|
|
|
# * GET /sessions/<type>/<session-id> : get session data
|
2017-01-06 11:57:51 +01:00
|
|
|
# * GET /sessions/<type>/<session-id>/<key> : get a session key value
|
2017-01-10 22:43:34 +01:00
|
|
|
# * GET /sessions/<type>/<session-id>/[k1,k2] : get some session key value
|
2017-01-06 11:57:51 +01:00
|
|
|
# * POST /sessions/<type> : create a session
|
2019-06-25 09:37:37 +02:00
|
|
|
# * POST /sessions/<type>?all=1 : get all sessions (needs a token)
|
|
|
|
# * POST /sessions/<type>?all=1&search=uid,dwho: search all sessions where uid=dwho (needs a token)
|
2017-01-06 11:57:51 +01:00
|
|
|
# * PUT /sessions/<type>/<session-id> : update some keys
|
2017-01-23 23:15:26 +01:00
|
|
|
# * DELETE /sessions/<type>/<session-id> : delete a session
|
2017-01-06 11:57:51 +01:00
|
|
|
#
|
2017-01-09 12:02:57 +01:00
|
|
|
# - Sessions for connected users (if restSessionServer is on):
|
2018-07-05 22:56:16 +02:00
|
|
|
# * GET /session/my/<type> : get session data
|
2018-06-20 21:38:26 +02:00
|
|
|
# * GET /session/my/<type>/key : get session key
|
|
|
|
# * DELETE /session/my : ask for logout
|
2017-01-08 13:13:29 +01:00
|
|
|
#
|
2017-02-28 06:30:47 +01:00
|
|
|
# - Authentication
|
2017-02-28 07:34:51 +01:00
|
|
|
# * POST /sessions/<type>/<session-id>?auth : authenticate with a fixed
|
|
|
|
# sessionId
|
2017-02-28 06:30:47 +01:00
|
|
|
# * Note that the "getCookie" method (authentification via SOAP) exists for
|
|
|
|
# REST requests directly by using '/' path : the portal recognize REST
|
|
|
|
# calls and generate JSON response instead of web page.
|
|
|
|
#
|
2017-01-08 13:13:29 +01:00
|
|
|
# - Configuration (if restConfigServer is on)
|
2017-09-05 17:08:57 +02:00
|
|
|
# * GET /config/latest : get the last config metadata
|
|
|
|
# * GET /config/<cfgNum> : get the metadata for config
|
2017-01-06 11:57:51 +01:00
|
|
|
# n° <cfgNum>
|
2017-09-05 17:08:57 +02:00
|
|
|
# * GET /config/<latest|cfgNum>/<key> : get conf key value
|
|
|
|
# * GET /config/<latest|cfgNum>?full : get the full configuration
|
2019-07-31 23:09:38 +02:00
|
|
|
# where <type> is the session type ("global" for SSO session or "persistent")
|
|
|
|
# * GET /error/<lang>/<errNum> : get <errNum> message from <lang>.json
|
|
|
|
# Return all error messages if no <errNum> specified
|
2017-01-09 12:02:57 +01:00
|
|
|
#
|
|
|
|
# - Authorizations for connected users (always):
|
2017-03-19 08:00:10 +01:00
|
|
|
# * GET /mysession/?whoami : get "my" uid
|
2017-01-09 12:02:57 +01:00
|
|
|
# * GET /mysession/?authorizationfor=<base64-encoded-url>: ask if url is
|
|
|
|
# authorizated
|
2017-03-19 08:00:10 +01:00
|
|
|
# * PUT /mysession/<type> : update some
|
2018-06-20 21:38:26 +02:00
|
|
|
# persistent data
|
|
|
|
# (restricted)
|
|
|
|
# * DELETE /mysession/<type>/key : delete key in data
|
2017-03-19 08:00:10 +01:00
|
|
|
# (restricted)
|
2017-01-06 11:57:51 +01:00
|
|
|
#
|
|
|
|
# There is no conflict with SOAP server, they can be used together
|
|
|
|
|
|
|
|
package Lemonldap::NG::Portal::Plugins::RESTServer;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use Mouse;
|
2018-07-17 22:28:39 +02:00
|
|
|
use JSON qw(from_json to_json);
|
2017-01-08 13:13:29 +01:00
|
|
|
use MIME::Base64;
|
2017-01-06 11:57:51 +01:00
|
|
|
|
2019-07-31 23:09:38 +02:00
|
|
|
our $VERSION = '2.0.6';
|
2017-01-06 11:57:51 +01:00
|
|
|
|
2017-01-08 09:42:16 +01:00
|
|
|
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
|
|
|
|
2017-03-06 16:06:49 +01:00
|
|
|
has configStorage => (
|
|
|
|
is => 'ro',
|
2017-03-27 18:51:18 +02:00
|
|
|
lazy => 1,
|
2017-03-06 16:06:49 +01:00
|
|
|
default => sub {
|
|
|
|
$_[0]->{p}->HANDLER->localConfig->{configStorage};
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-01-10 22:43:34 +01:00
|
|
|
has exportedAttr => (
|
|
|
|
is => 'rw',
|
2017-03-27 18:51:18 +02:00
|
|
|
lazy => 1,
|
2017-01-10 22:43:34 +01:00
|
|
|
default => sub {
|
|
|
|
my $conf = $_[0]->{conf};
|
|
|
|
if ( $conf->{exportedAttr} and $conf->{exportedAttr} !~ /^\s*\+/ ) {
|
|
|
|
return [ split /\s+/, $conf->{exportedAttr} ];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
my @attributes = (
|
|
|
|
'authenticationLevel', 'groups',
|
2017-03-21 21:52:40 +01:00
|
|
|
'ipAddr', '_startTime',
|
2017-01-10 22:43:34 +01:00
|
|
|
'_utime', '_lastSeen',
|
|
|
|
'_session_id',
|
|
|
|
);
|
|
|
|
if ( my $exportedAttr = $conf->{exportedAttr} ) {
|
|
|
|
$exportedAttr =~ s/^\s*\+\s+//;
|
|
|
|
@attributes = ( @attributes, split( /\s+/, $exportedAttr ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
# convert @attributes into hash to remove duplicates
|
|
|
|
my %attributes = map( { $_ => 1 } @attributes );
|
|
|
|
%attributes =
|
|
|
|
( %attributes, %{ $conf->{exportedVars} }, %{ $conf->{macros} },
|
|
|
|
);
|
|
|
|
|
|
|
|
return '[' . join( ',', keys %attributes ) . ']';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-09-18 22:40:01 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2017-01-06 11:57:51 +01:00
|
|
|
# INITIALIZATION
|
|
|
|
|
|
|
|
sub init {
|
2017-01-09 12:02:57 +01:00
|
|
|
my ($self) = @_;
|
2017-01-08 09:42:16 +01:00
|
|
|
my @parents = ('Lemonldap::NG::Portal::Main::Plugin');
|
2017-01-09 12:02:57 +01:00
|
|
|
my $add = 0;
|
2017-01-08 09:42:16 +01:00
|
|
|
if ( $self->conf->{restConfigServer} ) {
|
|
|
|
push @parents, 'Lemonldap::NG::Common::Conf::RESTServer';
|
2017-01-09 12:02:57 +01:00
|
|
|
$add++;
|
2017-01-08 09:42:16 +01:00
|
|
|
|
|
|
|
# Methods inherited from Lemonldap::NG::Common::Conf::RESTServer
|
|
|
|
$self->addUnauthRoute(
|
2017-09-05 17:08:57 +02:00
|
|
|
config => {
|
2017-01-08 09:42:16 +01:00
|
|
|
':cfgNum' => [
|
|
|
|
qw(virtualHosts samlIDPMetaDataNodes samlSPMetaDataNodes
|
|
|
|
applicationList oidcOPMetaDataNodes oidcRPMetaDataNodes
|
|
|
|
authChoiceModules grantSessionRules)
|
|
|
|
]
|
|
|
|
},
|
|
|
|
['GET'],
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
->addUnauthRoute(
|
2017-09-05 17:08:57 +02:00
|
|
|
config => { ':cfgNum' => { '*' => 'getKey' } },
|
2017-01-08 09:42:16 +01:00
|
|
|
['GET']
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
->addUnauthRoute( error => { '*' => 'getError' }, ['GET'] );
|
2017-01-08 09:42:16 +01:00
|
|
|
}
|
|
|
|
if ( $self->conf->{restSessionServer} ) {
|
|
|
|
push @parents, 'Lemonldap::NG::Common::Session::REST';
|
2017-01-09 12:02:57 +01:00
|
|
|
$add++;
|
2017-01-08 09:42:16 +01:00
|
|
|
|
|
|
|
# Methods inherited from Lemonldap::NG::Common::Session::REST
|
|
|
|
$self->addUnauthRoute(
|
2019-06-14 08:51:58 +02:00
|
|
|
sessions => {
|
|
|
|
':sessionType' => (
|
|
|
|
$self->conf->{restExportSecretKeys}
|
|
|
|
? 'rawSession'
|
|
|
|
: 'session'
|
|
|
|
)
|
|
|
|
},
|
2017-01-08 09:42:16 +01:00
|
|
|
['GET']
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
->addUnauthRoute(
|
2017-01-08 09:42:16 +01:00
|
|
|
sessions => { ':sessionType' => 'newSession' },
|
|
|
|
['POST']
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2019-07-31 23:09:38 +02:00
|
|
|
# Methods written below
|
|
|
|
->addUnauthRoute(
|
2017-01-09 07:11:28 +01:00
|
|
|
sessions => { ':sessionType' => 'updateSession' },
|
2017-01-08 09:42:16 +01:00
|
|
|
['PUT']
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
->addUnauthRoute(
|
2017-01-09 07:11:28 +01:00
|
|
|
sessions => { ':sessionType' => 'delSession' },
|
2017-01-08 09:42:16 +01:00
|
|
|
['DELETE']
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
2018-06-20 21:38:26 +02:00
|
|
|
|
2019-07-31 23:09:38 +02:00
|
|
|
->addAuthRoute(
|
2018-06-20 21:38:26 +02:00
|
|
|
session => { my => { ':sessionType' => 'getMyKey' } },
|
2017-01-09 12:02:57 +01:00
|
|
|
[ 'GET', 'POST' ]
|
2019-07-31 23:09:38 +02:00
|
|
|
);
|
2017-01-08 09:42:16 +01:00
|
|
|
}
|
2017-01-09 07:11:28 +01:00
|
|
|
|
|
|
|
# Methods always available
|
2017-01-08 09:42:16 +01:00
|
|
|
$self->addAuthRoute(
|
2017-01-08 13:13:29 +01:00
|
|
|
mysession => { '*' => 'mysession' },
|
|
|
|
[ 'GET', 'POST' ]
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
->addAuthRoute(
|
2018-06-21 13:52:18 +02:00
|
|
|
mysession => {
|
|
|
|
':sessionType' =>
|
|
|
|
{ ':key' => 'delKeyInMySession', '*' => 'delMySession' }
|
|
|
|
},
|
2018-06-20 21:38:26 +02:00
|
|
|
['DELETE']
|
2019-07-31 23:09:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
->addAuthRoute(
|
2017-03-19 08:00:10 +01:00
|
|
|
mysession => { ':sessionType' => 'updateMySession' },
|
|
|
|
['PUT']
|
2019-07-31 23:09:38 +02:00
|
|
|
);
|
2017-01-09 12:02:57 +01:00
|
|
|
extends @parents if ($add);
|
2017-01-10 17:09:28 +01:00
|
|
|
$self->setTypes( $self->conf ) if ( $self->conf->{restSessionServer} );
|
2017-01-08 09:42:16 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-01-09 07:11:28 +01:00
|
|
|
sub newSession {
|
2017-02-28 07:34:51 +01:00
|
|
|
my ( $self, $req, $id ) = @_;
|
|
|
|
|
|
|
|
# If id is defined
|
|
|
|
return $self->newAuthSession( $req, $id )
|
|
|
|
if ( $id and exists $req->parameters->{auth} );
|
2017-01-09 07:11:28 +01:00
|
|
|
my $mod = $self->getMod($req)
|
|
|
|
or return $self->p->sendError( $req, undef, 400 );
|
|
|
|
my $infos = $req->jsonBodyToObj
|
|
|
|
or return $self->p->sendError( $req, undef, 400 );
|
|
|
|
$infos->{_utime} = time();
|
|
|
|
|
2017-02-27 21:48:00 +01:00
|
|
|
my $force = 0;
|
|
|
|
if ( my $s = delete $infos->{__secret} ) {
|
2017-02-28 06:30:47 +01:00
|
|
|
my $t;
|
|
|
|
if ( $t =
|
|
|
|
$self->conf->{cipher}->decrypt($s)
|
|
|
|
and $t <= time
|
2019-06-24 23:07:34 +02:00
|
|
|
and $t > time - 15 )
|
2017-02-28 06:30:47 +01:00
|
|
|
{
|
2017-02-27 21:48:00 +01:00
|
|
|
$force = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->userLogger->error('Bad key, force denied');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-24 23:07:34 +02:00
|
|
|
if ( $req->param('all') and not $id ) {
|
|
|
|
return $self->p->sendError( $req,
|
|
|
|
'Bad key, refuse to send all sessions', 400 )
|
|
|
|
unless ($force);
|
|
|
|
my $data = $infos->{data};
|
|
|
|
my $opts = $self->conf->{globalStorageOptions} || {};
|
|
|
|
$opts->{backend} = $self->conf->{globalStorage};
|
2019-06-25 09:18:58 +02:00
|
|
|
my $sessions;
|
|
|
|
if ( my $query = $req->param('search') ) {
|
|
|
|
my ( $field, @values ) = split /,/, $query;
|
|
|
|
$sessions = Lemonldap::NG::Common::Apache::Session->searchOn(
|
|
|
|
$opts, $field,
|
|
|
|
join( ',', @values ),
|
|
|
|
( $data ? @$data : () )
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$sessions =
|
|
|
|
Lemonldap::NG::Common::Apache::Session
|
|
|
|
->get_key_from_all_sessions( $opts, $data );
|
|
|
|
}
|
2019-06-24 23:07:34 +02:00
|
|
|
return $self->p->sendJSONresponse( $req, $sessions );
|
|
|
|
}
|
2017-02-28 07:34:51 +01:00
|
|
|
my $session = $self->getApacheSession( $mod, $id, $infos, $force );
|
2017-01-09 07:11:28 +01:00
|
|
|
return $self->p->sendError( $req, 'Unable to create session', 500 )
|
|
|
|
unless ($session);
|
|
|
|
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->debug(
|
|
|
|
"SOAP request create a new session (" . $session->id . ")" );
|
2017-01-22 23:51:22 +01:00
|
|
|
|
2017-01-10 22:43:34 +01:00
|
|
|
return $self->p->sendJSONresponse( $req,
|
2017-01-22 23:51:22 +01:00
|
|
|
{ result => 1, session => $session->data } );
|
2017-01-09 07:11:28 +01:00
|
|
|
}
|
|
|
|
|
2017-02-28 07:34:51 +01:00
|
|
|
sub newAuthSession {
|
|
|
|
my ( $self, $req, $id ) = @_;
|
|
|
|
my $t;
|
2017-02-28 10:49:37 +01:00
|
|
|
unless ($t = $req->param('secret')
|
2017-02-28 07:34:51 +01:00
|
|
|
and $t = $self->conf->{cipher}->decrypt($t)
|
|
|
|
and $t <= time
|
|
|
|
and $t > time - 30 )
|
|
|
|
{
|
|
|
|
return $self->p->sendError( $req, 'Bad secret', 403 );
|
|
|
|
}
|
|
|
|
$req->{id} = $id;
|
|
|
|
$req->{force} = 1;
|
2017-02-28 10:49:37 +01:00
|
|
|
$req->user( $req->param('user') );
|
2018-07-05 22:56:16 +02:00
|
|
|
$req->data->{password} = $req->param('password');
|
2019-02-07 09:27:56 +01:00
|
|
|
$req->steps( [
|
2017-02-28 10:49:37 +01:00
|
|
|
@{ $self->p->beforeAuth },
|
|
|
|
qw(getUser authenticate setAuthSessionInfo),
|
2018-07-05 22:56:16 +02:00
|
|
|
@{ $self->p->betweenAuthAndData },
|
|
|
|
$self->p->sessionData,
|
|
|
|
@{ $self->p->afterData },
|
2018-09-05 09:19:01 +02:00
|
|
|
$self->p->validSession,
|
|
|
|
@{ $self->p->endAuth },
|
2017-02-28 07:34:51 +01:00
|
|
|
]
|
|
|
|
);
|
|
|
|
$req->{error} = $self->p->process($req);
|
|
|
|
$self->logger->debug(
|
|
|
|
"REST authentication result for $req->{user}: code $req->{error}");
|
2017-02-28 10:49:37 +01:00
|
|
|
|
2017-02-28 07:34:51 +01:00
|
|
|
if ( $req->error > 0 ) {
|
|
|
|
return $self->p->sendError( $req, 'Bad credentials', 401 );
|
|
|
|
}
|
|
|
|
return $self->session( $req, $id );
|
|
|
|
}
|
|
|
|
|
2017-01-09 07:11:28 +01:00
|
|
|
sub updateSession {
|
|
|
|
my ( $self, $req, $id ) = @_;
|
2017-02-20 22:00:05 +01:00
|
|
|
$self->logger->debug("REST request to update session $id");
|
2017-01-09 07:11:28 +01:00
|
|
|
my $mod = $self->getMod($req)
|
|
|
|
or return $self->p->sendError( $req, undef, 400 );
|
|
|
|
return $self->p->sendError( $req, 'ID is required', 400 ) unless ($id);
|
|
|
|
|
|
|
|
# Get new info
|
|
|
|
my $infos = $req->jsonBodyToObj
|
|
|
|
or return $self->p->sendError( $req, undef, 400 );
|
|
|
|
|
2017-02-27 21:48:00 +01:00
|
|
|
# Get secret if given
|
|
|
|
my $force = 0;
|
|
|
|
if ( my $s = delete $infos->{__secret} ) {
|
2017-02-28 06:30:47 +01:00
|
|
|
my $t;
|
|
|
|
if ( $t =
|
|
|
|
$self->conf->{cipher}->decrypt($s)
|
|
|
|
and $t <= time
|
|
|
|
and $t > time - 30 )
|
|
|
|
{
|
2017-02-27 21:48:00 +01:00
|
|
|
$force = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->userLogger->error('Bad key, force denied');
|
|
|
|
}
|
|
|
|
}
|
2017-02-28 06:30:47 +01:00
|
|
|
|
2017-02-20 22:00:05 +01:00
|
|
|
# Get session and store info
|
2017-02-27 21:48:00 +01:00
|
|
|
my $session = $self->getApacheSession( $mod, $id, $infos, $force )
|
2017-02-20 22:00:05 +01:00
|
|
|
or return $self->p->sendError( $req, 'Session id does not exists', 400 );
|
|
|
|
|
2017-01-09 07:11:28 +01:00
|
|
|
return $self->p->sendJSONresponse( $req, { result => 1 } );
|
2017-01-08 09:42:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub delSession {
|
2017-01-09 07:11:28 +01:00
|
|
|
my ( $self, $req, $id ) = @_;
|
|
|
|
my $mod = $self->getMod($req)
|
|
|
|
or return $self->p->sendError( $req, undef, 400 );
|
|
|
|
return $self->p->sendError( $req, 'ID is required', 400 ) unless ($id);
|
|
|
|
|
|
|
|
# Get session
|
|
|
|
my $session = $self->getApacheSession( $mod, $id )
|
|
|
|
or return $self->p->sendError( $req, 'Session id does not exists', 400 );
|
|
|
|
|
|
|
|
# Delete it
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->debug("REST request to delete session $id");
|
2017-01-10 22:43:34 +01:00
|
|
|
my $res = $self->p->_deleteSession( $req, $session );
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->debug(" Result is $res");
|
2017-01-09 07:11:28 +01:00
|
|
|
return $self->p->sendJSONresponse( $req, { result => $res } );
|
2017-01-08 09:42:16 +01:00
|
|
|
}
|
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
sub delMySession {
|
|
|
|
my ( $self, $req, $id ) = @_;
|
2017-01-10 17:09:28 +01:00
|
|
|
return $self->delSession( $req, $req->userData->{_session_id} );
|
2017-01-09 12:02:57 +01:00
|
|
|
}
|
|
|
|
|
2017-01-08 13:13:29 +01:00
|
|
|
sub mysession {
|
2017-01-08 09:42:16 +01:00
|
|
|
my ( $self, $req ) = @_;
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
# 1. whoami
|
|
|
|
if ( defined $req->param('whoami') ) {
|
2017-01-09 13:55:04 +01:00
|
|
|
return $self->p->sendJSONresponse( $req,
|
2017-01-10 17:09:28 +01:00
|
|
|
{ result => $req->userData->{ $self->conf->{whatToTrace} } } );
|
2017-01-09 12:02:57 +01:00
|
|
|
}
|
|
|
|
|
2017-09-18 22:40:01 +02:00
|
|
|
if ( defined $req->param('gettoken') ) {
|
|
|
|
return $self->p->sendJSONresponse( $req,
|
|
|
|
{ token => $self->ott->createToken() } );
|
|
|
|
}
|
|
|
|
|
2017-01-08 13:13:29 +01:00
|
|
|
# Verify authorizationfor arg
|
2017-01-09 12:02:57 +01:00
|
|
|
elsif ( my $url = $req->param('authorizationfor') ) {
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
# Verify that value is base64 encoded
|
|
|
|
return $self->p->sendError( $req, "Value must be in BASE64", 400 )
|
|
|
|
if ( $url =~ m#[^A-Za-z0-9\+/=]# );
|
|
|
|
$req->urldc( decode_base64($url) );
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
# Check for XSS problems
|
|
|
|
return $self->p->sendError( $req, 'XSS attack detected', 400 )
|
|
|
|
if ( $self->p->checkXSSAttack( 'authorizationfor', $req->urldc ) );
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
# Split URL
|
2017-03-06 17:43:06 +01:00
|
|
|
my ( $host, $uri ) = ( $req->urldc =~ m#^https?://([^/]+)(/.*)?$# );
|
|
|
|
$uri ||= '/';
|
2017-03-19 08:00:10 +01:00
|
|
|
return $self->p->sendError( $req, "Bad URL $req->{urldc}", 400 )
|
|
|
|
unless ($host);
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->debug("Looking for authorization for $url");
|
2017-01-08 13:13:29 +01:00
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
# Now check for authorization
|
|
|
|
my $res =
|
2017-03-28 23:07:49 +02:00
|
|
|
$self->p->HANDLER->grant( $req, $req->userData, $uri, undef, $host );
|
2017-02-15 07:41:50 +01:00
|
|
|
$self->logger->debug(" Result is $res");
|
2017-01-09 12:02:57 +01:00
|
|
|
return $self->p->sendJSONresponse( $req, { result => $res } );
|
|
|
|
}
|
2018-06-21 13:52:18 +02:00
|
|
|
return $self->p->sendError( $req,
|
|
|
|
'whoami or authorizationfor is required', 400 );
|
2017-01-08 13:13:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub getMyKey {
|
|
|
|
my ( $self, $req, $key ) = @_;
|
2018-07-17 22:38:01 +02:00
|
|
|
$key ||= '';
|
|
|
|
$self->logger->debug("Request to get personal session info -> Key : $key");
|
2017-01-10 22:43:34 +01:00
|
|
|
return $self->session(
|
|
|
|
$req,
|
|
|
|
$req->userData->{_session_id},
|
|
|
|
$key || $self->exportedAttr
|
|
|
|
);
|
2017-01-06 11:57:51 +01:00
|
|
|
}
|
|
|
|
|
2017-03-19 08:00:10 +01:00
|
|
|
sub updateMySession {
|
|
|
|
my ( $self, $req ) = @_;
|
|
|
|
my $res = 0;
|
|
|
|
my $mKeys = [];
|
2017-09-18 22:40:01 +02:00
|
|
|
if ( my $token = $req->param('token') ) {
|
|
|
|
if ( $self->ott->getToken($token) ) {
|
|
|
|
if ( $req->param('sessionType') eq 'persistent' ) {
|
2018-06-21 17:22:58 +02:00
|
|
|
foreach
|
|
|
|
my $key ( @{ $self->conf->{mySessionAuthorizedRWKeys} } )
|
|
|
|
{
|
2018-06-20 21:38:26 +02:00
|
|
|
my $v;
|
|
|
|
if ( $key =~ /\*/ ) {
|
|
|
|
$key =~ s/\*/\.\*/g;
|
|
|
|
if ( my ($k) = grep( /$key/, $req->params ) ) {
|
|
|
|
$v = $req->param($k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$v = $req->param($key);
|
|
|
|
}
|
2017-09-18 22:40:01 +02:00
|
|
|
if ( defined $v ) {
|
|
|
|
$res++;
|
|
|
|
push @$mKeys, $key;
|
|
|
|
$self->p->updatePersistentSession( $req,
|
|
|
|
{ $key => $v } );
|
2018-07-16 22:56:43 +02:00
|
|
|
$self->logger->debug(
|
|
|
|
"Request to update session -> Key : $key");
|
2017-09-18 22:40:01 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-19 08:00:10 +01:00
|
|
|
}
|
|
|
|
}
|
2017-09-18 22:40:01 +02:00
|
|
|
else {
|
|
|
|
$self->logger->error('Update session request with invalid token');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->logger->error('Update session request without token');
|
2017-03-19 08:00:10 +01:00
|
|
|
}
|
|
|
|
unless ($res) {
|
|
|
|
return $self->p->sendError( $req, 'Modification refused', 403 );
|
|
|
|
}
|
|
|
|
return $self->p->sendJSONresponse( $req,
|
|
|
|
{ result => 1, count => $res, modifiedKeys => $mKeys } );
|
|
|
|
}
|
|
|
|
|
2018-06-20 21:38:26 +02:00
|
|
|
sub delKeyInMySession {
|
|
|
|
my ( $self, $req ) = @_;
|
2018-07-17 18:18:50 +02:00
|
|
|
my $res = 0;
|
|
|
|
my $mKeys = [];
|
|
|
|
my $dkey = $req->param('key');
|
|
|
|
my $sub = $req->param('sub');
|
2018-06-20 21:38:26 +02:00
|
|
|
if ( my $token = $req->param('token') ) {
|
|
|
|
if ( $self->ott->getToken($token) ) {
|
|
|
|
if ( $req->param('sessionType') eq 'persistent' ) {
|
2018-06-21 17:22:58 +02:00
|
|
|
foreach
|
|
|
|
my $key ( @{ $self->conf->{mySessionAuthorizedRWKeys} } )
|
|
|
|
{
|
2018-06-20 21:38:26 +02:00
|
|
|
if ( $key =~ /\*/ ) {
|
|
|
|
$key =~ s/\*/\.\*/g;
|
2018-06-21 17:15:53 +02:00
|
|
|
if ( $dkey =~ /^$key$/ ) {
|
2018-06-20 21:38:26 +02:00
|
|
|
$res++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif ( $dkey eq $key ) {
|
|
|
|
$res++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($res) {
|
2018-07-16 22:56:43 +02:00
|
|
|
if ( $dkey !~ /^_oidcConsents$/ ) {
|
|
|
|
$self->p->updatePersistentSession( $req,
|
|
|
|
{ $dkey => undef } );
|
|
|
|
$self->logger->debug(
|
|
|
|
"Update session -> delete Key : $dkey");
|
|
|
|
}
|
2018-07-17 18:15:17 +02:00
|
|
|
elsif ( $dkey =~ /^_oidcConsents$/ and defined $sub ) {
|
2018-07-17 22:17:45 +02:00
|
|
|
|
|
|
|
# Read existing oidcConsents
|
|
|
|
$self->logger->debug("Looking for OIDC Consents ...");
|
|
|
|
my $_oidcConsents;
|
|
|
|
if ( $req->userData->{_oidcConsents} ) {
|
|
|
|
$_oidcConsents = eval {
|
|
|
|
from_json( $req->userData->{_oidcConsents},
|
|
|
|
{ allow_nonref => 1 } );
|
|
|
|
};
|
|
|
|
if ($@) {
|
|
|
|
$self->logger->error(
|
|
|
|
"Corrupted session (_oidcConsents): $@");
|
|
|
|
return $self->p->sendError( $req,
|
|
|
|
"Corrupted session", 500 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-07-17 22:38:01 +02:00
|
|
|
$self->logger->debug("No OIDC Consent found");
|
2018-07-17 22:17:45 +02:00
|
|
|
$_oidcConsents = [];
|
|
|
|
}
|
|
|
|
my @keep = ();
|
|
|
|
while (@$_oidcConsents) {
|
|
|
|
my $element = shift @$_oidcConsents;
|
|
|
|
$self->logger->debug(
|
|
|
|
"Looking for OIDC Consent to delete ...");
|
|
|
|
push @keep, $element
|
|
|
|
unless ( $element->{rp} eq $sub );
|
|
|
|
}
|
|
|
|
$self->p->updatePersistentSession( $req,
|
|
|
|
{ _oidcConsents => to_json( \@keep ) } );
|
2018-07-16 22:56:43 +02:00
|
|
|
$self->logger->debug(
|
2018-07-17 22:17:45 +02:00
|
|
|
"Update session -> delete Key : $dkey with Sub : $sub"
|
2018-07-16 22:56:43 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->logger->error(
|
2018-07-17 22:17:45 +02:00
|
|
|
'Update session request with invalid Key or Sub');
|
2018-07-16 22:56:43 +02:00
|
|
|
}
|
2018-06-20 21:38:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->logger->error('Update session request with invalid token');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->logger->error('Update session request without token');
|
|
|
|
}
|
|
|
|
unless ($res) {
|
|
|
|
return $self->p->sendError( $req, 'Modification refused', 403 );
|
|
|
|
}
|
|
|
|
return $self->p->sendJSONresponse( $req,
|
|
|
|
{ result => 1, count => $res, modifiedKeys => $dkey } );
|
|
|
|
}
|
|
|
|
|
2019-07-31 23:09:38 +02:00
|
|
|
sub getError {
|
|
|
|
my ( $self, $req, $lang, $errNum ) = @_;
|
|
|
|
my $json;
|
|
|
|
my $langsDir =
|
|
|
|
$self->conf->{templateDir}
|
|
|
|
. '/../htdocs'
|
|
|
|
. $self->conf->{staticPrefix}
|
|
|
|
. '/languages';
|
|
|
|
$lang ||= 'en';
|
2019-08-01 11:59:02 +02:00
|
|
|
|
|
|
|
$errNum
|
|
|
|
? $self->logger->debug("GET error: $errNum message from lang: $lang")
|
|
|
|
: $self->logger->debug("GET ALL error messages from lang: $lang");
|
2019-07-31 23:09:38 +02:00
|
|
|
|
|
|
|
if ( open my $file, "<", $langsDir . "/$lang.json" ) {
|
|
|
|
local $/ = undef;
|
|
|
|
$json = from_json(<$file>);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->logger->error("Unable to read $langsDir/$lang.json");
|
|
|
|
return $self->p->sendJSONresponse( $req,
|
2019-08-01 21:55:03 +02:00
|
|
|
{ result => 0, lang => $lang, error => 'Unable to read language file' } );
|
2019-07-31 23:09:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
%$json = map { $_ =~ /^PE\d+$/ ? ( $_ => $json->{$_} ) : () }
|
|
|
|
keys %$json
|
|
|
|
unless ($errNum);
|
|
|
|
|
|
|
|
return $self->p->sendJSONresponse(
|
|
|
|
$req,
|
|
|
|
{
|
|
|
|
result => 1,
|
|
|
|
lang => $lang,
|
|
|
|
errorNum => $errNum ? $errNum : 'all',
|
|
|
|
errorMsg => (
|
|
|
|
$errNum
|
|
|
|
? $json->{"PE$errNum"}
|
|
|
|
: $json
|
|
|
|
)
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-01-09 12:02:57 +01:00
|
|
|
1;
|