Improved session end flow

removed token id hint from mandatory
if client id is provided.

Change-Id: I53d9e3b1a2251a1c824d9080acea69a9e35c6577
Signed-off-by: smarcet <smarcet@gmail.com>
This commit is contained in:
smarcet 2020-04-01 22:08:06 -03:00
parent beca938384
commit c31d195527
4 changed files with 53 additions and 34 deletions

View File

@ -275,7 +275,10 @@ final class OAuth2ProviderController extends Controller
if(!$request->isValid())
{
Log::error('invalid OAuth2LogoutRequest!');
return Response::view('errors.404', [], 404);
return Response::view('errors.400', [
'error' => 'Invalid logout request.',
'error_description' => $request->getLastValidationError()
], 400);
}
if(Request::isMethod('get') )
@ -298,6 +301,7 @@ final class OAuth2ProviderController extends Controller
'id_token_hint' => $request->getIdTokenHint(),
'post_logout_redirect_uri' => $request->getPostLogoutRedirectUri(),
'state' => $request->getState(),
'client_id' => $request->getClientId(),
]);
}

View File

@ -1410,56 +1410,58 @@ final class OAuth2Protocol implements IOAuth2Protocol
if(!$this->last_request instanceof OAuth2LogoutRequest) throw new InvalidOAuth2Request;
$id_token_hint = $this->last_request->getIdTokenHint();
$client_id = null;
$user_id = null;
$jwt = BasicJWTFactory::build($id_token_hint);
if(!empty($id_token_hint)){
$jwt = BasicJWTFactory::build($id_token_hint);
if((!$jwt instanceof IJWT)) {
$this->log_service->debug_msg("OAuth2Protocol::endSession invalid id_token_hint!");
throw new InvalidOAuth2Request('invalid id_token_hint!');
if((!$jwt instanceof IJWT)) {
$this->log_service->debug_msg("OAuth2Protocol::endSession invalid id_token_hint!");
throw new InvalidOAuth2Request('invalid id_token_hint!');
}
$client_id = $jwt->getClaimSet()->getAudience()->getString();
$user_id = $jwt->getClaimSet()->getSubject();
}
if(empty($client_id)){
$client_id = $this->last_request->getClientId();
}
$client_id = $jwt->getClaimSet()->getAudience();
if(is_null($client_id)) {
$this->log_service->debug_msg("OAuth2Protocol::endSession claim aud not set on id_token_hint!");
throw new InvalidClientException('claim aud not set on id_token_hint!');
$this->log_service->debug_msg("OAuth2Protocol::endSession client_id can not be inferred.");
throw new InvalidClientException('client_id can not be inferred.');
}
$client = $this->client_repository->getClientById($client_id->getString());
$client = $this->client_repository->getClientById($client_id);
if(is_null($client)){
$this->log_service->debug_msg("OAuth2Protocol::endSession client not found!");
throw new InvalidClientException('client not found!');
throw new InvalidClientException('Client not found!');
}
$redirect_logout_uri = $this->last_request->getPostLogoutRedirectUri();
$state = $this->last_request->getState();
if(!empty($redirect_logout_uri) && !$client->isPostLogoutUriAllowed($redirect_logout_uri)) {
$this->log_service->debug_msg("OAuth2Protocol::endSession post_logout_redirect_uri not allowed!");
throw new InvalidOAuth2Request('post_logout_redirect_uri not allowed!');
}
$user_id = $jwt->getClaimSet()->getSubject();
if(!is_null($user_id)){
// try to get the user from id token ( if its set )
$user_id = $this->auth_service->unwrapUserId(intval($user_id->getString()));
$user = $this->auth_service->getUserById($user_id);
if(is_null($user_id)){
$this->log_service->debug_msg("OAuth2Protocol::endSession claim sub not set on id_token_hint!");
throw new InvalidOAuth2Request('claim sub not set on id_token_hint!');
}
$user_id = $this->auth_service->unwrapUserId(intval($user_id->getString()));
$user = $this->auth_service->getUserById($user_id);
if(is_null($user)){
$this->log_service->debug_msg("OAuth2Protocol::endSession user not found!");
throw new InvalidOAuth2Request('user not found!');
if(is_null($user)){
$this->log_service->debug_msg("OAuth2Protocol::endSession user not found!");
throw new InvalidOAuth2Request('user not found!');
}
}
$logged_user = $this->auth_service->getCurrentUser();
if(!is_null($logged_user) && $logged_user->getId() !== $user->getId()) {
if(!is_null($logged_user) && !is_null($user) && $logged_user->getId() !== $user->getId()) {
$this->log_service->debug_msg("OAuth2Protocol::endSession user does not match with current session!");
throw new InvalidOAuth2Request('user does not match with current session!');
}

View File

@ -14,7 +14,6 @@
use OAuth2\OAuth2Message;
use OAuth2\OAuth2Protocol;
/**
* OpenID Connect logout request initiated by the relying party (RP).
*
@ -38,18 +37,23 @@ final class OAuth2LogoutRequest extends OAuth2Request
public function isValid()
{
$this->last_validation_error = '';
$id_token_hint = $this->getIdTokenHint();
if(empty($id_token_hint))
{
$this->last_validation_error = 'id_token_hint not set';
return false;
}
$log_out_uri = $this->getPostLogoutRedirectUri();
$token_id = $this->getIdTokenHint();
$client_id = $this->getClientId();
// mandatory
if(empty($log_out_uri))
{
$this->last_validation_error = 'log_out_uri not set.';
return false;
}
if(empty($token_id)){
// if token id hint is not set client id is mandatory
if(empty($client_id)){
$this->last_validation_error = "client_id is not set.";
return false;
}
}
return true;
}
@ -69,6 +73,14 @@ final class OAuth2LogoutRequest extends OAuth2Request
return $this->getParam(OAuth2Protocol::OAuth2Protocol_PostLogoutRedirectUri);
}
/**
* @return string|null
*/
public function getClientId()
{
return $this->getParam(OAuth2Protocol::OAuth2Protocol_ClientId);
}
/**
* @return string|null
*/

View File

@ -26,6 +26,7 @@
<input type="hidden" name="id_token_hint" id="id_token_hint" value="{!!$id_token_hint!!}"/>
<input type="hidden" name="post_logout_redirect_uri" id="post_logout_redirect_uri" value="{!!$post_logout_redirect_uri!!}"/>
<input type="hidden" name="state" id="state" value="{!!$state!!}"/>
<input type="hidden" name="client_id" id="client_id" value="{!!$client_id!!}"/>
<div class="form-group">
{!! Form::submit('Yes ',array('id'=>'login','class'=>'btn active btn-primary')) !!}
<a class="btn btn-danger active" href="{!! URL::action('OAuth2\OAuth2ProviderController@cancelLogout') !!}">No</a>