Revert "Merge branch '3497' into 'v2.0'"

This reverts commit 11895a38c9, reversing
changes made to 0fdddb9556.
merge-requests/491/merge
Christophe Maudoux 6 days ago
parent 11895a38c9
commit 35f141d704
  1. 2
      doc/sources/admin/idpopenidconnect.rst
  2. 9
      lemonldap-ng-common/lib/Lemonldap/NG/Common/JWT.pm
  3. 2
      lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm
  4. 39
      lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/OAuth2.pm
  5. 7
      lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ServiceToken.pm
  6. 54
      lemonldap-ng-handler/t/71-Lemonldap-NG-Handler-PSGI-OAuth2.t
  7. 5
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenIDConnect.pm

@ -230,7 +230,7 @@ Options
identifier (``sub``). Default value is ``whatToTrace``. identifier (``sub``). Default value is ``whatToTrace``.
- **Additional audiences** (since version ``2.0.8``): You can - **Additional audiences** (since version ``2.0.8``): You can
specify a space-separated list of audiences that will be added to the specify a space-separated list of audiences that will be added to the
ID token audiences, and possibly the access token audiences if the ID Token audiences, and possibly the access token audiences if the
access token format is JWT access token format is JWT
- **Other RP allowed to exchange access_token** (since version ``2.20.0``): - **Other RP allowed to exchange access_token** (since version ``2.20.0``):
You can specify a space-separated list of Relying-Party allowed to ask You can specify a space-separated list of Relying-Party allowed to ask

@ -8,7 +8,7 @@ our @EXPORT_OK =
use JSON; use JSON;
use MIME::Base64 qw/encode_base64 decode_base64/; use MIME::Base64 qw/encode_base64 decode_base64/;
our $VERSION = '2.22'; our $VERSION = '2.21.0';
# Gets the Access Token session ID embedded in a LLNG-emitted JWT # Gets the Access Token session ID embedded in a LLNG-emitted JWT
sub getAccessTokenSessionId { sub getAccessTokenSessionId {
@ -18,7 +18,12 @@ sub getAccessTokenSessionId {
# and use it as session ID # and use it as session ID
if ( index( $access_token, '.' ) > 0 ) { if ( index( $access_token, '.' ) > 0 ) {
my $data = getJWTPayload($access_token); my $data = getJWTPayload($access_token);
return ( $data and $data->{jti} ) ? $data->{jti} : undef; if ( $data and $data->{jti} ) {
return $data->{jti};
}
else {
return;
}
} }
# Access Token is the session ID directly # Access Token is the session ID directly

@ -142,7 +142,7 @@ sub createSession {
# Hide user credentials to the protected application # Hide user credentials to the protected application
sub hideCookie { sub hideCookie {
my ( $class, $req ) = @_; my ( $class, $req ) = @_;
$class->logger->debug('Removing Authorization header'); $class->logger->debug("removing Authorization header");
$class->unset_header_in( $req, 'Authorization' ); $class->unset_header_in( $req, 'Authorization' );
} }

@ -1,9 +1,9 @@
package Lemonldap::NG::Handler::Lib::OAuth2; package Lemonldap::NG::Handler::Lib::OAuth2;
use Lemonldap::NG::Common::JWT qw(getAccessTokenSessionId); use Lemonldap::NG::Common::JWT qw(getAccessTokenSessionId);
use strict; use strict;
our $VERSION = '2.22.1'; our $VERSION = '2.19.0';
sub retrieveSession { sub retrieveSession {
my ( $class, $req, $id ) = @_; my ( $class, $req, $id ) = @_;
@ -40,17 +40,20 @@ sub retrieveSession {
); );
unless ( $session->error ) { unless ( $session->error ) {
my $data = { %{ $session->data }, $class->_getTokenAttributes($req) }; my $data = { %{ $session->data }, $class->_getTokenAttributes($req) };
$class->data($data); $class->data($data);
$class->logger->debug("Get session $offlineId from Handler::Main::Run"); $class->logger->debug("Get session $offlineId from Handler::Main::Run");
# Verify that session is valid # Verify that session is valid
$class->logger->error( $class->logger->error(
'_utime is not defined. This should not happen. Check if it is well transmitted to handler.' "_utime is not defined. This should not happen. Check if it is well transmitted to handler"
) unless $session->data->{_utime}; ) unless $session->data->{_utime};
my $ttl = $class->tsv->{timeout} - time + $session->data->{_utime}; my $ttl = $class->tsv->{timeout} - time + $session->data->{_utime};
$class->logger->debug("Session TTL = $ttl"); $class->logger->debug( "Session TTL = " . $ttl );
if ( time - $session->data->{_utime} > $class->tsv->{timeout} ) { if ( time - $session->data->{_utime} > $class->tsv->{timeout} ) {
$class->logger->info("Session $id expired"); $class->logger->info("Session $id expired");
@ -72,6 +75,7 @@ sub retrieveSession {
sub fetchId { sub fetchId {
my ( $class, $req ) = @_; my ( $class, $req ) = @_;
my $access_token; my $access_token;
my $authorization = $req->{env}->{HTTP_AUTHORIZATION}; my $authorization = $req->{env}->{HTTP_AUTHORIZATION};
@ -96,26 +100,6 @@ sub fetchId {
return; return;
} }
# Check audiences if defined
my @aud = split /[,\s]+/, $infos->{aud};
if ( $aud[0] ) {
my $vhost = $class->resolveAlias($req);
if ( grep { $_ eq $vhost } @aud ) {
$class->logger->debug(
"$vhost found in audiences list: " . join ', ', @aud );
}
else {
$class->auditLog(
$req,
message => 'VHost not found in audiences',
code => "INVALID_ACCESS_TOKEN",
);
$class->logger->debug(
"$vhost not found in audiences list: " . join ', ', @aud );
return;
}
}
# Store scope and rpid for future session attributes # Store scope and rpid for future session attributes
if ( $infos->{rp} ) { if ( $infos->{rp} ) {
my $rp = $infos->{rp}; my $rp = $infos->{rp};
@ -195,13 +179,6 @@ sub getOIDCInfos {
return $infos; return $infos;
} }
# Hide AccesToken to the protected application
sub hideCookie {
my ( $class, $req ) = @_;
$class->logger->debug("Removing Authorization header");
$class->unset_header_in( $req, 'Authorization' );
}
## The OAuth2 handler does not redirect, we simply return a 401 with relevant ## The OAuth2 handler does not redirect, we simply return a 401 with relevant
# information as described in https://tools.ietf.org/html/rfc6750#section-3 # information as described in https://tools.ietf.org/html/rfc6750#section-3
sub goToPortal { sub goToPortal {

@ -105,11 +105,4 @@ sub fetchId {
return $_session_id; return $_session_id;
} }
# Hide ServiceToken to the protected application
sub hideCookie {
my ( $class, $req ) = @_;
$class->logger->debug('Removing X_LLNG_TOKEN header');
$class->unset_header_in( $req, 'X_LLNG_TOKEN' );
}
1; 1;

@ -4,7 +4,7 @@ BEGIN {
require 't/test-psgi-lib.pm'; require 't/test-psgi-lib.pm';
} }
my $maintests = 29; my $maintests = 25;
init( init(
'Lemonldap::NG::Handler::Server', 'Lemonldap::NG::Handler::Server',
@ -60,27 +60,7 @@ Lemonldap::NG::Common::Session->new( {
"_type" => "access_token", "_type" => "access_token",
"_utime" => ( time - 72000 + 300 ), "_utime" => ( time - 72000 + 300 ),
"rp" => "rp-example2", "rp" => "rp-example2",
"scope" => "openid email read", "scope" => "openid email read"
"aud" => "test1.example.com other.example.com"
}
}
);
# Inject an on-line access token session
Lemonldap::NG::Common::Session->new( {
hashStore => $ENV{LLNG_HASHED_SESSION_STORE},
storageModule => 'Apache::Session::File',
storageModuleOptions => { Directory => 't/sessions' },
id =>
'f1fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
force => 1,
kind => 'OIDCI',
info => {
"user_session_id" => $sessionId,
"_type" => "access_token",
"_utime" => ( time - 72000 + 300 ),
"rp" => "rp-example2",
"scope" => "openid email read",
} }
} }
); );
@ -98,8 +78,7 @@ Lemonldap::NG::Common::Session->new( {
"_type" => "refresh_token", "_type" => "refresh_token",
"_utime" => ( time - 72000 + 300 ), "_utime" => ( time - 72000 + 300 ),
"rp" => "rp-example", "rp" => "rp-example",
"scope" => "openid email read", "scope" => "openid email read"
"aud" => "test1.example.com"
} }
} }
); );
@ -163,20 +142,6 @@ like(
'Got invalid token error' 'Got invalid token error'
); );
# Request with valid Access Token
ok(
$res = $client->_get(
'/read', undef,
'test1.example.com', '',
VHOSTTYPE => 'OAuth2',
HTTP_AUTHORIZATION =>
'Bearer f1fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
),
'Valid access token without audience'
);
%h = @{ $res->[1] };
is( $res->[0], 200, "Request accepted" );
# Request with valid Access Token # Request with valid Access Token
ok( ok(
$res = $client->_get( $res = $client->_get(
@ -229,19 +194,6 @@ is( $res->[0], 200, "Request accepted" );
ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
or explain( \%h, 'Auth-User => "dwho"' ); or explain( \%h, 'Auth-User => "dwho"' );
# Request with Access token from offline session
ok(
$res = $client->_get(
'/read', undef,
'other.example.com', '',
VHOSTTYPE => 'OAuth2',
HTTP_AUTHORIZATION => 'Bearer 999888777',
),
'Invalid access token (audience)'
);
%h = @{ $res->[1] };
is( $res->[0], 401, "Access was rejected" );
# Request with Access token from offline session # Request with Access token from offline session
ok( ok(
$res = $client->_get( $res = $client->_get(

@ -1208,6 +1208,7 @@ sub newAccessToken {
my $client_id = $self->rpOptions->{$rp}->{oidcRPMetaDataOptionsClientID}; my $client_id = $self->rpOptions->{$rp}->{oidcRPMetaDataOptionsClientID};
my $at_info = { my $at_info = {
scope => $scope, scope => $scope,
rp => $rp, rp => $rp,
client_id => $client_id, client_id => $client_id,
@ -1693,7 +1694,7 @@ sub decodeJWT {
decode_jwt( token => $jwt, @$keyArg, decode_payload => 0 ) ); decode_jwt( token => $jwt, @$keyArg, decode_payload => 0 ) );
}; };
if ($@) { if ($@) {
$error = [ "Unable to verify JWT: $@", "JWT was: $jwt" ]; $error = [ "Unable to verify JWT: $@", "Jwt was: $jwt" ];
} }
else { else {
$error = []; $error = [];
@ -2426,7 +2427,7 @@ sub _createJWT {
my @keyArg; my @keyArg;
$extra_headers //= {}; $extra_headers //= {};
# Set Crypt::JWT arguments depending on "alg" # Set Cript::JWT arguments depending on "alg"
# a) "none" # a) "none"
if ( $alg eq 'none' ) { if ( $alg eq 'none' ) {
@keyArg = ( allow_none => 1 ); @keyArg = ( allow_none => 1 );

Loading…
Cancel
Save