blob: ef6120300ac5fc551b696d9a633607e8cfacf9a1 [file] [log] [blame]
<?php
namespace OAuth2\ClientAssertionType;
use OAuth2\Storage\ClientCredentialsInterface;
use OAuth2\RequestInterface;
use OAuth2\ResponseInterface;
use LogicException;
/**
* Validate a client via Http Basic authentication
*
* @author Brent Shaffer <bshafs at gmail dot com>
*/
class HttpBasic implements ClientAssertionTypeInterface
{
private $clientData;
protected $storage;
protected $config;
/**
* Config array $config should look as follows:
* @code
* $config = array(
* 'allow_credentials_in_request_body' => true, // whether to look for credentials in the POST body in addition to the Authorize HTTP Header
* 'allow_public_clients' => true // if true, "public clients" (clients without a secret) may be authenticated
* );
* @endcode
*
* @param ClientCredentialsInterface $storage Storage
* @param array $config Configuration options for the server
*/
public function __construct(ClientCredentialsInterface $storage, array $config = array())
{
$this->storage = $storage;
$this->config = array_merge(array(
'allow_credentials_in_request_body' => true,
'allow_public_clients' => true,
), $config);
}
/**
* Validate the OAuth request
*
* @param RequestInterface $request
* @param ResponseInterface $response
* @return bool|mixed
* @throws LogicException
*/
public function validateRequest(RequestInterface $request, ResponseInterface $response)
{
if (!$clientData = $this->getClientCredentials($request, $response)) {
return false;
}
if (!isset($clientData['client_id'])) {
throw new LogicException('the clientData array must have "client_id" set');
}
if (!isset($clientData['client_secret']) || $clientData['client_secret'] == '') {
if (!$this->config['allow_public_clients']) {
$response->setError(400, 'invalid_client', 'client credentials are required');
return false;
}
if (!$this->storage->isPublicClient($clientData['client_id'])) {
$response->setError(400, 'invalid_client', 'This client is invalid or must authenticate using a client secret');
return false;
}
} elseif ($this->storage->checkClientCredentials($clientData['client_id'], $clientData['client_secret']) === false) {
$response->setError(400, 'invalid_client', 'The client credentials are invalid');
return false;
}
$this->clientData = $clientData;
return true;
}
/**
* Get the client id
*
* @return mixed
*/
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.
*
* @param RequestInterface $request
* @param ResponseInterface $response
* @return array|null 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, // OPTIONAL the client secret (may be omitted for public clients)
* );
* @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) {
$message = $this->config['allow_credentials_in_request_body'] ? ' or body' : '';
$response->setError(400, 'invalid_client', 'Client credentials were not found in the headers'.$message);
}
return null;
}
}