summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/OAuth2/Controller/AccessController.php2
-rw-r--r--src/OAuth2/Controller/AccessControllerInterface.php2
-rw-r--r--src/OAuth2/Controller/AuthorizeController.php6
-rw-r--r--src/OAuth2/Controller/AuthorizeControllerInterface.php4
-rw-r--r--src/OAuth2/Controller/GrantController.php58
-rw-r--r--src/OAuth2/Controller/GrantControllerInterface.php13
-rw-r--r--src/OAuth2/GrantType/AuthorizationCode.php14
-rw-r--r--src/OAuth2/GrantType/ClientCredentials.php15
-rw-r--r--src/OAuth2/GrantType/RefreshToken.php30
-rw-r--r--src/OAuth2/GrantType/UserCredentials.php22
-rw-r--r--src/OAuth2/GrantTypeInterface.php6
-rw-r--r--src/OAuth2/Request.php5
-rw-r--r--src/OAuth2/RequestInterface.php9
-rw-r--r--src/OAuth2/Response/AuthenticationError.php2
-rw-r--r--src/OAuth2/ResponseType/AccessToken.php25
-rw-r--r--src/OAuth2/ResponseType/AccessTokenInterface.php2
-rw-r--r--src/OAuth2/Server.php46
-rw-r--r--src/OAuth2/Storage/ClientCredentialsInterface.php3
-rw-r--r--src/OAuth2/Storage/Memory.php7
-rw-r--r--src/OAuth2/Storage/Pdo.php71
-rw-r--r--src/OAuth2/Storage/UserCredentialsInterface.php12
-rw-r--r--src/OAuth2/TokenType/Bearer.php8
-rw-r--r--src/OAuth2/TokenType/MAC.php2
-rw-r--r--src/OAuth2/TokenTypeInterface.php2
24 files changed, 238 insertions, 128 deletions
diff --git a/src/OAuth2/Controller/AccessController.php b/src/OAuth2/Controller/AccessController.php
index 8c2449a..883c64a 100644
--- a/src/OAuth2/Controller/AccessController.php
+++ b/src/OAuth2/Controller/AccessController.php
@@ -25,7 +25,7 @@ class OAuth2_Controller_AccessController implements OAuth2_Controller_AccessCont
$this->util = $util;
}
- public function verifyAccessRequest(OAuth2_Request $request)
+ public function verifyAccessRequest(OAuth2_RequestInterface $request)
{
$token = $this->tokenType->getAccessTokenParameter($request);
$this->response = $this->tokenType->getResponse();
diff --git a/src/OAuth2/Controller/AccessControllerInterface.php b/src/OAuth2/Controller/AccessControllerInterface.php
index ff63b13..a7b77c8 100644
--- a/src/OAuth2/Controller/AccessControllerInterface.php
+++ b/src/OAuth2/Controller/AccessControllerInterface.php
@@ -2,7 +2,7 @@
interface OAuth2_Controller_AccessControllerInterface extends OAuth2_Response_ProviderInterface
{
- public function verifyAccessRequest(OAuth2_Request $request);
+ public function verifyAccessRequest(OAuth2_RequestInterface $request);
public function getAccessTokenData($token_param, $scope = null);
} \ No newline at end of file
diff --git a/src/OAuth2/Controller/AuthorizeController.php b/src/OAuth2/Controller/AuthorizeController.php
index c7603ff..09ff56c 100644
--- a/src/OAuth2/Controller/AuthorizeController.php
+++ b/src/OAuth2/Controller/AuthorizeController.php
@@ -27,7 +27,7 @@ class OAuth2_Controller_AuthorizeController implements OAuth2_Controller_Authori
$this->util = $util;
}
- public function handleAuthorizeRequest(OAuth2_Request $request, $is_authorized, $user_id = null)
+ public function handleAuthorizeRequest(OAuth2_RequestInterface $request, $is_authorized, $user_id = null)
{
if (!is_bool($is_authorized)) {
throw new InvalidArgumentException('Argument "is_authorized" must be a boolean. This method must know if the user has granted access to the client.');
@@ -56,7 +56,7 @@ class OAuth2_Controller_AuthorizeController implements OAuth2_Controller_Authori
return new OAuth2_Response_Redirect($uri);
}
- public function validateAuthorizeRequest(OAuth2_Request $request)
+ public function validateAuthorizeRequest(OAuth2_RequestInterface $request)
{
// Make sure a valid client id was supplied (we can not redirect because we were unable to verify the URI)
if (!$client_id = $request->query("client_id")) {
@@ -139,7 +139,7 @@ class OAuth2_Controller_AuthorizeController implements OAuth2_Controller_Authori
}
// Return retrieved client details together with input
- return ($request->query + $clientData + array('state' => null));
+ return ((array)$request->getAllQueryParameters() + $clientData + array('state' => null));
}
public function getResponse()
diff --git a/src/OAuth2/Controller/AuthorizeControllerInterface.php b/src/OAuth2/Controller/AuthorizeControllerInterface.php
index 463ebda..4110297 100644
--- a/src/OAuth2/Controller/AuthorizeControllerInterface.php
+++ b/src/OAuth2/Controller/AuthorizeControllerInterface.php
@@ -14,7 +14,7 @@ interface OAuth2_Controller_AuthorizeControllerInterface extends OAuth2_Response
const RESPONSE_TYPE_AUTHORIZATION_CODE = 'code';
const RESPONSE_TYPE_ACCESS_TOKEN = 'token';
- public function handleAuthorizeRequest(OAuth2_Request $request, $is_authorized, $user_id = null);
+ public function handleAuthorizeRequest(OAuth2_RequestInterface $request, $is_authorized, $user_id = null);
- public function validateAuthorizeRequest(OAuth2_Request $request);
+ public function validateAuthorizeRequest(OAuth2_RequestInterface $request);
} \ No newline at end of file
diff --git a/src/OAuth2/Controller/GrantController.php b/src/OAuth2/Controller/GrantController.php
index d22ddd8..0e46802 100644
--- a/src/OAuth2/Controller/GrantController.php
+++ b/src/OAuth2/Controller/GrantController.php
@@ -15,15 +15,16 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
foreach ($grantTypes as $grantType) {
$this->addGrantType($grantType);
}
+
if (is_null($util)) {
$util = new OAuth2_Util();
}
$this->util = $util;
}
- public function handleGrantRequest(OAuth2_Request $request, $grantType = null)
+ public function handleGrantRequest(OAuth2_RequestInterface $request)
{
- if ($token = $this->grantAccessToken($request, $grantType)) {
+ if ($token = $this->grantAccessToken($request)) {
$this->response = new OAuth2_Response($token);
}
return $this->response;
@@ -32,9 +33,9 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
/**
* Grant or deny a requested access token.
* This would be called from the "/token" endpoint as defined in the spec.
- * Obviously, you can call your endpoint whatever you want.
+ * You can call your endpoint whatever you want.
*
- * @param $request - OAuth2_Request
+ * @param $request - OAuth2_RequestInterface
* Request object to grant access token
* @param $grantType - mixed
* OAuth2_GrantTypeInterface instance or one of the grant types configured in the constructor
@@ -48,31 +49,27 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
*
* @ingroup oauth2_section_4
*/
- public function grantAccessToken(OAuth2_Request $request, $grantType = null)
+ public function grantAccessToken(OAuth2_RequestInterface $request)
{
- if (!$grantType instanceof OAuth2_GrantTypeInterface) {
- if (is_null($grantType)) {
- if (!$grantType = $request->parameter('grant_type')) {
- $this->response = new OAuth2_Response_Error(400, 'invalid_request', 'The grant type was not specified in the request');
- return null;
- }
- } else if (!is_string($grantType)) {
- throw new InvalidArgumentException('parameter $grantType must be an instance of OAuth2_GrantTypeInterface, a string representing a configured grant type, or null to pull grant type from request');
- }
- if (!isset($this->grantTypes[$grantType])) {
- /* TODO: If this is an OAuth2 supported grant type that we have chosen not to implement, throw a 501 Not Implemented instead */
- $this->response = new OAuth2_Response_Error(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantType));
- return null;
- }
- $grantType = $this->grantTypes[$grantType];
+ // Determine grant type from request
+ if (!($grantType = $request->query('grant_type')) && !($grantType = $request->request('grant_type'))) {
+ $this->response = new OAuth2_Response_Error(400, 'invalid_request', 'The grant type was not specified in the request');
+ return null;
}
+ if (!isset($this->grantTypes[$grantType])) {
+ /* TODO: If this is an OAuth2 supported grant type that we have chosen not to implement, throw a 501 Not Implemented instead */
+ $this->response = new OAuth2_Response_Error(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantType));
+ return null;
+ }
+ $grantType = $this->grantTypes[$grantType];
+ // get and validate client authorization from the request
if (!$clientData = $this->getClientCredentials($request)) {
return null;
}
if (!isset($clientData['client_id']) || !isset($clientData['client_secret'])) {
- throw new LogicException('the clientData array must have "client_id" and "client_secret" values set. Use getClientCredentials()');
+ throw new LogicException('the clientData array must have "client_id" and "client_secret" values set.');
}
if ($this->clientStorage->checkClientCredentials($clientData['client_id'], $clientData['client_secret']) === false) {
@@ -80,13 +77,12 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
return null;
}
- if (!$this->clientStorage->checkRestrictedGrantType($clientData['client_id'], $grantType)) {
+ if (!$this->clientStorage->checkRestrictedGrantType($clientData['client_id'], $grantType->getQuerystringIdentifier())) {
$this->response = new OAuth2_Response_Error(400, 'unauthorized_client', 'The grant type is unauthorized for this client_id');
return null;
}
- /* TODO: Find a better way to handle grantTypes and their responses */
-
+ // validate the request for the token
if (!$grantType->validateRequest($request)) {
if ($grantType instanceof OAuth2_Response_ProviderInterface && $response = $grantType->getResponse()) {
$this->response = $response;
@@ -122,18 +118,14 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
}
// Check scope, if provided
- if (isset($request->query['scope']) && (!is_array($tokenData) || !isset($tokenData["scope"]) || !$this->util->checkScope($request->query['scope'], $tokenData["scope"]))) {
+ if (null != $request->query('scope') && (!is_array($tokenData) || !isset($tokenData["scope"]) || !$this->util->checkScope($request->query('scope'), $tokenData["scope"]))) {
$this->response = new OAuth2_Response_Error(400, 'invalid_scope', 'An unsupported scope was requested.');
return null;
}
- $user_id = isset($tokenData['user_id']) ? $tokenData['user_id'] : null;
- $token = $this->accessToken->createAccessToken($clientData['client_id'], $user_id, $tokenData['scope']);
-
- // TODO: Remove this
- $grantType->finishGrantRequest($token);
+ $tokenData['user_id'] = isset($tokenData['user_id']) ? $tokenData['user_id'] : null;
- return $token;
+ return $grantType->createAccessToken($this->accessToken, $clientData, $tokenData);
}
/**
@@ -156,7 +148,7 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
*
* @ingroup oauth2_section_2
*/
- public function getClientCredentials(OAuth2_Request $request)
+ public function getClientCredentials(OAuth2_RequestInterface $request)
{
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'));
@@ -186,7 +178,7 @@ class OAuth2_Controller_GrantController implements OAuth2_Controller_GrantContro
public function addGrantType(OAuth2_GrantTypeInterface $grantType, $identifier = null)
{
if (is_null($identifier) || is_numeric($identifier)) {
- $identifier = $grantType->getIdentifier();
+ $identifier = $grantType->getQuerystringIdentifier();
}
$this->grantTypes[$identifier] = $grantType;
diff --git a/src/OAuth2/Controller/GrantControllerInterface.php b/src/OAuth2/Controller/GrantControllerInterface.php
index 77fd66f..2bdcfd0 100644
--- a/src/OAuth2/Controller/GrantControllerInterface.php
+++ b/src/OAuth2/Controller/GrantControllerInterface.php
@@ -2,9 +2,16 @@
interface OAuth2_Controller_GrantControllerInterface extends OAuth2_Response_ProviderInterface
{
- public function handleGrantRequest(OAuth2_Request $request, $grantType = null);
+ /**
+ * handleGrantRequest
+ *
+ * @param $request
+ * OAuth2_RequestInterface - The current http request
+ *
+ **/
+ public function handleGrantRequest(OAuth2_RequestInterface $request);
- public function grantAccessToken(OAuth2_Request $request, $grantType = null);
+ public function grantAccessToken(OAuth2_RequestInterface $request);
- public function getClientCredentials(OAuth2_Request $request);
+ public function getClientCredentials(OAuth2_RequestInterface $request);
} \ No newline at end of file
diff --git a/src/OAuth2/GrantType/AuthorizationCode.php b/src/OAuth2/GrantType/AuthorizationCode.php
index 5ae1bd1..2a40b2f 100644
--- a/src/OAuth2/GrantType/AuthorizationCode.php
+++ b/src/OAuth2/GrantType/AuthorizationCode.php
@@ -13,14 +13,14 @@ class OAuth2_GrantType_AuthorizationCode implements OAuth2_GrantTypeInterface, O
$this->storage = $storage;
}
- public function getIdentifier()
+ public function getQuerystringIdentifier()
{
return 'authorization_code';
}
public function validateRequest($request)
{
- if (!isset($request->query['code']) || !$request->query['code']) {
+ if (!$request->query('code')) {
$this->response = new OAuth2_Response_Error(400, 'invalid_request', 'Missing parameter: "code" is required');
return false;
}
@@ -30,7 +30,7 @@ class OAuth2_GrantType_AuthorizationCode implements OAuth2_GrantTypeInterface, O
public function getTokenDataFromRequest($request)
{
- if (!$tokenData = $this->storage->getAuthorizationCode($request->query['code'])) {
+ if (!$tokenData = $this->storage->getAuthorizationCode($request->query('code'))) {
$this->response = new OAuth2_Response_Error(400, 'invalid_grant', "Authorization code doesn't exist or is invalid for the client");
return null;
}
@@ -49,7 +49,7 @@ class OAuth2_GrantType_AuthorizationCode implements OAuth2_GrantTypeInterface, O
return $tokenData;
}
- public function validateTokenData(array $tokenData, array $clientData)
+ public function validateTokenData($tokenData, array $clientData)
{
// Check the code exists
if ($tokenData === null || $clientData['client_id'] != $tokenData['client_id']) {
@@ -66,8 +66,10 @@ class OAuth2_GrantType_AuthorizationCode implements OAuth2_GrantTypeInterface, O
return true;
}
- public function finishGrantRequest($token)
- {}
+ public function createAccessToken(OAuth2_ResponseType_AccessTokenInterface $accessToken, array $clientData, array $tokenData)
+ {
+ return $accessToken->createAccessToken($clientData['client_id'], $tokenData['user_id'], $tokenData['scope']);
+ }
public function getResponse()
{
diff --git a/src/OAuth2/GrantType/ClientCredentials.php b/src/OAuth2/GrantType/ClientCredentials.php
index 4d47c6b..2dae255 100644
--- a/src/OAuth2/GrantType/ClientCredentials.php
+++ b/src/OAuth2/GrantType/ClientCredentials.php
@@ -2,7 +2,7 @@
class OAuth2_GrantType_ClientCredentials implements OAuth2_GrantTypeInterface
{
- public function getIdentifier()
+ public function getQuerystringIdentifier()
{
return 'client_credentials';
}
@@ -22,12 +22,19 @@ class OAuth2_GrantType_ClientCredentials implements OAuth2_GrantTypeInterface
);
}
- public function validateTokenData(array $tokenData, array $clientData)
+ public function validateTokenData($tokenData, array $clientData)
{
// Scope is validated in the client class
return true;
}
- public function finishGrantRequest($token)
- {}
+ public function createAccessToken(OAuth2_ResponseType_AccessTokenInterface $accessToken, array $clientData, array $tokenData)
+ {
+ /*
+ * Client Credentials Grant does NOT include a refresh token
+ * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.4.3
+ */
+ $includeRefreshToken = false;
+ return $accessToken->createAccessToken($clientData['client_id'], $tokenData['user_id'], $tokenData['scope'], $includeRefreshToken);
+ }
} \ No newline at end of file
diff --git a/src/OAuth2/GrantType/RefreshToken.php b/src/OAuth2/GrantType/RefreshToken.php
index 36057fd..5bc9732 100644
--- a/src/OAuth2/GrantType/RefreshToken.php
+++ b/src/OAuth2/GrantType/RefreshToken.php
@@ -7,21 +7,25 @@ class OAuth2_GrantType_RefreshToken implements OAuth2_GrantTypeInterface, OAuth2
{
private $storage;
private $response;
+ private $config;
private $oldRefreshToken;
- public function __construct(OAuth2_Storage_RefreshTokenInterface $storage)
+ public function __construct(OAuth2_Storage_RefreshTokenInterface $storage, $config = array())
{
+ $this->config = array_merge(array(
+ 'always_issue_new_refresh_token' => false
+ ), $config);
$this->storage = $storage;
}
- public function getIdentifier()
+ public function getQuerystringIdentifier()
{
return 'refresh_token';
}
public function validateRequest($request)
{
- if (!isset($request->query["refresh_token"]) || !$request->query['refresh_token']) {
+ if (!$request->query("refresh_token")) {
$this->response = new OAuth2_Response_Error(400, 'invalid_request', 'Missing parameter: "refresh_token" is required');
return false;
}
@@ -31,7 +35,7 @@ class OAuth2_GrantType_RefreshToken implements OAuth2_GrantTypeInterface, OAuth2
public function getTokenDataFromRequest($request)
{
- if (!$stored = $this->storage->getRefreshToken($request->query["refresh_token"])) {
+ if (!$stored = $this->storage->getRefreshToken($request->query("refresh_token"))) {
$this->response = new OAuth2_Response_Error(400, 'invalid_grant', 'Invalid refresh token');
return false;
}
@@ -39,7 +43,7 @@ class OAuth2_GrantType_RefreshToken implements OAuth2_GrantTypeInterface, OAuth2
return $stored;
}
- public function validateTokenData(array $tokenData, array $clientData)
+ public function validateTokenData($tokenData, array $clientData)
{
if ($tokenData === null || $clientData['client_id'] != $tokenData["client_id"]) {
$this->response = new OAuth2_Response_Error(400, 'invalid_grant', 'Invalid refresh token');
@@ -57,9 +61,21 @@ class OAuth2_GrantType_RefreshToken implements OAuth2_GrantTypeInterface, OAuth2
return true;
}
- public function finishGrantRequest($token)
+ public function createAccessToken(OAuth2_ResponseType_AccessTokenInterface $accessToken, array $clientData, array $tokenData)
{
- $this->storage->unsetRefreshToken($this->oldRefreshToken);
+ /*
+ * It is optional to force a new refresh token when a refresh token is used.
+ * However, if a new refresh token is issued, the old one MUST be expired
+ * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-6
+ */
+ $issueNewRefreshToken = $this->config['always_issue_new_refresh_token'];
+ $token = $accessToken->createAccessToken($clientData['client_id'], $tokenData['user_id'], $tokenData['scope'], $issueNewRefreshToken);
+
+ if ($issueNewRefreshToken) {
+ $this->storage->unsetRefreshToken($this->oldRefreshToken);
+ }
+
+ return $token;
}
public function getResponse()
diff --git a/src/OAuth2/GrantType/UserCredentials.php b/src/OAuth2/GrantType/UserCredentials.php
index 5a5dabe..51d05aa 100644
--- a/src/OAuth2/GrantType/UserCredentials.php
+++ b/src/OAuth2/GrantType/UserCredentials.php
@@ -13,14 +13,14 @@ class OAuth2_GrantType_UserCredentials implements OAuth2_GrantTypeInterface, OAu
$this->storage = $storage;
}
- public function getIdentifier()
+ public function getQuerystringIdentifier()
{
return 'password';
}
public function validateRequest($request)
{
- if (!isset($request->query["username"]) || !isset($request->query["password"]) || !$request->query["username"] || !$request->query["password"]) {
+ if (!$request->query("password") || !$request->query("username")) {
$this->response = new OAuth2_Response_Error(400, 'invalid_request', 'Missing parameters: "username" and "password" required');
return false;
}
@@ -30,22 +30,32 @@ class OAuth2_GrantType_UserCredentials implements OAuth2_GrantTypeInterface, OAu
public function getTokenDataFromRequest($request)
{
- if (!$tokenData = $this->storage->checkUserCredentials($request->query["username"], $request->query["password"])) {
+ if (!$this->storage->checkUserCredentials($request->query("username"), $request->query("password"))) {
$this->response = new OAuth2_Response_Error(400, 'invalid_grant', 'Invalid username and password combination');
return false;
}
+ $tokenData = $this->storage->getUserDetails($request->query("username"));
+
+ // tokenData can be an empty array
+ if (false === $tokenData || is_null($tokenData)) {
+ $this->response = new OAuth2_Response_Error(400, 'invalid_grant', 'Unable to retrieve user information');
+ return false;
+ }
+
return $tokenData;
}
- public function validateTokenData(array $tokenData, array $clientData)
+ public function validateTokenData($tokenData, array $clientData)
{
// Scope is validated in the client class
return true;
}
- public function finishGrantRequest($token)
- {}
+ public function createAccessToken(OAuth2_ResponseType_AccessTokenInterface $accessToken, array $clientData, array $tokenData)
+ {
+ return $accessToken->createAccessToken($clientData['client_id'], $tokenData['user_id'], $tokenData['scope']);
+ }
public function getResponse()
{
diff --git a/src/OAuth2/GrantTypeInterface.php b/src/OAuth2/GrantTypeInterface.php
index 25146de..0573f9d 100644
--- a/src/OAuth2/GrantTypeInterface.php
+++ b/src/OAuth2/GrantTypeInterface.php
@@ -2,9 +2,9 @@
interface OAuth2_GrantTypeInterface
{
- public function getIdentifier();
+ public function getQuerystringIdentifier();
public function validateRequest($request);
public function getTokenDataFromRequest($request);
- public function validateTokenData(array $tokenData, array $clientData);
- public function finishGrantRequest($token);
+ public function validateTokenData($tokenData, array $clientData);
+ public function createAccessToken(OAuth2_ResponseType_AccessTokenInterface $accessToken, array $clientData, array $tokenData);
} \ No newline at end of file
diff --git a/src/OAuth2/Request.php b/src/OAuth2/Request.php
index 3f745c9..3ddc3ff 100644
--- a/src/OAuth2/Request.php
+++ b/src/OAuth2/Request.php
@@ -14,6 +14,7 @@ class OAuth2_Request implements OAuth2_RequestInterface
public $files;
public $cookies;
public $headers;
+ public $content;
/**
* Constructor.
@@ -79,9 +80,9 @@ class OAuth2_Request implements OAuth2_RequestInterface
return isset($this->headers[$name]) ? $this->headers[$name] : $default;
}
- public function parameter($name, $default = null)
+ public function getAllQueryParameters()
{
- return $this->query($name) ? $this->query($name) : $this->request($name, $default);
+ return $this->query;
}
/**
diff --git a/src/OAuth2/RequestInterface.php b/src/OAuth2/RequestInterface.php
index c23eb55..0195605 100644
--- a/src/OAuth2/RequestInterface.php
+++ b/src/OAuth2/RequestInterface.php
@@ -2,4 +2,13 @@
interface OAuth2_RequestInterface
{
+ public function query($name, $default = null);
+
+ public function request($name, $default = null);
+
+ public function server($name, $default = null);
+
+ public function headers($name, $default = null);
+
+ public function getAllQueryParameters();
} \ No newline at end of file
diff --git a/src/OAuth2/Response/AuthenticationError.php b/src/OAuth2/Response/AuthenticationError.php
index 7c2566a..c3c5a62 100644
--- a/src/OAuth2/Response/AuthenticationError.php
+++ b/src/OAuth2/Response/AuthenticationError.php
@@ -8,7 +8,7 @@ class OAuth2_Response_AuthenticationError extends OAuth2_Response_Error
public function __construct($statusCode, $error, $errorDescription, $tokenType, $realm, $scope = null)
{
parent::__construct($statusCode, $error, $errorDescription);
- $authHeader = sprintf('WWW-Authenticate: %s realm=%s', $tokenType, $realm);
+ $authHeader = sprintf('%s realm=%s', $tokenType, $realm);
if ($scope) {
$authHeader = sprintf('%s, scope=%s', $authHeader, $scope);
}
diff --git a/src/OAuth2/ResponseType/AccessToken.php b/src/OAuth2/ResponseType/AccessToken.php
index 43efc95..37b5e54 100644
--- a/src/OAuth2/ResponseType/AccessToken.php
+++ b/src/OAuth2/ResponseType/AccessToken.php
@@ -17,7 +17,7 @@ class OAuth2_ResponseType_AccessToken implements OAuth2_ResponseType_AccessToken
'token_type' => 'bearer',
'access_lifetime' => 3600,
'refresh_token_lifetime' => 1209600,
- ));
+ ), $config);
}
// same params as above
@@ -28,8 +28,13 @@ class OAuth2_ResponseType_AccessToken implements OAuth2_ResponseType_AccessToken
$params += array('scope' => null, 'state' => null);
- // should this call from a grant type?
- $result["fragment"] = $this->createAccessToken($params['client_id'], $user_id, $params['scope']);
+ /*
+ * a refresh token MUST NOT be included in the fragment
+ *
+ * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.2.2
+ */
+ $includeRefreshToken = false;
+ $result["fragment"] = $this->createAccessToken($params['client_id'], $user_id, $params['scope'], $includeRefreshToken);
if (isset($params['state'])) {
$result["fragment"]["state"] = $params['state'];
@@ -48,11 +53,13 @@ class OAuth2_ResponseType_AccessToken implements OAuth2_ResponseType_AccessToken
* Client identifier related to the access token.
* @param $scope
* (optional) Scopes to be stored in space-separated string.
+ * @param bool $excludeRefreshToken
+ * If true, the refresh_token will be omitted from the response
*
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-5
* @ingroup oauth2_section_5
*/
- public function createAccessToken($client_id, $user_id, $scope = null)
+ public function createAccessToken($client_id, $user_id, $scope = null, $includeRefreshToken = true)
{
$token = array(
"access_token" => $this->generateAccessToken(),
@@ -63,9 +70,13 @@ class OAuth2_ResponseType_AccessToken implements OAuth2_ResponseType_AccessToken
$this->tokenStorage->setAccessToken($token["access_token"], $client_id, $user_id, $this->config['access_lifetime'] ? time() + $this->config['access_lifetime'] : null, $scope);
- // Issue a refresh token also, if we support them
- /* TODO: How do we handle this? */
- if ($this->refreshStorage) {
+ /*
+ * Issue a refresh token also, if we support them
+ *
+ * Refresh Tokens are considered supported if an instance of OAuth2_Storage_RefreshTokenInterface
+ * is supplied in the constructor
+ */
+ if ($includeRefreshToken && $this->refreshStorage) {
$token["refresh_token"] = $this->generateRefreshToken();
$this->refreshStorage->setRefreshToken($token['refresh_token'], $client_id, $user_id, time() + $this->config['refresh_token_lifetime'], $scope);
}
diff --git a/src/OAuth2/ResponseType/AccessTokenInterface.php b/src/OAuth2/ResponseType/AccessTokenInterface.php
index 5247f6f..457c3b8 100644
--- a/src/OAuth2/ResponseType/AccessTokenInterface.php
+++ b/src/OAuth2/ResponseType/AccessTokenInterface.php
@@ -2,5 +2,5 @@
interface OAuth2_ResponseType_AccessTokenInterface extends OAuth2_ResponseTypeInterface
{
- public function createAccessToken($client_id, $user_id, $scope = null);
+ public function createAccessToken($client_id, $user_id, $scope = null, $includeRefreshToken = true);
} \ No newline at end of file
diff --git a/src/OAuth2/Server.php b/src/OAuth2/Server.php
index bfad2ab..c67057d 100644
--- a/src/OAuth2/Server.php
+++ b/src/OAuth2/Server.php
@@ -2,7 +2,10 @@
/**
* Service class for OAuth
-* Inspired by oauth2-php (https://github.com/quizlet/oauth2-php)
+* This class serves only to wrap the other Controller classes
+* @see OAuth2_Controller_AccessController
+* @see OAuth2_Controller_AuthorizeController
+* @see OAuth2_Controller_GrantController
*/
class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
OAuth2_Controller_AuthorizeControllerInterface, OAuth2_Controller_GrantControllerInterface
@@ -27,14 +30,18 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
* array - array of Objects to implement storage
* OAuth2_Storage object implementing all required storage types (ClientCredentialsInterface and AccessTokenInterface as a minimum)
*
+ * @param array $config
+ * specify a different token lifetime, token header name, etc
+ *
* @param array $grantTypes
* An array of OAuth2_GrantTypeInterface to use for granting access tokens
*
- * @param array $config
- * specify a different token lifetime, token header name, etc
+ * @param array $responseTypes
+ * Response types to use. array keys should be "code" and and "token" for
+ * Access Token and Authorization Code response types
*
- * @param array $response
- * Send in an instance of OAuth2_ResponseInterface to use a different response object
+ * @param OAuth2_ResponseType_AccessTokenInterface $accessTokenResponseType
+ * Response type to use for access token
*
* @return
* TRUE if everything in required scope is contained in available scope,
@@ -44,7 +51,7 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
*
* @ingroup oauth2_section_7
*/
- public function __construct($storage = array(), array $config = array(), array $grantTypes = array(), array $responseTypes = array(), OAuth2_ResponseType_AccessToken $accessTokenResponseType = null)
+ public function __construct($storage = array(), array $config = array(), array $grantTypes = array(), array $responseTypes = array(), OAuth2_ResponseType_AccessTokenInterface $accessTokenResponseType = null)
{
$validStorage = array(
'access_token' => 'OAuth2_Storage_AccessTokenInterface',
@@ -147,7 +154,7 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
if (isset($this->storages['refresh_token'])) {
$refreshStorage = $this->storages['refresh_token'];
}
- $config = array_intersect_key($this->config, array_flip(explode(' ', 'token_type access_lifetime')));
+ $config = array_intersect_key($this->config, array_flip(explode(' ', 'token_type access_lifetime refresh_token_lifetime')));
$this->accessTokenResponseType = new OAuth2_ResponseType_AccessToken($this->storages['access_token'], $refreshStorage, $config);
}
}
@@ -167,7 +174,7 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
if (isset($this->storages['refresh_token'])) {
$refreshStorage = $this->storages['refresh_token'];
}
- $config = array_intersect_key($this->config, array_flip(explode(' ', 'token_type access_lifetime')));
+ $config = array_intersect_key($this->config, array_flip(explode(' ', 'token_type access_lifetime refresh_token_lifetime')));
$responseTypes['token'] = new OAuth2_ResponseType_AccessToken($this->storages['access_token'], $refreshStorage, $config);
}
@@ -217,8 +224,9 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
*
* @param $request - OAuth2_Request
* Request object to grant access token
- * @param $grantType - mixed
- * OAuth2_GrantTypeInterface instance or one of the grant types configured in the constructor
+ *
+ * @return
+ * OAuth_Response
*
* @throws InvalidArgumentException
* @throws LogicException
@@ -229,21 +237,21 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
*
* @ingroup oauth2_section_4
*/
- public function handleGrantRequest(OAuth2_Request $request, $grantType = null)
+ public function handleGrantRequest(OAuth2_RequestInterface $request)
{
- $value = $this->getGrantController()->handleGrantRequest($request, $grantType);
+ $value = $this->getGrantController()->handleGrantRequest($request);
$this->response = $this->grantController->getResponse();
return $value;
}
- public function grantAccessToken(OAuth2_Request $request, $grantType = null)
+ public function grantAccessToken(OAuth2_RequestInterface $request)
{
- $value = $this->getGrantController()->grantAccessToken($request, $grantType);
+ $value = $this->getGrantController()->grantAccessToken($request);
$this->response = $this->grantController->getResponse();
return $value;
}
- public function getClientCredentials(OAuth2_Request $request)
+ public function getClientCredentials(OAuth2_RequestInterface $request)
{
$value = $this->getGrantController()->getClientCredentials($request);
$this->response = $this->grantController->getResponse();
@@ -269,8 +277,10 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
* list of space-delimited strings.
* - state: (optional) An opaque value used by the client to maintain
* state between the request and callback.
+ *
* @param $is_authorized
* TRUE or FALSE depending on whether the user authorized the access.
+ *
* @param $user_id
* Identifier of user who authorized the client
*
@@ -278,7 +288,7 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
*
* @ingroup oauth2_section_4
*/
- public function handleAuthorizeRequest(OAuth2_Request $request, $is_authorized, $user_id = null)
+ public function handleAuthorizeRequest(OAuth2_RequestInterface $request, $is_authorized, $user_id = null)
{
$value = $this->getAuthorizeController()->handleAuthorizeRequest($request, $is_authorized, $user_id);
$this->response = $this->authorizeController->getResponse();
@@ -304,14 +314,14 @@ class OAuth2_Server implements OAuth2_Controller_AccessControllerInterface,
*
* @ingroup oauth2_section_3
*/
- public function validateAuthorizeRequest(OAuth2_Request $request)
+ public function validateAuthorizeRequest(OAuth2_RequestInterface $request)
{
$value = $this->getAuthorizeController()->validateAuthorizeRequest($request);
$this->response = $this->authorizeController->getResponse();
return $value;
}
- public function verifyAccessRequest(OAuth2_Request $request)
+ public function verifyAccessRequest(OAuth2_RequestInterface $request)
{
$value = $this->getAccessController()->verifyAccessRequest($request);
$this->response = $this->accessController->getResponse();
diff --git a/src/OAuth2/Storage/ClientCredentialsInterface.php b/src/OAuth2/Storage/ClientCredentialsInterface.php
index 0110c9f..374d628 100644
--- a/src/OAuth2/Storage/ClientCredentialsInterface.php
+++ b/src/OAuth2/Storage/ClientCredentialsInterface.php
@@ -35,8 +35,7 @@ interface OAuth2_Storage_ClientCredentialsInterface extends OAuth2_Storage_Clien
* @param $client_id
* Client identifier to be check with.
* @param $grant_type
- * Grant type to be check with, would be one of the values contained in
- * OAuth2::GRANT_TYPE_REGEXP.
+ * Grant type to be check with
*
* @return
* TRUE if the grant type is supported by this client identifier, and
diff --git a/src/OAuth2/Storage/Memory.php b/src/OAuth2/Storage/Memory.php
index c986076..ec5d97a 100644
--- a/src/OAuth2/Storage/Memory.php
+++ b/src/OAuth2/Storage/Memory.php
@@ -58,7 +58,12 @@ class OAuth2_Storage_Memory implements OAuth2_Storage_AuthorizationCodeInterface
public function setUserCredentials($user_credentials)
{
- $this->userCredentials = $user_credentials;
+ return isset($this->userCredentials[$username]) ? $this->userCredentials[$username] : null;
+ }
+
+ public function getUserDetails($username)
+ {
+ return $this->getUser($username);
}
/* ClientCredentialsInterface */
diff --git a/src/OAuth2/Storage/Pdo.php b/src/OAuth2/Storage/Pdo.php
index e806bed..de659e2 100644
--- a/src/OAuth2/Storage/Pdo.php
+++ b/src/OAuth2/Storage/Pdo.php
@@ -5,7 +5,7 @@
*/
class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
OAuth2_Storage_AccessTokenInterface, OAuth2_Storage_ClientCredentialsInterface,
- OAuth2_Storage_UserCredentialsInterface
+ OAuth2_Storage_UserCredentialsInterface, OAuth2_Storage_RefreshTokenInterface
{
private $db;
private $config;
@@ -32,17 +32,18 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->config = array_merge(array(
- 'client_table_name' => 'oauth_clients',
- 'token_table_name' => 'oauth_access_tokens',
- 'code_table_name' => 'oauth_authorization_codes',
- 'user_table_name' => 'oauth_users',
+ 'client_table' => 'oauth_clients',
+ 'access_token_table' => 'oauth_access_tokens',
+ 'refresh_token_table' => 'oauth_refresh_tokens',
+ 'code_table' => 'oauth_authorization_codes',
+ 'user_table' => 'oauth_users',
), $config);
}
/* ClientCredentialsInterface */
public function checkClientCredentials($client_id, $client_secret = null)
{
- $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = "%s"', $this->config['client_table_name'], $client_id));
+ $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = "%s"', $this->config['client_table'], $client_id));
$stmt->execute();
$result = $stmt->fetch();
@@ -52,7 +53,7 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
public function getClientDetails($client_id)
{
- $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = "%s"', $this->config['client_table_name'], $client_id));
+ $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = "%s"', $this->config['client_table'], $client_id));
$stmt->execute();
return $stmt->fetch();
@@ -72,7 +73,7 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
/* AccessTokenInterface */
public function getAccessToken($access_token)
{
- $stmt = $this->db->prepare(sprintf('SELECT * from %s where access_token = "%s"', $this->config['token_table_name'], $access_token));
+ $stmt = $this->db->prepare(sprintf('SELECT * from %s where access_token = "%s"', $this->config['access_token_table'], $access_token));
$token = $stmt->execute();
if ($token = $stmt->fetch()) {
@@ -90,9 +91,9 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
// if it exists, update it.
if ($this->getAccessToken($access_token)) {
- $stmt = $this->db->prepare(sprintf('UPDATE %s SET client_id=:client_id, expires=:expires, user_id=:user_id, scope=:scope where access_token=:access_token', $this->config['token_table_name']));
+ $stmt = $this->db->prepare(sprintf('UPDATE %s SET client_id=:client_id, expires=:expires, user_id=:user_id, scope=:scope where access_token=:access_token', $this->config['access_token_table']));
} else {
- $stmt = $this->db->prepare(sprintf('INSERT INTO %s (access_token, client_id, expires, user_id, scope) VALUES (:access_token, :client_id, :expires, :user_id, :scope)', $this->config['token_table_name']));
+ $stmt = $this->db->prepare(sprintf('INSERT INTO %s (access_token, client_id, expires, user_id, scope) VALUES (:access_token, :client_id, :expires, :user_id, :scope)', $this->config['access_token_table']));
}
return $stmt->execute(compact('access_token', 'client_id', 'user_id', 'expires', 'scope'));
}
@@ -100,7 +101,7 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
/* AuthorizationCodeInterface */
public function getAuthorizationCode($code)
{
- $stmt = $this->db->prepare(sprintf('SELECT * from %s where authorization_code = "%s"', $this->config['code_table_name'], $code));
+ $stmt = $this->db->prepare(sprintf('SELECT * from %s where authorization_code = "%s"', $this->config['code_table'], $code));
$stmt->execute();
if ($code = $stmt->fetch()) {
@@ -118,9 +119,9 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
// if it exists, update it.
if ($this->getAuthorizationCode($code)) {
- $stmt = $this->db->prepare($sql = sprintf('UPDATE %s SET client_id=:client_id, user_id=:user_id, redirect_uri=:redirect_uri, expires=:expires, scope=:scope where authorization_code=:code', $this->config['code_table_name']));
+ $stmt = $this->db->prepare($sql = sprintf('UPDATE %s SET client_id=:client_id, user_id=:user_id, redirect_uri=:redirect_uri, expires=:expires, scope=:scope where authorization_code=:code', $this->config['code_table']));
} else {
- $stmt = $this->db->prepare(sprintf('INSERT INTO %s (authorization_code, client_id, user_id, redirect_uri, expires, scope) VALUES (:code, :client_id, :user_id, :redirect_uri, :expires, :scope)', $this->config['code_table_name']));
+ $stmt = $this->db->prepare(sprintf('INSERT INTO %s (authorization_code, client_id, user_id, redirect_uri, expires, scope) VALUES (:code, :client_id, :user_id, :redirect_uri, :expires, :scope)', $this->config['code_table']));
}
return $stmt->execute(compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope'));
}
@@ -134,6 +135,42 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
return false;
}
+ public function getUserDetails($username)
+ {
+ return $this->getUser($username);
+ }
+
+ /* RefreshTokenInterface */
+ public function getRefreshToken($refresh_token)
+ {
+ $stmt = $this->db->prepare(sprintf('SELECT * FROM %s WHERE refresh_token = "%s"', $this->config['refresh_token_table'], $refresh_token));
+
+ $token = $stmt->execute();
+ if ($token = $stmt->fetch()) {
+ // convert expires to epoch time
+ $token['expires'] = strtotime($token['expires']);
+ }
+
+ return $token;
+ }
+
+ public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = NULL)
+ {
+ // convert expires to datestring
+ $expires = date('Y-m-d H:i:s', $expires);
+
+ $stmt = $this->db->prepare(sprintf('INSERT INTO %s (refresh_token, client_id, user_id, expires, scope) VALUES (:refresh_token, :client_id, :user_id, :expires, :scope)', $this->config['refresh_token_table']));
+
+ return $stmt->execute(compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope'));
+ }
+
+ public function unsetRefreshToken($refresh_token)
+ {
+ $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE refresh_token = "%s"', $this->config['refresh_token_table'], $refresh_token));
+
+ return $stmt->execute();
+ }
+
// plaintext passwords are bad! Override this for your application
protected function checkPassword($user, $password)
{
@@ -142,7 +179,7 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
public function getUser($username)
{
- $stmt = $this->db->prepare($sql = sprintf('SELECT * from %s where username=:username', $this->config['user_table_name']));
+ $stmt = $this->db->prepare($sql = sprintf('SELECT * from %s where username=:username', $this->config['user_table']));
$stmt->execute(array('username' => $username));
return $stmt->fetch();
}
@@ -151,10 +188,10 @@ class OAuth2_Storage_Pdo implements OAuth2_Storage_AuthorizationCodeInterface,
{
// if it exists, update it.
if ($this->getUser($username)) {
- $stmt = $this->db->prepare($sql = sprintf('UPDATE %s SET username=:username, password=:password, first_name=:firstName, last_name=:lastName where username=:username', $this->config['user_table_name']));
+ $stmt = $this->db->prepare($sql = sprintf('UPDATE %s SET username=:username, password=:password, first_name=:firstName, last_name=:lastName where username=:username', $this->config['user_table']));
} else {
- $stmt = $this->db->prepare(sprintf('INSERT INTO %s (username, password, first_name, last_name) VALUES (:username, :password, :firstName, :lastName)', $this->config['user_table_name']));
+ $stmt = $this->db->prepare(sprintf('INSERT INTO %s (username, password, first_name, last_name) VALUES (:username, :password, :firstName, :lastName)', $this->config['user_table']));
}
return $stmt->execute(compact('username', 'password', 'firstName', 'lastName'));
}
-} \ No newline at end of file
+}
diff --git a/src/OAuth2/Storage/UserCredentialsInterface.php b/src/OAuth2/Storage/UserCredentialsInterface.php
index 8ecf866..9fff562 100644
--- a/src/OAuth2/Storage/UserCredentialsInterface.php
+++ b/src/OAuth2/Storage/UserCredentialsInterface.php
@@ -3,13 +3,13 @@
/**
* Storage engines that support the "Resource Owner Password Credentials"
* grant type should implement this interface
- *
+ *
* @author Dave Rochwerger <catch.dave@gmail.com>
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-4.3
*/
interface OAuth2_Storage_UserCredentialsInterface
{
-
+
/**
* Grant access tokens for basic user credentials.
*
@@ -42,4 +42,12 @@ interface OAuth2_Storage_UserCredentialsInterface
* @ingroup oauth2_section_4
*/
public function checkUserCredentials($username, $password);
+
+ /**
+ * @return
+ * ARRAY the associated "scope" or "user_id" values if applicable, or an empty array
+ * if this does not apply
+ *
+ */
+ public function getUserDetails($username);
} \ No newline at end of file
diff --git a/src/OAuth2/TokenType/Bearer.php b/src/OAuth2/TokenType/Bearer.php
index bcccd08..08492a4 100644
--- a/src/OAuth2/TokenType/Bearer.php
+++ b/src/OAuth2/TokenType/Bearer.php
@@ -42,14 +42,10 @@ class OAuth2_TokenType_Bearer implements OAuth2_TokenTypeInterface, OAuth2_Respo
* Old Android version bug (at least with version 2.2)
* @see http://code.google.com/p/android/issues/detail?id=6684
*
- * We don't want to test this functionality as it relies on superglobals and headers:
- * @codeCoverageIgnoreStart
*/
- public function getAccessTokenParameter(OAuth2_Request $request)
+ public function getAccessTokenParameter(OAuth2_RequestInterface $request)
{
- if (isset($request->server['AUTHORIZATION'])) {
- $headers = $request->server['AUTHORIZATION'];
- }
+ $headers = $request->server('AUTHORIZATION');
// Check that exactly one method was used
$methodsUsed = !empty($headers) + !is_null($request->query($this->config['token_param_name'])) + !is_null($request->request($this->config['token_param_name']));
diff --git a/src/OAuth2/TokenType/MAC.php b/src/OAuth2/TokenType/MAC.php
index c809a3b..6d47932 100644
--- a/src/OAuth2/TokenType/MAC.php
+++ b/src/OAuth2/TokenType/MAC.php
@@ -10,7 +10,7 @@ class OAuth2_TokenType_MAC implements OAuth2_TokenTypeInterface
return 'mac';
}
- public function getAccessTokenParameter(OAuth2_Request $request)
+ public function getAccessTokenParameter(OAuth2_RequestInterface $request)
{
throw new LogicException("Not supported");
diff --git a/src/OAuth2/TokenTypeInterface.php b/src/OAuth2/TokenTypeInterface.php
index ab8ac9f..27ca292 100644
--- a/src/OAuth2/TokenTypeInterface.php
+++ b/src/OAuth2/TokenTypeInterface.php
@@ -3,5 +3,5 @@
interface OAuth2_TokenTypeInterface
{
public function getTokenType();
- public function getAccessTokenParameter(OAuth2_Request $request);
+ public function getAccessTokenParameter(OAuth2_RequestInterface $request);
} \ No newline at end of file