From bbd30afd8067c2c813100168ca3b11d179d46867 Mon Sep 17 00:00:00 2001 From: Erik Amaru Ortiz Date: Thu, 21 Aug 2014 17:01:00 -0400 Subject: [PATCH] FIX for OAuth new grant types over php >= 5.3.3 --- .../Services/OAuth2/PmClientCredentials.php | 129 ++++++++++++++++++ .../ProcessMaker/Services/OAuth2/Server.php | 4 +- 2 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 workflow/engine/src/ProcessMaker/Services/OAuth2/PmClientCredentials.php diff --git a/workflow/engine/src/ProcessMaker/Services/OAuth2/PmClientCredentials.php b/workflow/engine/src/ProcessMaker/Services/OAuth2/PmClientCredentials.php new file mode 100644 index 000000000..30c9c7978 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Services/OAuth2/PmClientCredentials.php @@ -0,0 +1,129 @@ + + * + * @see OAuth2_ClientAssertionType_HttpBasic + */ +class PmClientCredentials implements \OAuth2\GrantType\GrantTypeInterface +{ + private $clientData; + + protected $storage; + protected $config; + + public function __construct(ClientCredentialsInterface $storage, array $config = array()) + { + $this->storage = $storage; + $this->config = array_merge(array( + 'allow_credentials_in_request_body' => true + ), $config); + } + + public function validateRequest(RequestInterface $request, ResponseInterface $response) + { + if (!$clientData = $this->getClientCredentials($request, $response)) { + return false; + } + + if (!isset($clientData['client_id']) || !isset($clientData['client_secret'])) { + throw new \LogicException('the clientData array must have "client_id" and "client_secret" values set.'); + } + + if ($this->storage->checkClientCredentials($clientData['client_id'], $clientData['client_secret']) === false) { + $response->setError(400, 'invalid_client', 'The client credentials are invalid'); + return false; + } + + if (!$this->storage->checkRestrictedGrantType($clientData['client_id'], $request->request('grant_type'))) { + $response->setError(400, 'unauthorized_client', 'The grant type is unauthorized for this client_id'); + return false; + } + + $this->clientData = $clientData; + + return true; + } + + public function getClientId() + { + return $this->clientData['client_id']; + } + + /** + * Internal function used to get the client credentials from HTTP basic + * auth or POST data. + * + * According to the spec (draft 20), the client_id can be provided in + * the Basic Authorization header (recommended) or via GET/POST. + * + * @return + * A list containing the client identifier and password, for example + * @code + * return array( + * "client_id" => CLIENT_ID, // REQUIRED the client id + * "client_secret" => CLIENT_SECRET, // REQUIRED the client secret + * ); + * @endcode + * + * @see http://tools.ietf.org/html/rfc6749#section-2.3.1 + * + * @ingroup oauth2_section_2 + */ + public function getClientCredentials(RequestInterface $request, ResponseInterface $response = null) + { + if (!is_null($request->headers('PHP_AUTH_USER')) && !is_null($request->headers('PHP_AUTH_PW'))) { + return array('client_id' => $request->headers('PHP_AUTH_USER'), 'client_secret' => $request->headers('PHP_AUTH_PW')); + } + + if ($this->config['allow_credentials_in_request_body']) { + // Using POST for HttpBasic authorization is not recommended, but is supported by specification + if (!is_null($request->request('client_id'))) { + /** + * client_secret can be null if the client's password is an empty string + * @see http://tools.ietf.org/html/rfc6749#section-2.3.1 + */ + return array('client_id' => $request->request('client_id'), 'client_secret' => $request->request('client_secret', '')); + } + } + + if ($response) { + $response->setError(400, 'invalid_client', 'Client credentials were not found in the headers or body'); + } + + return null; + } + + public function getQuerystringIdentifier() + { + return 'client_credentials'; + } + + public function getScope() + { + return null; + } + + public function getUserId() + { + return null; + } + + public function createAccessToken(AccessTokenInterface $accessToken, $client_id, $user_id, $scope) + { + /* + * Client Credentials Grant does NOT include a refresh token + * @see http://tools.ietf.org/html/rfc6749#section-4.4.3 + */ + $includeRefreshToken = false; + return $accessToken->createAccessToken($client_id, $user_id, $scope, $includeRefreshToken); + } +} diff --git a/workflow/engine/src/ProcessMaker/Services/OAuth2/Server.php b/workflow/engine/src/ProcessMaker/Services/OAuth2/Server.php index b517bd8f1..4c6636cdf 100644 --- a/workflow/engine/src/ProcessMaker/Services/OAuth2/Server.php +++ b/workflow/engine/src/ProcessMaker/Services/OAuth2/Server.php @@ -55,7 +55,7 @@ class Server implements iAuthenticate $this->server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->storage)); // Add the "Client Credentials" grant type (it is the simplest of the grant types) - $this->server->addGrantType(new \OAuth2\GrantType\ClientCredentials($this->storage)); + $this->server->addGrantType(new \ProcessMaker\Services\OAuth2\PmClientCredentials($this->storage)); // Add the "Refresh token" grant type $this->server->addGrantType(new \OAuth2\GrantType\RefreshToken($this->storage)); @@ -184,7 +184,7 @@ class Server implements iAuthenticate */ public function postAuthorize($authorize = null, $userId = null, $returnResponse = false) { - session_start(); + @session_start(); if (! isset($_SESSION['USER_LOGGED'])) { throw new RestException(400, "Local Authentication Error, user session is not started.");