mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-10 19:43:16 +00:00
Refactor lib/classes/API/OAuth2/Adapter.php to use api entities
This commit is contained in:
@@ -13,6 +13,9 @@ use Alchemy\Phrasea\Application;
|
|||||||
|
|
||||||
use Alchemy\Phrasea\Authentication\Exception\AccountLockedException;
|
use Alchemy\Phrasea\Authentication\Exception\AccountLockedException;
|
||||||
use Alchemy\Phrasea\Authentication\Exception\RequireCaptchaException;
|
use Alchemy\Phrasea\Authentication\Exception\RequireCaptchaException;
|
||||||
|
use Alchemy\Phrasea\Exception\RuntimeException;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\Session;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class API_OAuth2_Adapter extends OAuth2
|
class API_OAuth2_Adapter extends OAuth2
|
||||||
@@ -24,7 +27,7 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @var API_OAuth2_Application
|
* @var ApiApplication
|
||||||
*/
|
*/
|
||||||
protected $client;
|
protected $client;
|
||||||
|
|
||||||
@@ -84,10 +87,8 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
public function __construct(Application $app)
|
public function __construct(Application $app)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->params = [];
|
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
|
$this->params = [];
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,7 +102,7 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return API_OAuth2_Application
|
* @return ApiApplication
|
||||||
*/
|
*/
|
||||||
public function getClient()
|
public function getClient()
|
||||||
{
|
{
|
||||||
@@ -125,11 +126,7 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
return $this->token;
|
return $this->token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function setClient(ApiApplication $client)
|
||||||
*
|
|
||||||
* @param API_OAuth2_Application $client
|
|
||||||
*/
|
|
||||||
public function setClient(API_OAuth2_Application $client)
|
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
|
|
||||||
@@ -164,91 +161,85 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Implements OAuth2::checkClientCredentials().
|
* Implements OAuth2::checkClientCredentials().
|
||||||
*
|
*
|
||||||
* @param string $client_id
|
* @param string $clientId
|
||||||
* @param string $client_secret
|
* @param string $clientSecret
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
protected function checkClientCredentials($client_id, $client_secret = NULL)
|
protected function checkClientCredentials($clientId, $clientSecret = null)
|
||||||
{
|
{
|
||||||
try {
|
if (null === $application = $this->app['repo.api-applications']->findByClientId($clientId)) {
|
||||||
$application = API_OAuth2_Application::load_from_client_id($this->app, $client_id);
|
return false;
|
||||||
|
|
||||||
if ($client_secret === NULL) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($application->get_client_secret() === $client_secret);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (null === $clientSecret) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $application->getClientSecret() === $clientSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Implements OAuth2::getRedirectUri().
|
* Implements OAuth2::getRedirectUri().
|
||||||
*
|
*
|
||||||
* @param string $client_id
|
* @param $clientId
|
||||||
* @return string
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
protected function getRedirectUri($client_id)
|
protected function getRedirectUri($clientId)
|
||||||
{
|
{
|
||||||
$application = API_OAuth2_Application::load_from_client_id($this->app, $client_id);
|
if (null === $application = $this->app['repo.api-applications']->findByClientId($clientId)) {
|
||||||
|
throw new RuntimeException(sprintf('Application with client id %s could not be found', $clientId));
|
||||||
|
}
|
||||||
|
|
||||||
return $application->get_redirect_uri();
|
return $application->getRedirectUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Implements OAuth2::getAccessToken().
|
* Implements OAuth2::getAccessToken().
|
||||||
*
|
*
|
||||||
* @param string $oauth_token
|
* @param string $oauthToken
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getAccessToken($oauth_token)
|
protected function getAccessToken($oauthToken)
|
||||||
{
|
{
|
||||||
$result = null;
|
if (null === $token = $this->app['repo.api-oauth-tokens']->find($oauthToken)) {
|
||||||
|
return null;
|
||||||
try {
|
|
||||||
$token = API_OAuth2_Token::load_by_oauth_token($this->app, $oauth_token);
|
|
||||||
|
|
||||||
$result = [
|
|
||||||
'scope' => $token->get_scope()
|
|
||||||
, 'expires' => $token->get_expires()
|
|
||||||
, 'client_id' => $token->get_account()->get_application()->get_client_id()
|
|
||||||
, 'session_id' => $token->get_session_id()
|
|
||||||
, 'revoked' => ($token->get_account()->is_revoked() ? '1' : '0')
|
|
||||||
, 'usr_id' => $token->get_account()->get_user()->getId()
|
|
||||||
, 'oauth_token' => $token->get_value()
|
|
||||||
];
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return [
|
||||||
|
'scope' => $token->getScope(),
|
||||||
|
'expires' => $token->getExpire()->getTimestamp(),
|
||||||
|
'client_id' => $token->getAccount()->getApplication()->getClientId(),
|
||||||
|
'session_id' => null === $token->getSession() ? null : $token->getSession()->getId(),
|
||||||
|
'revoked' => (int) $token->getAccount()->isRevoked(),
|
||||||
|
'usr_id' => $token->getAccount()->getUser()->getId(),
|
||||||
|
'oauth_token' => $token->getOauthToken(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Implements OAuth2::setAccessToken().
|
* Implements OAuth2::setAccessToken().
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
*
|
||||||
* @param type $oauth_token
|
* @param $oauthToken
|
||||||
* @param type $account_id
|
* @param $accountId
|
||||||
* @param type $expires
|
* @param $expires
|
||||||
* @param string $scope
|
* @param null $scope
|
||||||
* @return API_OAuth2_Adapter
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
protected function setAccessToken($oauth_token, $account_id, $expires, $scope = NULL)
|
protected function setAccessToken($oauthToken, $accountId, $expires, $scope = null)
|
||||||
{
|
{
|
||||||
$account = new API_OAuth2_Account($this->app, $account_id);
|
if (null === $account = $this->app['repo.api-accounts']->find($accountId)) {
|
||||||
$token = API_OAuth2_Token::create($this->app['phraseanet.appbox'], $account, $this->app['random.medium'], $scope);
|
throw new RuntimeException(sprintf('Account with id %s is not valid', $accountId));
|
||||||
$token->set_value($oauth_token)->set_expires($expires);
|
}
|
||||||
|
|
||||||
|
$token = $this->app['manipulator.api-oauth-token']->create($account, null, \DateTime::createFromFormat('U', $expires), $scope);
|
||||||
|
$this->app['manipulator.api-oauth-token']->setOauthToken($token, $oauthToken);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -279,87 +270,106 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Overrides OAuth2::getAuthCode().
|
* Overrides OAuth2::getAuthCode().
|
||||||
*
|
*
|
||||||
* @return array
|
* @param $code
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
protected function getAuthCode($code)
|
protected function getAuthCode($code)
|
||||||
{
|
{
|
||||||
try {
|
if (null === $code = $this->app['repo.api-oauth-codes']->find($code)) {
|
||||||
$code = new API_OAuth2_AuthCode($this->app, $code);
|
return null;
|
||||||
|
|
||||||
return [
|
|
||||||
'redirect_uri' => $code->get_redirect_uri()
|
|
||||||
, 'client_id' => $code->get_account()->get_application()->get_client_id()
|
|
||||||
, 'expires' => $code->get_expires()
|
|
||||||
, 'account_id' => $code->get_account()->get_id()
|
|
||||||
];
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return [
|
||||||
|
'redirect_uri' => $code->getRedirectUri(),
|
||||||
|
'client_id' => $code->getAccount()->getApplication()->getClientId(),
|
||||||
|
'expires' => $code->getExpires()->getTimestamp(),
|
||||||
|
'account_id' => $code->getAccount()->getId(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Overrides OAuth2::setAuthCode().
|
* Overrides OAuth2::setAuthCode().
|
||||||
|
*
|
||||||
|
* @param $oauthCode
|
||||||
|
* @param $accountId
|
||||||
|
* @param $redirectUri
|
||||||
|
* @param $expires
|
||||||
|
* @param null $scope
|
||||||
*
|
*
|
||||||
* @param string $code
|
* @return $this|void
|
||||||
* @param int $account_id
|
* @throws RuntimeException
|
||||||
* @param string $redirect_uri
|
|
||||||
* @param string $expires
|
|
||||||
* @param string $scope
|
|
||||||
* @return API_OAuth2_Adapter
|
|
||||||
*/
|
*/
|
||||||
protected function setAuthCode($code, $account_id, $redirect_uri, $expires, $scope = NULL)
|
protected function setAuthCode($oauthCode, $accountId, $redirectUri, $expires, $scope = null)
|
||||||
{
|
{
|
||||||
$account = new API_OAuth2_Account($this->app, $account_id);
|
if (null === $account = $this->app['repo.api-accounts']->find($accountId)) {
|
||||||
$code = API_OAuth2_AuthCode::create($this->app, $account, $code, $expires);
|
throw new RuntimeException(sprintf('Account with id %s is not valid', $accountId));
|
||||||
$code->set_redirect_uri($redirect_uri)->set_scope($scope);
|
}
|
||||||
|
|
||||||
|
$code = $this->app['manipulator.api-oauth-code']->create($account, \DateTime::createFromFormat('U', $expires), $scope);
|
||||||
|
$this->app['manipulator.api-oauth-code']->setCode($code, $oauthCode);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides OAuth2::setRefreshToken().
|
* Overrides OAuth2::setRefreshToken().
|
||||||
|
*
|
||||||
|
* @param $refreshToken
|
||||||
|
* @param $accountId
|
||||||
|
* @param $expires
|
||||||
|
* @param null $scope
|
||||||
|
*
|
||||||
|
* @return $this|void
|
||||||
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
protected function setRefreshToken($refresh_token, $account_id, $expires, $scope = NULL)
|
protected function setRefreshToken($refreshToken, $accountId, $expires, $scope = null)
|
||||||
{
|
{
|
||||||
$account = new API_OAuth2_Account($this->app, $account_id);
|
if (null === $account = $this->app['repo.api-accounts']->find($accountId)) {
|
||||||
API_OAuth2_RefreshToken::create($this->app, $account, $expires, $refresh_token, $scope);
|
throw new RuntimeException(sprintf('Account with id %s is not valid', $accountId));
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $this->app['manipulator.api-oauth-refresh-token']->create($account, \DateTime::createFromFormat('U', $expires), $scope);
|
||||||
|
$this->app['manipulator.api-oauth-refresh-token']->setRefreshToken($token, $refreshToken);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides OAuth2::getRefreshToken().
|
* Overrides OAuth2::getRefreshToken().
|
||||||
|
*
|
||||||
|
* @param $refreshToken
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
protected function getRefreshToken($refresh_token)
|
protected function getRefreshToken($refreshToken)
|
||||||
{
|
{
|
||||||
try {
|
if (null === $token = $this->app['repo.api-oauth-refresh-token']->find($refreshToken)) {
|
||||||
$token = new API_OAuth2_RefreshToken($this->app, $refresh_token);
|
return null;
|
||||||
|
|
||||||
return [
|
|
||||||
'token' => $token->get_value()
|
|
||||||
, 'expires' => $token->get_expires()->format('U')
|
|
||||||
, 'client_id' => $token->get_account()->get_application()->get_client_id()
|
|
||||||
];
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return [
|
||||||
|
'token' => $token->getRefreshToken(),
|
||||||
|
'expires' => $token->getExpires()->getTimestamp(),
|
||||||
|
'client_id' => $token->getAccount()->getApplication()->getClientId()
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides OAuth2::unsetRefreshToken().
|
* Overrides OAuth2::unsetRefreshToken().
|
||||||
|
*
|
||||||
|
* @param $refreshToken
|
||||||
|
*
|
||||||
|
* @return $this|void
|
||||||
*/
|
*/
|
||||||
protected function unsetRefreshToken($refresh_token)
|
protected function unsetRefreshToken($refreshToken)
|
||||||
{
|
{
|
||||||
$token = new API_OAuth2_RefreshToken($this->app, $refresh_token);
|
if (null !== $token = $this->app['repo.api-oauth-refresh-token']->find($refreshToken)) {
|
||||||
$token->delete();
|
$this->app['manipulator.api-oauth-refresh-token']->delete($token);
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -371,22 +381,21 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
*/
|
*/
|
||||||
public function getAuthorizationRequestParameters(Request $request)
|
public function getAuthorizationRequestParameters(Request $request)
|
||||||
{
|
{
|
||||||
|
$data = [
|
||||||
$datas = [
|
'response_type' => $request->get('response_type', false),
|
||||||
'response_type' => $request->get('response_type', false)
|
'client_id' => $request->get('client_id', false),
|
||||||
, 'client_id' => $request->get('client_id', false)
|
'redirect_uri' => $request->get('redirect_uri', false),
|
||||||
, 'redirect_uri' => $request->get('redirect_uri', false)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$scope = $request->get('scope', false);
|
$scope = $request->get('scope', false);
|
||||||
$state = $request->get('state', false);
|
$state = $request->get('state', false);
|
||||||
|
|
||||||
if ($state) {
|
if ($state) {
|
||||||
$datas["state"] = $state;
|
$data["state"] = $state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope) {
|
if ($scope) {
|
||||||
$datas["scope"] = $scope;
|
$data["scope"] = $scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filters = [
|
$filters = [
|
||||||
@@ -405,17 +414,16 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
, "scope" => ["flags" => FILTER_REQUIRE_SCALAR]
|
, "scope" => ["flags" => FILTER_REQUIRE_SCALAR]
|
||||||
];
|
];
|
||||||
|
|
||||||
$input = filter_var_array($datas, $filters);
|
$input = filter_var_array($data, $filters);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check for valid client_id
|
* check for valid client_id
|
||||||
* check for valid redirect_uri
|
* check for valid redirect_uri
|
||||||
*/
|
*/
|
||||||
if (! $input["client_id"]) {
|
if (! $input["client_id"]) {
|
||||||
if ($input["redirect_uri"])
|
if ($input["redirect_uri"]) {
|
||||||
$this->errorDoRedirectUriCallback(
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_INVALID_CLIENT, null, null, $input["state"]);
|
||||||
$input["redirect_uri"], OAUTH2_ERROR_INVALID_CLIENT, NULL, NULL, $input["state"]
|
}
|
||||||
);
|
|
||||||
// We don't have a good URI to use
|
// We don't have a good URI to use
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_FOUND, OAUTH2_ERROR_INVALID_CLIENT);
|
$this->errorJsonResponse(OAUTH2_HTTP_FOUND, OAUTH2_ERROR_INVALID_CLIENT);
|
||||||
}
|
}
|
||||||
@@ -424,68 +432,71 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
* redirect_uri is not required if already established via other channels
|
* redirect_uri is not required if already established via other channels
|
||||||
* check an existing redirect URI against the one supplied
|
* check an existing redirect URI against the one supplied
|
||||||
*/
|
*/
|
||||||
$redirect_uri = $this->getRedirectUri($input["client_id"]);
|
$redirectUri = $this->getRedirectUri($input["client_id"]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At least one of: existing redirect URI or input redirect URI must be specified
|
* At least one of: existing redirect URI or input redirect URI must be specified
|
||||||
*/
|
*/
|
||||||
if ( ! $redirect_uri && ! $input["redirect_uri"])
|
if ( ! $redirectUri && ! $input["redirect_uri"]) {
|
||||||
$this->errorJsonResponse(
|
$this->errorJsonResponse(OAUTH2_HTTP_FOUND, OAUTH2_ERROR_INVALID_REQUEST);
|
||||||
OAUTH2_HTTP_FOUND, OAUTH2_ERROR_INVALID_REQUEST);
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getRedirectUri() should return FALSE if the given client ID is invalid
|
* getRedirectUri() should return false if the given client ID is invalid
|
||||||
* this probably saves us from making a separate db call, and simplifies the method set
|
* this probably saves us from making a separate db call, and simplifies the method set
|
||||||
*/
|
*/
|
||||||
if ($redirect_uri === FALSE)
|
if ($redirectUri === false) {
|
||||||
$this->errorDoRedirectUriCallback(
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_INVALID_CLIENT, null, null, $input["state"]);
|
||||||
$input["redirect_uri"], OAUTH2_ERROR_INVALID_CLIENT, NULL, NULL, $input["state"]);
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If there's an existing uri and one from input, verify that they match
|
* If there's an existing uri and one from input, verify that they match
|
||||||
*/
|
*/
|
||||||
if ($redirect_uri && $input["redirect_uri"]) {
|
if ($redirectUri && $input["redirect_uri"]) {
|
||||||
/**
|
/**
|
||||||
* Ensure that the input uri starts with the stored uri
|
* Ensure that the input uri starts with the stored uri
|
||||||
*/
|
*/
|
||||||
$compare = strcasecmp(
|
$compare = strcasecmp(
|
||||||
substr(
|
substr(
|
||||||
$input["redirect_uri"], 0, strlen($redirect_uri)
|
$input["redirect_uri"], 0, strlen($redirectUri)
|
||||||
), $redirect_uri);
|
), $redirectUri);
|
||||||
if ($compare !== 0)
|
if ($compare !== 0) {
|
||||||
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_REDIRECT_URI_MISMATCH, NULL, NULL, $input["state"]);
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_REDIRECT_URI_MISMATCH, null, null, $input["state"]);
|
||||||
} elseif ($redirect_uri) {
|
}
|
||||||
|
} elseif ($redirectUri) {
|
||||||
/**
|
/**
|
||||||
* They did not provide a uri from input, so use the stored one
|
* They did not provide a uri from input, so use the stored one
|
||||||
*/
|
*/
|
||||||
$input["redirect_uri"] = $redirect_uri;
|
$input["redirect_uri"] = $redirectUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check response_type
|
* Check response_type
|
||||||
*/
|
*/
|
||||||
if (! $input["response_type"]) {
|
if (! $input["response_type"]) {
|
||||||
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_INVALID_REQUEST, 'Invalid response type.', NULL, $input["state"]);
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_INVALID_REQUEST, 'Invalid response type.', null, $input["state"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check requested auth response type against the list of supported types
|
* Check requested auth response type against the list of supported types
|
||||||
*/
|
*/
|
||||||
if (array_search($input["response_type"], $this->getSupportedAuthResponseTypes()) === FALSE)
|
if (array_search($input["response_type"], $this->getSupportedAuthResponseTypes()) === false) {
|
||||||
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_UNSUPPORTED_RESPONSE_TYPE, NULL, NULL, $input["state"]);
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_UNSUPPORTED_RESPONSE_TYPE, null, null, $input["state"]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restrict clients to certain authorization response types
|
* Restrict clients to certain authorization response types
|
||||||
*/
|
*/
|
||||||
if ($this->checkRestrictedAuthResponseType($input["client_id"], $input["response_type"]) === FALSE)
|
if ($this->checkRestrictedAuthResponseType($input["client_id"], $input["response_type"]) === false) {
|
||||||
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_UNAUTHORIZED_CLIENT, NULL, NULL, $input["state"]);
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_UNAUTHORIZED_CLIENT, null, null, $input["state"]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that the requested scope is supported
|
* Validate that the requested scope is supported
|
||||||
*/
|
*/
|
||||||
if ($input["scope"] && ! $this->checkScope($input["scope"], $this->getSupportedScopes()))
|
if ($input["scope"] && ! $this->checkScope($input["scope"], $this->getSupportedScopes())) {
|
||||||
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_INVALID_SCOPE, NULL, NULL, $input["state"]);
|
$this->errorDoRedirectUriCallback($input["redirect_uri"], OAUTH2_ERROR_INVALID_SCOPE, null, null, $input["state"]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* at this point all params are ok
|
* at this point all params are ok
|
||||||
@@ -496,121 +507,101 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param User $user
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @return mixed
|
||||||
* @return API_OAuth2_Account
|
* @throws logicalException
|
||||||
*/
|
*/
|
||||||
public function updateAccount(User $user)
|
public function updateAccount(User $user)
|
||||||
{
|
{
|
||||||
if ($this->client === null)
|
if ($this->client === null) {
|
||||||
throw new logicalException("Client property must be set before update an account");
|
throw new logicalException("Client property must be set before update an account");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
if (null === $account = $this->app['repo.api-accounts']->findByUserAndApplication($user, $this->client)) {
|
||||||
$account = API_OAuth2_Account::load_with_user($this->app, $this->client, $user);
|
$account = $this->app['manipulator.api-account']->create($this->client, $user);
|
||||||
} catch (\Exception $e) {
|
|
||||||
$account = $this->createAccount($user->getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param $is_authorized
|
||||||
|
* @param array $params
|
||||||
*
|
*
|
||||||
* @param int $usr_id
|
* @return array
|
||||||
* @return API_OAuth2_Account
|
|
||||||
*/
|
|
||||||
private function createAccount($usr_id)
|
|
||||||
{
|
|
||||||
$user = $this->app['repo.users']->find($usr_id);
|
|
||||||
|
|
||||||
return API_OAuth2_Account::create($this->app, $user, $this->client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param <type> $is_authorized
|
|
||||||
* @param array $params
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function finishNativeClientAuthorization($is_authorized, $params = [])
|
public function finishNativeClientAuthorization($is_authorized, $params = [])
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
$params += [
|
$params += ['scope' => null, 'state' => null,];
|
||||||
'scope' => NULL,
|
|
||||||
'state' => NULL,
|
|
||||||
];
|
|
||||||
extract($params);
|
|
||||||
|
|
||||||
if ($state !== NULL)
|
if ($params['state'] !== null) {
|
||||||
$result["query"]["state"] = $state;
|
$result["query"]["state"] = $params['state'] ;
|
||||||
|
}
|
||||||
|
|
||||||
if ($is_authorized === FALSE) {
|
if ($is_authorized === false) {
|
||||||
$result["error"] = OAUTH2_ERROR_USER_DENIED;
|
$result["error"] = OAUTH2_ERROR_USER_DENIED;
|
||||||
} else {
|
} else {
|
||||||
if ($response_type == OAUTH2_AUTH_RESPONSE_TYPE_AUTH_CODE)
|
if ($params['response_type'] === OAUTH2_AUTH_RESPONSE_TYPE_AUTH_CODE) {
|
||||||
$result["code"] = $this->createAuthCode($account_id, $redirect_uri, $scope);
|
$result["code"] = $this->createAuthCode($params['account_id'], $params['redirect_uri'], $params['scope']);
|
||||||
|
}
|
||||||
|
|
||||||
if ($response_type == OAUTH2_AUTH_RESPONSE_TYPE_ACCESS_TOKEN)
|
if ($params['response_type'] === OAUTH2_AUTH_RESPONSE_TYPE_ACCESS_TOKEN) {
|
||||||
$result["error"] = OAUTH2_ERROR_UNSUPPORTED_RESPONSE_TYPE;
|
$result["error"] = OAUTH2_ERROR_UNSUPPORTED_RESPONSE_TYPE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param $redirectUri
|
||||||
*
|
*
|
||||||
* @param <type> $redirect_uri
|
* @return bool
|
||||||
* @return <type>
|
|
||||||
*/
|
*/
|
||||||
public function isNativeApp($redirect_uri)
|
public function isNativeApp($redirectUri)
|
||||||
{
|
{
|
||||||
return $redirect_uri === API_OAuth2_Application::NATIVE_APP_REDIRECT_URI;
|
return $redirectUri === ApiApplication::NATIVE_APP_REDIRECT_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function remember_this_ses_id($ses_id)
|
public function rememberSession(Session $session)
|
||||||
{
|
{
|
||||||
try {
|
if (null !== $token = $this->app['repo.api-oauth-tokens']->find($this->token)) {
|
||||||
$token = API_OAuth2_Token::load_by_oauth_token($this->app, $this->token);
|
$token->setSession($session);
|
||||||
$token->set_session_id($ses_id);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verifyAccessToken($scope = NULL, $exit_not_present = TRUE, $exit_invalid = TRUE, $exit_expired = TRUE, $exit_scope = TRUE, $realm = NULL)
|
public function verifyAccessToken($scope = null, $exit_not_present = TRUE, $exit_invalid = TRUE, $exit_expired = TRUE, $exit_scope = TRUE, $realm = null)
|
||||||
{
|
{
|
||||||
$token_param = $this->getAccessTokenParams();
|
$token_param = $this->getAccessTokenParams();
|
||||||
|
|
||||||
// Access token was not provided
|
// Access token was not provided
|
||||||
if ($token_param === false) {
|
if ($token_param === false) {
|
||||||
return $exit_not_present ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_BAD_REQUEST, $realm, OAUTH2_ERROR_INVALID_REQUEST, 'The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed.', NULL, $scope) : FALSE;
|
return $exit_not_present ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_BAD_REQUEST, $realm, OAUTH2_ERROR_INVALID_REQUEST, 'The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed.', null, $scope) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the stored token data (from the implementing subclass)
|
// Get the stored token data (from the implementing subclass)
|
||||||
$token = $this->getAccessToken($token_param);
|
$token = $this->getAccessToken($token_param);
|
||||||
|
|
||||||
if ($token === NULL) {
|
if ($token === null) {
|
||||||
return $exit_invalid ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_UNAUTHORIZED, $realm, OAUTH2_ERROR_INVALID_TOKEN, 'The access token provided is invalid.', NULL, $scope) : FALSE;
|
return $exit_invalid ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_UNAUTHORIZED, $realm, OAUTH2_ERROR_INVALID_TOKEN, 'The access token provided is invalid.', null, $scope) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($token['revoked']) && $token['revoked']) {
|
if (isset($token['revoked']) && $token['revoked']) {
|
||||||
return $exit_invalid ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_UNAUTHORIZED, $realm, OAUTH2_ERROR_INVALID_TOKEN, 'End user has revoked access to his personal datas for your application.', NULL, $scope) : FALSE;
|
return $exit_invalid ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_UNAUTHORIZED, $realm, OAUTH2_ERROR_INVALID_TOKEN, 'End user has revoked access to his personal datas for your application.', null, $scope) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->enable_expire) {
|
if ($this->enable_expire) {
|
||||||
// Check token expiration (I'm leaving this check separated, later we'll fill in better error messages)
|
// Check token expiration (I'm leaving this check separated, later we'll fill in better error messages)
|
||||||
if (isset($token["expires"]) && time() > $token["expires"]) {
|
if (isset($token["expires"]) && time() > $token["expires"]) {
|
||||||
return $exit_expired ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_UNAUTHORIZED, $realm, OAUTH2_ERROR_EXPIRED_TOKEN, 'The access token provided has expired.', NULL, $scope) : FALSE;
|
return $exit_expired ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_UNAUTHORIZED, $realm, OAUTH2_ERROR_EXPIRED_TOKEN, 'The access token provided has expired.', null, $scope) : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check scope, if provided
|
// Check scope, if provided
|
||||||
// If token doesn't have a scope, it's NULL/empty, or it's insufficient, then throw an error
|
// If token doesn't have a scope, it's null/empty, or it's insufficient, then throw an error
|
||||||
if ($scope && ( ! isset($token["scope"]) || ! $token["scope"] || ! $this->checkScope($scope, $token["scope"]))) {
|
if ($scope && ( ! isset($token["scope"]) || ! $token["scope"] || ! $this->checkScope($scope, $token["scope"]))) {
|
||||||
return $exit_scope ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_FORBIDDEN, $realm, OAUTH2_ERROR_INSUFFICIENT_SCOPE, 'The request requires higher privileges than provided by the access token.', NULL, $scope) : FALSE;
|
return $exit_scope ? $this->errorWWWAuthenticateResponseHeader(OAUTH2_HTTP_FORBIDDEN, $realm, OAUTH2_ERROR_INSUFFICIENT_SCOPE, 'The request requires higher privileges than provided by the access token.', null, $scope) : false;
|
||||||
}
|
}
|
||||||
//save token's linked ses_id
|
//save token's linked ses_id
|
||||||
$this->session_id = $token['session_id'];
|
$this->session_id = $token['session_id'];
|
||||||
@@ -623,23 +614,25 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
public function finishClientAuthorization($is_authorized, $params = [])
|
public function finishClientAuthorization($is_authorized, $params = [])
|
||||||
{
|
{
|
||||||
$params += [
|
$params += [
|
||||||
'scope' => NULL,
|
'scope' => null,
|
||||||
'state' => NULL,
|
'state' => null,
|
||||||
];
|
];
|
||||||
extract($params);
|
|
||||||
|
|
||||||
if ($state !== NULL)
|
if ($params['state'] !== null) {
|
||||||
$result["query"]["state"] = $state;
|
$result["query"]["state"] = $params['state'];
|
||||||
if ($is_authorized === FALSE)
|
|
||||||
$result["query"]["error"] = OAUTH2_ERROR_USER_DENIED;
|
|
||||||
else {
|
|
||||||
if ($response_type == OAUTH2_AUTH_RESPONSE_TYPE_AUTH_CODE || $response_type == OAUTH2_AUTH_RESPONSE_TYPE_CODE_AND_TOKEN)
|
|
||||||
$result["query"]["code"] = $this->createAuthCode($account_id, $redirect_uri, $scope);
|
|
||||||
|
|
||||||
if ($response_type == OAUTH2_AUTH_RESPONSE_TYPE_ACCESS_TOKEN || $response_type == OAUTH2_AUTH_RESPONSE_TYPE_CODE_AND_TOKEN)
|
|
||||||
$result["fragment"] = $this->createAccessToken($account_id, $scope);
|
|
||||||
}
|
}
|
||||||
$this->doRedirectUriCallback($redirect_uri, $result);
|
if ($is_authorized === false) {
|
||||||
|
$result["query"]["error"] = OAUTH2_ERROR_USER_DENIED;
|
||||||
|
} else {
|
||||||
|
if ($params['response_type'] == OAUTH2_AUTH_RESPONSE_TYPE_AUTH_CODE || $params['response_type'] == OAUTH2_AUTH_RESPONSE_TYPE_CODE_AND_TOKEN) {
|
||||||
|
$result["query"]["code"] = $this->createAuthCode($params['account_id'], $params['redirect_uri'], $params['scope']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($params['response_type'] == OAUTH2_AUTH_RESPONSE_TYPE_ACCESS_TOKEN || $params['response_type'] == OAUTH2_AUTH_RESPONSE_TYPE_CODE_AND_TOKEN) {
|
||||||
|
$result["fragment"] = $this->createAccessToken($params['account_id'], $params['scope']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->doRedirectUriCallback($params['redirect_uri'], $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -648,62 +641,75 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
public function grantAccessToken()
|
public function grantAccessToken()
|
||||||
{
|
{
|
||||||
$filters = [
|
$filters = [
|
||||||
"grant_type" => ["filter" => FILTER_VALIDATE_REGEXP, "options" => ["regexp" => OAUTH2_GRANT_TYPE_REGEXP], "flags" => FILTER_REQUIRE_SCALAR],
|
"grant_type" => [
|
||||||
"scope" => ["flags" => FILTER_REQUIRE_SCALAR],
|
"filter" => FILTER_VALIDATE_REGEXP,
|
||||||
"code" => ["flags" => FILTER_REQUIRE_SCALAR],
|
"options" => ["regexp" => OAUTH2_GRANT_TYPE_REGEXP],
|
||||||
"redirect_uri" => ["filter" => FILTER_SANITIZE_URL],
|
"flags" => FILTER_REQUIRE_SCALAR
|
||||||
"username" => ["flags" => FILTER_REQUIRE_SCALAR],
|
],
|
||||||
"password" => ["flags" => FILTER_REQUIRE_SCALAR],
|
"scope" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
"assertion_type" => ["flags" => FILTER_REQUIRE_SCALAR],
|
"code" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
"assertion" => ["flags" => FILTER_REQUIRE_SCALAR],
|
"redirect_uri" => ["filter" => FILTER_SANITIZE_URL],
|
||||||
|
"username" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
|
"password" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
|
"assertion_type" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
|
"assertion" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
"refresh_token" => ["flags" => FILTER_REQUIRE_SCALAR],
|
"refresh_token" => ["flags" => FILTER_REQUIRE_SCALAR],
|
||||||
];
|
];
|
||||||
|
|
||||||
$input = filter_input_array(INPUT_POST, $filters);
|
$input = filter_input_array(INPUT_POST, $filters);
|
||||||
|
|
||||||
// Grant Type must be specified.
|
// Grant Type must be specified.
|
||||||
if ( ! $input["grant_type"])
|
if ( ! $input["grant_type"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing');
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing');
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we've implemented the requested grant type
|
// Make sure we've implemented the requested grant type
|
||||||
if ( ! in_array($input["grant_type"], $this->getSupportedGrantTypes()))
|
if ( ! in_array($input["grant_type"], $this->getSupportedGrantTypes())) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNSUPPORTED_GRANT_TYPE);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNSUPPORTED_GRANT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
// Authorize the client
|
// Authorize the client
|
||||||
$client = $this->getClientCredentials();
|
$client = $this->getClientCredentials();
|
||||||
|
|
||||||
if ($this->checkClientCredentials($client[0], $client[1]) === FALSE)
|
if ($this->checkClientCredentials($client[0], $client[1]) === false) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_CLIENT);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! $this->checkRestrictedGrantType($client[0], $input["grant_type"]))
|
if ( ! $this->checkRestrictedGrantType($client[0], $input["grant_type"])) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNAUTHORIZED_CLIENT);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNAUTHORIZED_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! $this->checkRestrictedGrantType($client[0], $input["grant_type"]))
|
if ( ! $this->checkRestrictedGrantType($client[0], $input["grant_type"])) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNAUTHORIZED_CLIENT);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNAUTHORIZED_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
// Do the granting
|
// Do the granting
|
||||||
switch ($input["grant_type"]) {
|
switch ($input["grant_type"]) {
|
||||||
case OAUTH2_GRANT_TYPE_AUTH_CODE:
|
case OAUTH2_GRANT_TYPE_AUTH_CODE:
|
||||||
if ( ! $input["code"] || ! $input["redirect_uri"])
|
if ( ! $input["code"] || ! $input["redirect_uri"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST);
|
||||||
|
}
|
||||||
$stored = $this->getAuthCode($input["code"]);
|
$stored = $this->getAuthCode($input["code"]);
|
||||||
|
|
||||||
// Ensure that the input uri starts with the stored uri
|
// Ensure that the input uri starts with the stored uri
|
||||||
if ($stored === NULL || (strcasecmp(substr($input["redirect_uri"], 0, strlen($stored["redirect_uri"])), $stored["redirect_uri"]) !== 0) || $client[0] != $stored["client_id"])
|
if ($stored === null || (strcasecmp(substr($input["redirect_uri"], 0, strlen($stored["redirect_uri"])), $stored["redirect_uri"]) !== 0) || $client[0] != $stored["client_id"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT);
|
||||||
|
}
|
||||||
|
|
||||||
if ($stored["expires"] < time())
|
if ($stored["expires"] < time()) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_EXPIRED_TOKEN);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_EXPIRED_TOKEN);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OAUTH2_GRANT_TYPE_USER_CREDENTIALS:
|
case OAUTH2_GRANT_TYPE_USER_CREDENTIALS:
|
||||||
$application = API_OAuth2_Application::load_from_client_id($this->app, $client[0]);
|
$application = ApiApplication::load_from_client_id($this->app, $client[0]);
|
||||||
|
|
||||||
if ( ! $application->is_password_granted()) {
|
if ( ! $application->is_password_granted()) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNSUPPORTED_GRANT_TYPE, 'Password grant type is not enable for your client');
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_UNSUPPORTED_GRANT_TYPE, 'Password grant type is not enable for your client');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $input["username"] || ! $input["password"])
|
if ( ! $input["username"] || ! $input["password"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Missing parameters. "username" and "password" required');
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Missing parameters. "username" and "password" required');
|
||||||
|
}
|
||||||
|
|
||||||
$stored = $this->checkUserCredentials($client[0], $input["username"], $input["password"]);
|
$stored = $this->checkUserCredentials($client[0], $input["username"], $input["password"]);
|
||||||
|
|
||||||
@@ -712,26 +718,31 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OAUTH2_GRANT_TYPE_ASSERTION:
|
case OAUTH2_GRANT_TYPE_ASSERTION:
|
||||||
if ( ! $input["assertion_type"] || ! $input["assertion"])
|
if ( ! $input["assertion_type"] || ! $input["assertion"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
$stored = $this->checkAssertion($client[0], $input["assertion_type"], $input["assertion"]);
|
$stored = $this->checkAssertion($client[0], $input["assertion_type"], $input["assertion"]);
|
||||||
|
|
||||||
if ($stored === FALSE)
|
if ($stored === false) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case OAUTH2_GRANT_TYPE_REFRESH_TOKEN:
|
case OAUTH2_GRANT_TYPE_REFRESH_TOKEN:
|
||||||
if ( ! $input["refresh_token"])
|
if ( ! $input["refresh_token"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'No "refresh_token" parameter found');
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'No "refresh_token" parameter found');
|
||||||
|
}
|
||||||
|
|
||||||
$stored = $this->getRefreshToken($input["refresh_token"]);
|
$stored = $this->getRefreshToken($input["refresh_token"]);
|
||||||
|
|
||||||
if ($stored === NULL || $client[0] != $stored["client_id"])
|
if ($stored === null || $client[0] != $stored["client_id"]) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_GRANT);
|
||||||
|
}
|
||||||
|
|
||||||
if ($stored["expires"] < time())
|
if ($stored["expires"] < time()) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_EXPIRED_TOKEN);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_EXPIRED_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
// store the refresh token locally so we can delete it when a new refresh token is generated
|
// store the refresh token locally so we can delete it when a new refresh token is generated
|
||||||
$this->setVariable('_old_refresh_token', $stored["token"]);
|
$this->setVariable('_old_refresh_token', $stored["token"]);
|
||||||
@@ -740,16 +751,19 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
case OAUTH2_GRANT_TYPE_NONE:
|
case OAUTH2_GRANT_TYPE_NONE:
|
||||||
$stored = $this->checkNoneAccess($client[0]);
|
$stored = $this->checkNoneAccess($client[0]);
|
||||||
|
|
||||||
if ($stored === FALSE)
|
if ($stored === false) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check scope, if provided
|
// Check scope, if provided
|
||||||
if ($input["scope"] && ( ! is_array($stored) || ! isset($stored["scope"]) || ! $this->checkScope($input["scope"], $stored["scope"])))
|
if ($input["scope"] && ( ! is_array($stored) || ! isset($stored["scope"]) || ! $this->checkScope($input["scope"], $stored["scope"]))) {
|
||||||
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_SCOPE);
|
$this->errorJsonResponse(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_SCOPE);
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! $input["scope"])
|
if ( ! $input["scope"]) {
|
||||||
$input["scope"] = NULL;
|
$input["scope"] = null;
|
||||||
|
}
|
||||||
|
|
||||||
$token = $this->createAccessToken($stored['account_id'], $input["scope"]);
|
$token = $this->createAccessToken($stored['account_id'], $input["scope"]);
|
||||||
$this->sendJsonHeaders();
|
$this->sendJsonHeaders();
|
||||||
@@ -759,51 +773,63 @@ class API_OAuth2_Adapter extends OAuth2
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createAccessToken($account_id, $scope = NULL)
|
protected function createAccessToken($accountId, $scope = null)
|
||||||
{
|
{
|
||||||
$token = [
|
$token = [
|
||||||
"access_token" => $this->genAccessToken(),
|
"access_token" => $this->genAccessToken(),
|
||||||
"scope" => $scope
|
"scope" => $scope
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->enable_expire)
|
if ($this->enable_expire) {
|
||||||
$token['expires_in'] = $this->getVariable('access_token_lifetime', OAUTH2_DEFAULT_ACCESS_TOKEN_LIFETIME);
|
$token['expires_in'] = $this->getVariable('access_token_lifetime', OAUTH2_DEFAULT_ACCESS_TOKEN_LIFETIME);
|
||||||
|
}
|
||||||
|
|
||||||
$this->setAccessToken($token["access_token"], $account_id, time() + $this->getVariable('access_token_lifetime', OAUTH2_DEFAULT_ACCESS_TOKEN_LIFETIME), $scope);
|
$this->setAccessToken($token["access_token"], $accountId, time() + $this->getVariable('access_token_lifetime', OAUTH2_DEFAULT_ACCESS_TOKEN_LIFETIME), $scope);
|
||||||
|
|
||||||
// Issue a refresh token also, if we support them
|
// Issue a refresh token also, if we support them
|
||||||
if (in_array(OAUTH2_GRANT_TYPE_REFRESH_TOKEN, $this->getSupportedGrantTypes())) {
|
if (in_array(OAUTH2_GRANT_TYPE_REFRESH_TOKEN, $this->getSupportedGrantTypes())) {
|
||||||
$token["refresh_token"] = $this->genAccessToken();
|
$token["refresh_token"] = $this->genAccessToken();
|
||||||
$this->setRefreshToken($token["refresh_token"], $account_id, time() + $this->getVariable('refresh_token_lifetime', OAUTH2_DEFAULT_REFRESH_TOKEN_LIFETIME), $scope);
|
$this->setRefreshToken($token["refresh_token"], $accountId, time() + $this->getVariable('refresh_token_lifetime', OAUTH2_DEFAULT_REFRESH_TOKEN_LIFETIME), $scope);
|
||||||
// If we've granted a new refresh token, expire the old one
|
// If we've granted a new refresh token, expire the old one
|
||||||
if ($this->getVariable('_old_refresh_token'))
|
if ($this->getVariable('_old_refresh_token')) {
|
||||||
$this->unsetRefreshToken($this->getVariable('_old_refresh_token'));
|
$this->unsetRefreshToken($this->getVariable('_old_refresh_token'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkUserCredentials($client_id, $username, $password)
|
/**
|
||||||
|
* @param $clientId
|
||||||
|
* @param $username
|
||||||
|
* @param $password
|
||||||
|
*
|
||||||
|
* @return array|boolean
|
||||||
|
*/
|
||||||
|
protected function checkUserCredentials($clientId, $username, $password)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->setClient(API_OAuth2_Application::load_from_client_id($this->app, $client_id));
|
if (null === $client = $this->app['repo.api-applications']->findByClientId($clientId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->setClient($client);
|
||||||
|
|
||||||
$usr_id = $this->app['auth.native']->getUsrId($username, $password, Request::createFromGlobals());
|
$usrId = $this->app['auth.native']->getUsrId($username, $password, Request::createFromGlobals());
|
||||||
|
|
||||||
if (!$usr_id) {
|
if (!$usrId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $user = $this->app['repo.users']->find($usr_id)) {
|
if (null === $user = $this->app['repo.users']->find($usrId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$account = $this->updateAccount($user);
|
$account = $this->updateAccount($user);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'redirect_uri' => $this->client->get_redirect_uri()
|
'redirect_uri' => $this->client->getRedirectUri(),
|
||||||
, 'client_id' => $this->client->get_client_id()
|
'client_id' => $this->client->getClient(),
|
||||||
, 'account_id' => $account->get_id()
|
'account_id' => $account->getId(),
|
||||||
];
|
];
|
||||||
} catch (AccountLockedException $e) {
|
} catch (AccountLockedException $e) {
|
||||||
return false;
|
return false;
|
||||||
|
Reference in New Issue
Block a user