From 31f05b9e2d0c569fbc456d6adb822830c1acd729 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Thu, 23 Apr 2020 10:27:56 +0200 Subject: [PATCH] Make Introspection endpoint look for offline sessions (#2171) --- .../NG/Portal/Issuer/OpenIDConnect.pm | 102 +++++++++--------- .../t/32-OIDC-Offline-Session.t | 20 ++++ 2 files changed, 70 insertions(+), 52 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm index 1680e32c6..457f69cd0 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm @@ -1500,35 +1500,11 @@ sub userInfo { my $rp = $accessTokenSession->data->{rp}; my $user_session_id = $accessTokenSession->data->{user_session_id}; - my $session; - - # If using a refreshed access token - if ($user_session_id) { - - # Get user identifier - $session = $self->p->getApacheSession($user_session_id); - - unless ($session) { - $self->logger->error("Unable to find user session"); - return $self->returnBearerError( 'invalid_request', - 'Invalid request', 401 ); - } - } - else { - my $offline_session_id = - $accessTokenSession->data->{offline_session_id}; - unless ($offline_session_id) { - return $self->returnBearerError( 'invalid_request', - 'Invalid request', 401 ); - } - - $session = $self->getRefreshToken($offline_session_id); - - unless ($session) { - $self->logger->error("Unable to find refresh session"); - return $self->returnBearerError( 'invalid_request', - 'Invalid request', 401 ); - } + my $session = + $self->_getSessionFromAccessTokenData( $accessTokenSession->data ); + unless ($session) { + return $self->returnBearerError( 'invalid_request', + 'Invalid request', 401 ); } my $userinfo_response = @@ -1559,6 +1535,32 @@ sub userInfo { } } +sub _getSessionFromAccessTokenData { + my ( $self, $tokenData ) = @_; + my $session; + + # If using a refreshed access token + if ( $tokenData->{user_session_id} ) { + + # Get user identifier + $session = $self->p->getApacheSession( $tokenData->{user_session_id} ); + + unless ($session) { + $self->logger->error("Unable to find user session"); + } + } + else { + my $offline_session_id = $tokenData->{offline_session_id}; + if ($offline_session_id) { + $session = $self->getRefreshToken($offline_session_id); + unless ($session) { + $self->logger->error("Unable to find refresh session"); + } + } + } + return $session; +} + sub introspection { my ( $self, $req ) = @_; $self->logger->debug("URL detected as an OpenID Connect INTROSPECTION URL"); @@ -1586,35 +1588,31 @@ sub introspection { my $response = { active => JSON::false }; my $oidcSession = $self->getOpenIDConnectSession($token); if ($oidcSession) { - if ( my $user_session_id = $oidcSession->{data}->{user_session_id} ) { - - # Get user identifier - my $apacheSession = $self->p->getApacheSession($user_session_id); - if ($apacheSession) { + my $apacheSession = + $self->_getSessionFromAccessTokenData( $oidcSession->{data} ); + if ($apacheSession) { - $response->{active} = JSON::true; + $response->{active} = JSON::true; # The ID attribute we choose is the one of the calling webservice, # which might be different from the OIDC client the token was issued to. - my $user_id_attribute = - $self->conf->{oidcRPMetaDataOptions}->{$rp} - ->{oidcRPMetaDataOptionsUserIDAttr} - || $self->conf->{whatToTrace}; - $response->{sub} = $apacheSession->data->{$user_id_attribute}; - $response->{scope} = $oidcSession->{data}->{scope} - if $oidcSession->{data}->{scope}; - $response->{client_id} = - $self->oidcRPList->{ $oidcSession->{data}->{rp} } - ->{oidcRPMetaDataOptionsClientID} - if $oidcSession->{data}->{rp}; - $response->{iss} = $self->iss; - $response->{exp} = - $oidcSession->{data}->{_utime} + $self->conf->{timeout}; - } + my $user_id_attribute = + $self->conf->{oidcRPMetaDataOptions}->{$rp} + ->{oidcRPMetaDataOptionsUserIDAttr} + || $self->conf->{whatToTrace}; + $response->{sub} = $apacheSession->data->{$user_id_attribute}; + $response->{scope} = $oidcSession->{data}->{scope} + if $oidcSession->{data}->{scope}; + $response->{client_id} = + $self->oidcRPList->{ $oidcSession->{data}->{rp} } + ->{oidcRPMetaDataOptionsClientID} + if $oidcSession->{data}->{rp}; + $response->{iss} = $self->iss; + $response->{exp} = + $oidcSession->{data}->{_utime} + $self->conf->{timeout}; } else { - $self->logger->error( - "Could not find user session ID in access token object"); + $self->logger->error("Count not find session tied to Access Token"); } } return $self->p->sendJSONresponse( $req, $response ); diff --git a/lemonldap-ng-portal/t/32-OIDC-Offline-Session.t b/lemonldap-ng-portal/t/32-OIDC-Offline-Session.t index 778f9e649..c591e40a1 100644 --- a/lemonldap-ng-portal/t/32-OIDC-Offline-Session.t +++ b/lemonldap-ng-portal/t/32-OIDC-Offline-Session.t @@ -247,6 +247,26 @@ $json = expectJSON($res); ok( $json->{name} eq "Frédéric Accents", "Correct user info" ); count(1); +## Test introspection of refreshed token #2171 +my $req = 'client_id=rpid&client_secret=rpsecret&token=' . $access_token; +ok( + $res = $op->_post( + "/oauth2/introspect", + IO::String->new($req), + accept => 'application/json', + length => length($req), + ), + "Post new access token" +); +count(1); +$json = expectJSON($res); + +is( $json->{active}, 1 ); +is( $json->{client_id}, 'rpid' ); +is( $json->{sub}, 'french' ); + +count(3); + clean_sessions(); done_testing( count() );