openstackid/app/libs/oauth2/grant_types/RevokeBearerTokenGrantType.php
smarcet ebeb5d2dbf Implements: blueprint openid-oauth2-admin.backend-client-administration
[smarcet] - #5033 - Client Administration

Change-Id: If87a611f5f25646480478d7799339a6d5186a37f
2014-02-06 15:12:19 -03:00

182 lines
7.7 KiB
PHP

<?php
namespace oauth2\grant_types;
use oauth2\exceptions\InvalidOAuth2Request;
use oauth2\exceptions\UnAuthorizedClientException;
use oauth2\exceptions\BearerTokenDisclosureAttemptException;
use oauth2\exceptions\InvalidGrantTypeException;
use oauth2\OAuth2Protocol;
use oauth2\requests\OAuth2Request;
use oauth2\responses\OAuth2TokenRevocationResponse;
use oauth2\services\IClientService;
use oauth2\services\ITokenService;
use ReflectionClass;
use utils\services\ILogService;
use Exception;
/**
* Class RevokeTokenGrantType
* http://tools.ietf.org/html/rfc7009
* The OAuth 2.0 core specification [RFC6749] defines several ways for a
* client to obtain refresh and access tokens. This specification
* supplements the core specification with a mechanism to revoke both
* types of tokens. A token is a string representing an authorization
* grant issued by the resource owner to the client. A revocation
* request will invalidate the actual token and, if applicable, other
* tokens based on the same authorization grant and the authorization
* grant itself.
* From an end-user's perspective, OAuth is often used to log into a
* certain site or application. This revocation mechanism allows a
* client to invalidate its tokens if the end-user logs out, changes
* identity, or uninstalls the respective application. Notifying the
* authorization server that the token is no longer needed allows the
* authorization server to clean up data associated with that token
* (e.g., session data) and the underlying authorization grant. This
* behavior prevents a situation in which there is still a valid
* authorization grant for a particular client of which the end-user is
* not aware. This way, token revocation prevents abuse of abandoned
* tokens and facilitates a better end-user experience since invalidated
* authorization grants will no longer turn up in a list of
* authorization grants the authorization server might present to the
* end-user.
* @package oauth2\grant_types
*/
class RevokeBearerTokenGrantType extends AbstractGrantType
{
const OAuth2Protocol_GrantType_Extension_RevokeToken = 'urn:tools.ietf.org:oauth2:grant_type:revoke_bearer';
public function __construct(IClientService $client_service, ITokenService $token_service, ILogService $log_service)
{
parent::__construct($client_service, $token_service, $log_service);
}
/** Given an OAuth2Request, returns true if it can handle it, false otherwise
* @param OAuth2Request $request
* @return boolean
*/
public function canHandle(OAuth2Request $request)
{
$reflector = new ReflectionClass($request);
$class_name = $reflector->getName();
return $class_name == 'oauth2\requests\OAuth2TokenRevocationRequest' && $request->isValid();
}
/** defines entry point for first request processing
* @param OAuth2Request $request
* @throws \oauth2\exceptions\InvalidOAuth2Request
* @return mixed
*/
public function handle(OAuth2Request $request)
{
throw new InvalidOAuth2Request('not implemented!');
}
public function completeFlow(OAuth2Request $request)
{
$reflector = new ReflectionClass($request);
$class_name = $reflector->getName();
if ($class_name === 'oauth2\requests\OAuth2TokenRevocationRequest') {
parent::completeFlow($request);
$token_value = $request->getToken();
$token_hint = $request->getTokenHint();
try{
if (!is_null($token_hint) && !empty($token_hint)) {
//we have been provided with a token hint...
switch ($token_hint) {
case OAuth2Protocol::OAuth2Protocol_AccessToken:
{
//check ownership
$access_token = $this->token_service->getAccessToken($token_value);
if ($access_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('access token %s does not belongs to client id %s',$token_value, $this->current_client_id));
$this->token_service->revokeAccessToken($token_value, false);
}
break;
case OAuth2Protocol::OAuth2Protocol_RefreshToken:
{
//check ownership
$refresh_token = $this->token_service->getRefreshToken($token_value);
if ($refresh_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('refresh token %s does not belongs to client id %s',$token_value, $this->current_client_id));
$this->token_service->revokeRefreshToken($token_value, false);
}
break;
}
} else {
/*
* no token hint given :(
* if the server is unable to locate the token using
* the given hint, it MUST extend its search across all of its
* supported token types.
*/
//check and handle access token first ..
try{
//check ownership
$access_token = $this->token_service->getAccessToken($token_value);
if ($access_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('access token %s does not belongs to client id %s',$token_value, $this->current_client_id));
$this->token_service->revokeAccessToken($token_value, false);
}
catch(UnAuthorizedClientException $ex1){
$this->log_service->error($ex1);
throw $ex1;
}
catch(Exception $ex){
$this->log_service->warning($ex);
//access token was not found, check refresh token
//check ownership
$refresh_token = $this->token_service->getRefreshToken($token_value);
if ($refresh_token->getClientId() !== $this->current_client_id)
throw new BearerTokenDisclosureAttemptException($this->current_client_id,sprintf('refresh token %s does not belongs to client id %s',$token_value, $this->current_client_id));
$this->token_service->revokeRefreshToken($token_value, false);
}
}
return new OAuth2TokenRevocationResponse;
}
catch(InvalidGrantTypeException $ex){
throw new BearerTokenDisclosureAttemptException($this->current_client_id,$ex->getMessage());
}
}
throw new InvalidOAuth2Request;
}
/**
* get grant type
* @return mixed
*/
public function getType()
{
return self::OAuth2Protocol_GrantType_Extension_RevokeToken;
}
/** get grant type response type
* @return mixed
* @throws \oauth2\exceptions\InvalidOAuth2Request
*/
public function getResponseType()
{
throw new InvalidOAuth2Request('not implemented!');
}
/**
* @param OAuth2Request $request
* @return mixed|void
* @throws \oauth2\exceptions\InvalidOAuth2Request
*/
public function buildTokenRequest(OAuth2Request $request)
{
throw new InvalidOAuth2Request('not implemented!');
}
}