Merge remote-tracking branch 'origin/v2.0'
This commit is contained in:
commit
ed84fdd771
|
@ -113,22 +113,19 @@ Register LL::NG to an OpenID Connect Provider
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To register LL::NG, you will need to give some information like
|
||||
application name or logo. One of mandatory information is the redirect
|
||||
URL (one or many).
|
||||
application name or logo.
|
||||
|
||||
To know this information, just take the portal URL and the Callback GET
|
||||
parameter, for example:
|
||||
You will be asked to provide a *Redirect URI* for LemonLDAP::NG, which is constructed by appending the ``openidcallback=1`` parameter to the Portal URL.
|
||||
|
||||
- http://auth.example.com/?openidcallback=1
|
||||
- http://auth.example.com/index.pl?openidcallback=1
|
||||
- http://auth.example.com/?lmAuth=oidc&openidcallback=1
|
||||
For example:
|
||||
|
||||
- https://auth.example.com/?openidcallback=1
|
||||
|
||||
|
||||
.. attention::
|
||||
|
||||
If you use the :doc:`choice backend<authchoice>`, you
|
||||
need to add the choice parameter in redirect URL or
|
||||
set SameSite cookie value to "Lax" or "None".
|
||||
If you use the :doc:`choice backend<authchoice>`,
|
||||
you need to set SameSite cookie value to "Lax" or "None".
|
||||
See :doc:`SSO cookie parameters<ssocookie>`
|
||||
|
||||
After registration, the OP must give you a client ID and a client
|
||||
|
|
|
@ -45,6 +45,7 @@ Invocation
|
|||
Options:
|
||||
|
||||
- ``-c``: job configuration file (mandatory)
|
||||
- ``-r oldkey=newkey``: rename session keys during conversion (optional, can be given multiple times)
|
||||
- ``-i``: ignore errors. By default errors will stop the script
|
||||
execution
|
||||
- ``-d``: print debugging output
|
||||
|
|
|
@ -20,7 +20,7 @@ Activation
|
|||
|
||||
To activate notifications system:
|
||||
|
||||
Go to Manager ``General Parameters`` » ``Advanced Parameters`` » ``Notifications`` » ``Activation``
|
||||
Go to Manager ``General Parameters`` » ``Plugins`` » ``Notifications`` » ``Activation``
|
||||
|
||||
or in ``lemonldap-ng.ini`` [portal] section:
|
||||
|
||||
|
@ -34,7 +34,7 @@ Explorer
|
|||
|
||||
Notifications explorer allows users to see and display theirs accepted
|
||||
notifications. Disable by default, you just have to activate it in the
|
||||
Manager (``General Parameters`` » ``Advanced Parameters`` » ``Notifications`` »
|
||||
Manager (``General Parameters`` » ``Plugins`` » ``Notifications`` »
|
||||
``Explorer``)
|
||||
|
||||
or in ``lemonldap-ng.ini`` [portal] section:
|
||||
|
@ -91,7 +91,7 @@ configuration:
|
|||
You can change default parameters using the "notificationStorage" and
|
||||
"notificationStorageOptions" parameters with the same syntax as
|
||||
configuration storage parameters. To do this in Manager, go in General
|
||||
Parameters > Advanced Parameters > Notifications.
|
||||
Parameters > Plugins > Notifications.
|
||||
|
||||
File
|
||||
^^^^
|
||||
|
@ -200,7 +200,7 @@ The notifications module uses a wildcard to manage notifications for all
|
|||
users. The default value of this wildcard is ``allusers``, but you can
|
||||
change it if ``allusers`` is a known identifier in your system.
|
||||
|
||||
To change it, go in General Parameters > Advanced Parameters >
|
||||
To change it, go in General Parameters > Plugins >
|
||||
Notifications > Wildcard for all users, and set for example
|
||||
``alluserscustom``.
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ our $specialNodeHash = {
|
|||
};
|
||||
|
||||
our $doubleHashKeys = 'issuerDBGetParameters';
|
||||
our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|(?:(?:d(?:emo|bi)|webID)E|e)xportedVar|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
|
||||
our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|(?:(?:d(?:emo|bi)|webID)E|e)xportedVar|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|OPMetaDataJ(?:SON|WKS))|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
|
||||
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
|
||||
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:(?:UserAttribut|Servic|Rul)e|AuthnLevel)|(?:ExportedVar|Macro)s)';
|
||||
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
|
||||
|
|
|
@ -13,62 +13,45 @@ use Lemonldap::NG::Common::Apache::Session;
|
|||
use Lemonldap::NG::Common::Session;
|
||||
use Config::IniFiles;
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
$Getopt::Std::STANDARD_HELP_VERSION = 1;
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
|
||||
our $VERSION = "2.0.6";
|
||||
|
||||
# Options
|
||||
# -d: debug mode
|
||||
# -c: configuration file
|
||||
# -r: configuration file
|
||||
# -i: ignore errors
|
||||
my $opts = {};
|
||||
getopts( 'dic:', $opts );
|
||||
|
||||
my $debug = $opts->{d};
|
||||
my $config_file = $opts->{c};
|
||||
my $ignore_errors = $opts->{i};
|
||||
my $nb_converted = 0;
|
||||
my $nb_error = 0;
|
||||
my $debug;
|
||||
my $config_file;
|
||||
my $ignore_errors;
|
||||
my %rename;
|
||||
my $help;
|
||||
my $nb_converted = 0;
|
||||
my $nb_error = 0;
|
||||
|
||||
sub HELP_MESSAGE {
|
||||
my $OUT = shift;
|
||||
print $OUT <<END_MESSAGE;
|
||||
|
||||
$0 [-di] -c config_file.ini
|
||||
|
||||
-d Debug mode
|
||||
-i Ignore errors
|
||||
|
||||
This script converts sessions in between the two backends specified in the configuration file
|
||||
The configuration file must contain the following (adjust to your environment):
|
||||
|
||||
[sessions_from]
|
||||
storageModule = Apache::Session::File
|
||||
storageModuleOptions = { \\
|
||||
'Directory' => '/var/lib/lemonldap-ng/sessions', \\
|
||||
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock', \\
|
||||
}
|
||||
# Only convert some session types
|
||||
# sessionKind = Persistent, SSO
|
||||
|
||||
[sessions_to]
|
||||
storageModule = Apache::Session::Browseable::Postgres
|
||||
storageModuleOptions = { \\
|
||||
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \\
|
||||
'UserName' => 'lemonldaplogin', \\
|
||||
'Password' => 'lemonldappw', \\
|
||||
'Commit' => 1, \\
|
||||
'Index' => 'ipAddr _whatToTrace user', \\
|
||||
'TableName' => 'sessions', \\
|
||||
}
|
||||
|
||||
END_MESSAGE
|
||||
}
|
||||
GetOptions(
|
||||
'help|?' => \$help,
|
||||
'debug|d' => \$debug,
|
||||
'config|c=s' => \$config_file,
|
||||
'ignore-errors|i' => \$ignore_errors,
|
||||
'rename|r=s' => \%rename,
|
||||
) or pod2usage(2);
|
||||
pod2usage(
|
||||
-exitval => 1,
|
||||
-verbose => 99,
|
||||
-sections => "SYNOPSIS|OPTIONS|CONFIGURATION FILE FORMAT"
|
||||
) if $help;
|
||||
|
||||
unless ($config_file) {
|
||||
HELP_MESSAGE( \*STDERR );
|
||||
die "You must provide the -c option";
|
||||
pod2usage(
|
||||
-exitval => 2,
|
||||
-verbose => 99,
|
||||
-message => "You must provide the -c option\n",
|
||||
-sections => "SYNOPSIS|OPTIONS|CONFIGURATION FILE FORMAT"
|
||||
);
|
||||
}
|
||||
|
||||
my $inicfg =
|
||||
|
@ -128,6 +111,28 @@ Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
|
|||
my $entry = shift;
|
||||
my $id = shift;
|
||||
|
||||
# If filtering sessionKind
|
||||
if (@sessionKindOnly) {
|
||||
|
||||
unless ( grep { $_ eq $entry->{_session_kind} } @sessionKindOnly ) {
|
||||
print "Ignoring session $id with type "
|
||||
. $entry->{_session_kind} . "\n"
|
||||
if $debug;
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
if (%rename) {
|
||||
for my $oldkey ( keys %rename ) {
|
||||
my $newkey = $rename{$oldkey};
|
||||
if ( $newkey and $entry->{$oldkey} ) {
|
||||
print "Renaming $oldkey to $newkey in session $id\n"
|
||||
if $debug;
|
||||
$entry->{$newkey} = delete $entry->{$oldkey};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "Processing session $id\n" if $debug;
|
||||
my $s = Lemonldap::NG::Common::Session->new( {
|
||||
storageModule => $backendTo->{backend},
|
||||
|
@ -138,14 +143,6 @@ Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
|
|||
}
|
||||
);
|
||||
|
||||
# If filtering sessionKind
|
||||
if (@sessionKindOnly) {
|
||||
|
||||
unless ( grep { $_ eq $entry->{_session_kind} } @sessionKindOnly ) {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $s->error ) {
|
||||
die "Error encountered on session $id" unless $ignore_errors;
|
||||
$nb_error += 1;
|
||||
|
@ -175,7 +172,7 @@ convertSessions - A tool to convert Lemonldap::NG sessions between storage backe
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
convertSession [-di] -c parameters.ini
|
||||
convertSession [-di] [-r oldkey=newkey ] -c parameters.ini
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
@ -191,6 +188,29 @@ destination backend will be kept, unless they have the same session ID as a
|
|||
session in the source backend. In that case, the source will overwrite the
|
||||
destination.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over
|
||||
|
||||
=item B<--config>,B<-c>
|
||||
|
||||
Specify configuration file
|
||||
|
||||
=item B<--debug>,B<-d>
|
||||
|
||||
Turns on debugging information
|
||||
|
||||
=item B<--ignore-errors>,B<-i>
|
||||
|
||||
Skip to the next session if converting a session fails
|
||||
|
||||
=item B<--rename oldkey=newkey>,B<-r oldkey=newkey>
|
||||
|
||||
Rename key names when migrating from one backend to the next.
|
||||
|
||||
This option can be specified multiple times
|
||||
|
||||
=back
|
||||
|
||||
=head1 CONFIGURATION FILE FORMAT
|
||||
|
||||
|
|
|
@ -2152,9 +2152,15 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
'type' => 'keyTextContainer'
|
||||
},
|
||||
'oidcOPMetaDataJSON' => {
|
||||
'keyTest' => sub {
|
||||
1;
|
||||
},
|
||||
'type' => 'file'
|
||||
},
|
||||
'oidcOPMetaDataJWKS' => {
|
||||
'keyTest' => sub {
|
||||
1;
|
||||
},
|
||||
'type' => 'file'
|
||||
},
|
||||
'oidcOPMetaDataNodes' => {
|
||||
|
@ -2447,7 +2453,7 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
'default' => {},
|
||||
'test' => {
|
||||
'keyMsgFail' => '__badMacroName__',
|
||||
'keyTest' => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
|
||||
'keyTest' => qr/^[\x21\x23-\x5B\x5D-\x7E]+$/,
|
||||
'test' => sub {
|
||||
return perlExpr(@_);
|
||||
}
|
||||
|
|
|
@ -694,9 +694,18 @@ sub scanTree {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($prefix) {
|
||||
push @cnodesKeys, $leaf;
|
||||
}
|
||||
|
||||
# issue 2439
|
||||
# FIXME: in future versions, oidcOPMetaDataJSON and samlIDPMetaDataXML shoud
|
||||
# behave the same
|
||||
if ( $leaf =~ /^oidcOPMetaData(?:JSON|JWKS)$/ ) {
|
||||
push @simpleHashKeys, $leaf;
|
||||
}
|
||||
|
||||
if ( $attr->{type} =~ /^(?:catAndAppList|\w+Container)$/ ) {
|
||||
$jleaf->{cnodes} = $prefix . $leaf;
|
||||
unless ( $prefix or $leaf =~ $reIgnoreKeys ) {
|
||||
|
|
|
@ -4162,8 +4162,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
oidcRPMetaDataOptions => { type => 'subContainer', },
|
||||
|
||||
# OpenID Connect providers
|
||||
oidcOPMetaDataJSON => { type => 'file', },
|
||||
oidcOPMetaDataJWKS => { type => 'file', },
|
||||
oidcOPMetaDataJSON => { type => 'file', keyTest => sub { 1 } },
|
||||
oidcOPMetaDataJWKS => { type => 'file', keyTest => sub { 1 } },
|
||||
oidcOPMetaDataExportedVars => {
|
||||
type => 'keyTextContainer',
|
||||
default => {
|
||||
|
@ -4348,7 +4348,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
type => 'keyTextContainer',
|
||||
help => 'idpopenidconnect.html#scope-rules',
|
||||
test => {
|
||||
keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
|
||||
# RFC6749
|
||||
keyTest => qr/^[\x21\x23-\x5B\x5D-\x7E]+$/,
|
||||
keyMsgFail => '__badMacroName__',
|
||||
test => sub { return perlExpr(@_) },
|
||||
},
|
||||
|
|
|
@ -1719,7 +1719,7 @@ sub userInfo {
|
|||
|
||||
unless ($accessTokenSession) {
|
||||
$self->userLogger->error(
|
||||
"Unable to get access token session for id $access_token");
|
||||
"Unable to validate access token $access_token");
|
||||
return $self->returnBearerError( 'invalid_request',
|
||||
'Invalid request', 401 );
|
||||
}
|
||||
|
|
|
@ -722,93 +722,100 @@ sub getAuthorizationCode {
|
|||
sub newAccessToken {
|
||||
my ( $self, $req, $rp, $scope, $sessionInfo, $info ) = @_;
|
||||
|
||||
my $at_info = {
|
||||
|
||||
scope => $scope,
|
||||
rp => $rp,
|
||||
%{$info},
|
||||
};
|
||||
|
||||
my $session = $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
"access_token",
|
||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||
|| $self->conf->{oidcServiceAccessTokenExpiration},
|
||||
{
|
||||
|
||||
scope => $scope,
|
||||
rp => $rp,
|
||||
%{$info},
|
||||
}
|
||||
$at_info,
|
||||
);
|
||||
|
||||
if ($session) {
|
||||
return $self->maybeJWT( $req, $rp, $scope, $session->id, $sessionInfo );
|
||||
if ( $self->_wantJWT($rp) ) {
|
||||
my $at_jwt =
|
||||
$self->makeJWT( $req, $rp, $scope, $session->id, $sessionInfo );
|
||||
$at_info->{sha256_hash} = $self->createHash( $at_jwt, 256 );
|
||||
$self->updateToken( $session->id, $at_info );
|
||||
return $at_jwt;
|
||||
}
|
||||
else {
|
||||
return $session->id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
sub maybeJWT {
|
||||
sub _wantJWT {
|
||||
my ( $self, $rp ) = @_;
|
||||
return $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenJWT};
|
||||
}
|
||||
|
||||
sub makeJWT {
|
||||
my ( $self, $req, $rp, $scope, $id, $sessionInfo ) = @_;
|
||||
|
||||
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenJWT} )
|
||||
{
|
||||
my $exp =
|
||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||
|| $self->conf->{oidcServiceAccessTokenExpiration};
|
||||
$exp += time;
|
||||
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
|
||||
|
||||
my $exp =
|
||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenExpiration}
|
||||
|| $self->conf->{oidcServiceAccessTokenExpiration};
|
||||
$exp += time;
|
||||
my $client_id =
|
||||
$self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
|
||||
my $access_token_payload = {
|
||||
iss => $self->iss, # Issuer Identifier
|
||||
exp => $exp, # expiration
|
||||
aud => $self->getAudiences($rp), # Audience
|
||||
client_id => $client_id, # Client ID
|
||||
iat => time, # Issued time
|
||||
jti => $id, # Access Token session ID
|
||||
scope => $scope, # Scope
|
||||
};
|
||||
|
||||
my $access_token_payload = {
|
||||
iss => $self->iss, # Issuer Identifier
|
||||
exp => $exp, # expiration
|
||||
aud => $self->getAudiences($rp), # Audience
|
||||
client_id => $client_id, # Client ID
|
||||
iat => time, # Issued time
|
||||
jti => $id, # Access Token session ID
|
||||
scope => $scope, # Scope
|
||||
};
|
||||
|
||||
my $claims;
|
||||
if ( ref($sessionInfo) eq "HASH" ) {
|
||||
$claims = $self->buildUserInfoResponseFromData( $req, $scope,
|
||||
$rp, $sessionInfo );
|
||||
}
|
||||
else {
|
||||
$claims = $self->buildUserInfoResponseFromId( $req, $scope,
|
||||
$rp, $sessionInfo );
|
||||
}
|
||||
|
||||
# Release claims, or only sub
|
||||
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenClaims} )
|
||||
{
|
||||
foreach ( keys %$claims ) {
|
||||
$access_token_payload->{$_} = $claims->{$_};
|
||||
}
|
||||
}
|
||||
else {
|
||||
$access_token_payload->{sub} = $claims->{sub};
|
||||
}
|
||||
|
||||
# Call hook to let the user modify payload
|
||||
my $h = $self->p->processHook( $req, 'oidcGenerateAccessToken',
|
||||
$access_token_payload, $rp );
|
||||
return undef if ( $h != PE_OK );
|
||||
|
||||
# Get signature algorithm
|
||||
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenSignAlg} || "RS256";
|
||||
$self->logger->debug("Access Token signature algorithm: $alg");
|
||||
|
||||
my $jwt =
|
||||
$self->createJWT( $access_token_payload, $alg, $rp, "at+JWT" );
|
||||
|
||||
return $jwt;
|
||||
my $claims;
|
||||
if ( ref($sessionInfo) eq "HASH" ) {
|
||||
$claims = $self->buildUserInfoResponseFromData( $req, $scope,
|
||||
$rp, $sessionInfo );
|
||||
}
|
||||
else {
|
||||
return $id;
|
||||
$claims =
|
||||
$self->buildUserInfoResponseFromId( $req, $scope, $rp, $sessionInfo );
|
||||
}
|
||||
|
||||
# Release claims, or only sub
|
||||
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenClaims} )
|
||||
{
|
||||
foreach ( keys %$claims ) {
|
||||
$access_token_payload->{$_} = $claims->{$_};
|
||||
}
|
||||
}
|
||||
else {
|
||||
$access_token_payload->{sub} = $claims->{sub};
|
||||
}
|
||||
|
||||
# Call hook to let the user modify payload
|
||||
my $h = $self->p->processHook( $req, 'oidcGenerateAccessToken',
|
||||
$access_token_payload, $rp );
|
||||
return undef if ( $h != PE_OK );
|
||||
|
||||
# Get signature algorithm
|
||||
my $alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenSignAlg} || "RS256";
|
||||
$self->logger->debug("Access Token signature algorithm: $alg");
|
||||
|
||||
my $jwt = $self->createJWT( $access_token_payload, $alg, $rp, "at+JWT" );
|
||||
|
||||
return $jwt;
|
||||
}
|
||||
|
||||
# Get an session from the supplied Access Token
|
||||
|
@ -820,7 +827,26 @@ sub getAccessToken {
|
|||
my $id = getAccessTokenSessionId($access_token);
|
||||
return unless $id;
|
||||
|
||||
return $self->getOpenIDConnectSession( $id, "access_token" );
|
||||
my $session = $self->getOpenIDConnectSession( $id, "access_token" );
|
||||
return undef unless $session;
|
||||
|
||||
my $stored_hash = $session->{data}->{sha256_hash};
|
||||
if ($stored_hash) {
|
||||
my $incoming_hash = $self->createHash( $access_token, 256 );
|
||||
if ( $stored_hash eq $incoming_hash ) {
|
||||
return $session;
|
||||
}
|
||||
else {
|
||||
$self->logger->error(
|
||||
"Incoming Access token hash $incoming_hash "
|
||||
. "does not match stored hash $stored_hash. "
|
||||
. "The access token might have been tampered with." );
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $session;
|
||||
}
|
||||
}
|
||||
|
||||
# Create a new Refresh Token
|
||||
|
@ -851,6 +877,11 @@ sub getRefreshToken {
|
|||
}
|
||||
|
||||
sub updateRefreshToken {
|
||||
my $self = shift;
|
||||
return $self->updateToken($@);
|
||||
}
|
||||
|
||||
sub updateToken {
|
||||
my ( $self, $id, $infos ) = @_;
|
||||
|
||||
my %storage = (
|
||||
|
|
|
@ -107,7 +107,7 @@ sub createNotification {
|
|||
sub canUpdateSfa {
|
||||
my ( $self, $req, $action ) = @_;
|
||||
my $user = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
my $msg = undef;
|
||||
my $msg = undef;
|
||||
|
||||
# Test action
|
||||
if ( $action && $action eq 'delete' ) {
|
||||
|
@ -157,7 +157,7 @@ sub canUpdateSfa {
|
|||
$msg = 'notAuthorized';
|
||||
}
|
||||
}
|
||||
$self->userLogger->info("$user is allowed to update 2FA") unless $msg;
|
||||
$self->logger->debug("$user is allowed to update 2FA") unless $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue