Silent token renewal issue

Fixed identiy check issue

Change-Id: Icf30f27df424dd3a9b7b3477febecdf297e10b37
This commit is contained in:
Sebastian Marcet 2018-09-01 14:27:41 -03:00
parent 7b7ebe628e
commit 0050988830
7 changed files with 102 additions and 24 deletions

View File

@ -103,12 +103,7 @@ final class ResourceServerService implements IResourceServerService
);
}
if ($this->repository->getByIp($ips) != null) {
throw new InvalidResourceServer
(
sprintf('there is already another resource server with that ip (%s).', $ips)
);
}
if ($this->repository->getByFriendlyName($friendly_name) != null) {
throw new InvalidResourceServer

View File

@ -1447,11 +1447,8 @@ final class TokenService implements ITokenService
// build claim set
$epoch_now = time();
$session_id = Crypt::encrypt(Session::getId());
$encoder = new Base64UrlRepresentation();
$jti = $encoder->encode(hash('sha512', $session_id.$client_id, true));
$this->cache_service->addSingleValue($jti, $session_id, $id_token_lifetime);
$jti = $this->auth_service->generateJTI($client_id, $id_token_lifetime);
$claim_set = new JWTClaimSet
(

View File

@ -11,6 +11,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\libs\OAuth2\Exceptions\ReloadSessionException;
use Auth\Repositories\IMemberRepository;
use Auth\Repositories\IUserRepository;
use Illuminate\Support\Facades\Auth;
@ -21,6 +22,7 @@ use OAuth2\Models\IClient;
use OAuth2\Services\IPrincipalService;
use OpenId\Models\IOpenIdUser;
use OpenId\Services\IUserService;
use utils\Base64UrlRepresentation;
use Utils\Services\IAuthService;
use Utils\Services\ICacheService;
use jwe\compression_algorithms\CompressionAlgorithms_Registry;
@ -104,10 +106,12 @@ final class AuthService implements IAuthService
*/
public function login($username, $password, $remember_me)
{
Log::debug("AuthService::login");
$res = Auth::attempt(array('username' => $username, 'password' => $password), $remember_me);
if ($res)
{
Log::debug("AuthService::login: clearing principal");
$this->principal_service->clear();
$this->principal_service->register
(
@ -121,6 +125,7 @@ final class AuthService implements IAuthService
public function logout()
{
$this->invalidateSession();
Auth::logout();
$this->principal_service->clear();
Cookie::queue(IAuthService::LOGGED_RELAYING_PARTIES_COOKIE_NAME, null, $minutes = -2628000, $path = '/', $domain = null, $secure = false, $httpOnly = false);
@ -348,7 +353,7 @@ final class AuthService implements IAuthService
$rps = $zlib->uncompress($rps);
return explode('|', $rps);
}
return null;
return [];
}
/**
@ -357,16 +362,51 @@ final class AuthService implements IAuthService
*/
public function reloadSession($jti)
{
Log::debug(sprintf("AuthService::reloadSession jti %s", $jti ));
$session_id = $this->cache_service->getSingleValue($jti);
if(empty($session_id)) throw new Exception('session not found!');
Log::debug(sprintf("AuthService::reloadSession session_id %s", $session_id ));
if(empty($session_id))
throw new ReloadSessionException('session not found!');
if($this->cache_service->exists($session_id."invalid")){
// session was marked as void, check if we are authenticated
if(!Auth::check())
throw new ReloadSessionException('user not found!');
}
Session::setId(Crypt::decrypt($session_id));
Session::start();
if(!Auth::check())
{
$user_id = $this->principal_service->get()->getUserId();
Log::debug(sprintf("AuthService::reloadSession user_id %s", $user_id ));
$user = $this->getUserById($user_id);
if(is_null($user)) throw new Exception('user not found!');
if(is_null($user))
throw new ReloadSessionException('user not found!');
Auth::login($user);
}
}
/**
* @param string $client_id
* @param int $id_token_lifetime
* @return string
*/
public function generateJTI($client_id, $id_token_lifetime){
$session_id = Crypt::encrypt(Session::getId());
$encoder = new Base64UrlRepresentation();
$jti = $encoder->encode(hash('sha512', $session_id.$client_id, true));
$this->cache_service->addSingleValue($jti, $session_id, $id_token_lifetime);
return $jti;
}
public function invalidateSession(){
$session_id = Crypt::encrypt(Session::getId());
$this->cache_service->addSingleValue($session_id."invalid", $session_id);
}
}

View File

@ -0,0 +1,30 @@
<?php namespace App\libs\OAuth2\Exceptions;
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use OAuth2\Exceptions\OAuth2BaseException;
use OAuth2\OAuth2Protocol;
/**
* Class ReloadSessionException
* @package App\libs\OAuth2\Exceptions
*/
final class ReloadSessionException extends OAuth2BaseException
{
/**
* @return string
*/
public function getError()
{
return OAuth2Protocol::OAuth2Protocol_Error_Session_Cant_Reload;
}
}

View File

@ -14,6 +14,7 @@
**/
use Exception;
use Illuminate\Support\Facades\Session;
use jwe\IJWE;
use jwk\exceptions\InvalidJWKAlgorithm;
use jws\IJWS;
@ -399,7 +400,7 @@ abstract class InteractiveGrantType extends AbstractGrantType
{
$login_hint = $request->getLoginHint();
$token_hint = $request->getIdTokenHint();
$this->log_service->debug_msg("InteractiveGrantType::processUserHint");
// process login hint
$user = null;
@ -418,6 +419,7 @@ abstract class InteractiveGrantType extends AbstractGrantType
}
else if(!empty($token_hint))
{
$this->log_service->debug_msg("InteractiveGrantType::processUserHint has token hint");
$client_id = $request->getClientId();
$client = $this->client_repository->getClientById($client_id);
@ -437,6 +439,7 @@ abstract class InteractiveGrantType extends AbstractGrantType
if($jwt instanceof IJWE)
{
$this->log_service->debug_msg("InteractiveGrantType::processUserHint token hint is IJWE");
// decrypt using server key
$heuristic = new ServerEncryptionKeyFinder($this->server_private_key_repository);
$server_enc_private_key = $heuristic->find
@ -452,6 +455,7 @@ abstract class InteractiveGrantType extends AbstractGrantType
}
if($jwt instanceof IJWS)
{
$this->log_service->debug_msg("InteractiveGrantType::processUserHint token hint is IJWS");
// signed by client ?
try
{
@ -467,7 +471,7 @@ abstract class InteractiveGrantType extends AbstractGrantType
catch(RecipientKeyNotFoundException $ex)
{
// try to find the server signing key used ...
$this->log_service->debug_msg("InteractiveGrantType::processUserHint token hint is IJWS -> RecipientKeyNotFoundException");
$heuristic = new ServerSigningKeyFinder($this->server_private_key_repository);
$server_private_sig_key = $heuristic->find
(
@ -497,19 +501,20 @@ abstract class InteractiveGrantType extends AbstractGrantType
if($user)
{
$principal = $this->principal_service->get();
$this->log_service->debug_msg("InteractiveGrantType::processUserHint: checking principal");
$logged_user = $this->auth_service->getCurrentUser();
if
(
!is_null($principal) &&
!is_null($principal->getUserId()) &&
$principal->getUserId() !== $user->getId()
!is_null($logged_user) &&
$logged_user->getId() !== $user->getId()
)
{
if(!$this->canInteractWithEndUser($request))
throw new InteractionRequiredException;
$this->auth_service->logout();
if(!$this->canInteractWithEndUser($request)) {
$this->log_service->debug_msg("InteractiveGrantType::processUserHint: cant interact with user");
throw new InteractionRequiredException;
}
}
$this->security_context_service->save

View File

@ -563,6 +563,7 @@ final class OAuth2Protocol implements IOAuth2Protocol
//http://tools.ietf.org/html/rfc6750#section-3-1
const OAuth2Protocol_Error_InvalidToken = 'invalid_token';
const OAuth2Protocol_Error_InsufficientScope = 'insufficient_scope';
const OAuth2Protocol_Error_Session_Cant_Reload = 'session_cant_reload';
// http://openid.net/specs/openid-connect-core-1_0.html#AuthError
@ -1427,8 +1428,9 @@ final class OAuth2Protocol implements IOAuth2Protocol
$this->log_service->debug_msg("OAuth2Protocol::endSession user not found!");
throw new InvalidOAuth2Request('user not found!');
}
$logged_user = $this->auth_service->getCurrentUser();
if($this->principal_service->get()->getUserId() !== $user->getId()) {
if(is_null($logged_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

@ -127,4 +127,13 @@ interface IAuthService
const LOGGED_RELAYING_PARTIES_COOKIE_NAME = 'rps';
/**
* @param string $client_id
* @param int $id_token_lifetime
* @return string
*/
public function generateJTI($client_id, $id_token_lifetime);
public function invalidateSession();
}