HttpBasic.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <?php
  2. namespace OAuth2\ClientAssertionType;
  3. use OAuth2\Storage\ClientCredentialsInterface;
  4. use OAuth2\RequestInterface;
  5. use OAuth2\ResponseInterface;
  6. use LogicException;
  7. /**
  8. * Validate a client via Http Basic authentication
  9. *
  10. * @author Brent Shaffer <bshafs at gmail dot com>
  11. */
  12. class HttpBasic implements ClientAssertionTypeInterface
  13. {
  14. private $clientData;
  15. protected $storage;
  16. protected $config;
  17. /**
  18. * Config array $config should look as follows:
  19. * @code
  20. * $config = array(
  21. * 'allow_credentials_in_request_body' => true, // whether to look for credentials in the POST body in addition to the Authorize HTTP Header
  22. * 'allow_public_clients' => true // if true, "public clients" (clients without a secret) may be authenticated
  23. * );
  24. * @endcode
  25. *
  26. * @param ClientCredentialsInterface $storage Storage
  27. * @param array $config Configuration options for the server
  28. */
  29. public function __construct(ClientCredentialsInterface $storage, array $config = array())
  30. {
  31. $this->storage = $storage;
  32. $this->config = array_merge(array(
  33. 'allow_credentials_in_request_body' => true,
  34. 'allow_public_clients' => true,
  35. ), $config);
  36. }
  37. /**
  38. * Validate the OAuth request
  39. *
  40. * @param RequestInterface $request
  41. * @param ResponseInterface $response
  42. * @return bool|mixed
  43. * @throws LogicException
  44. */
  45. public function validateRequest(RequestInterface $request, ResponseInterface $response)
  46. {
  47. if (!$clientData = $this->getClientCredentials($request, $response)) {
  48. return false;
  49. }
  50. if (!isset($clientData['client_id'])) {
  51. throw new LogicException('the clientData array must have "client_id" set');
  52. }
  53. if (!isset($clientData['client_secret']) || $clientData['client_secret'] == '') {
  54. if (!$this->config['allow_public_clients']) {
  55. $response->setError(400, 'invalid_client', 'client credentials are required');
  56. return false;
  57. }
  58. if (!$this->storage->isPublicClient($clientData['client_id'])) {
  59. $response->setError(400, 'invalid_client', 'This client is invalid or must authenticate using a client secret');
  60. return false;
  61. }
  62. } elseif ($this->storage->checkClientCredentials($clientData['client_id'], $clientData['client_secret']) === false) {
  63. $response->setError(400, 'invalid_client', 'The client credentials are invalid');
  64. return false;
  65. }
  66. $this->clientData = $clientData;
  67. return true;
  68. }
  69. /**
  70. * Get the client id
  71. *
  72. * @return mixed
  73. */
  74. public function getClientId()
  75. {
  76. return $this->clientData['client_id'];
  77. }
  78. /**
  79. * Internal function used to get the client credentials from HTTP basic
  80. * auth or POST data.
  81. *
  82. * According to the spec (draft 20), the client_id can be provided in
  83. * the Basic Authorization header (recommended) or via GET/POST.
  84. *
  85. * @param RequestInterface $request
  86. * @param ResponseInterface $response
  87. * @return array|null A list containing the client identifier and password, for example:
  88. * @code
  89. * return array(
  90. * "client_id" => CLIENT_ID, // REQUIRED the client id
  91. * "client_secret" => CLIENT_SECRET, // OPTIONAL the client secret (may be omitted for public clients)
  92. * );
  93. * @endcode
  94. *
  95. * @see http://tools.ietf.org/html/rfc6749#section-2.3.1
  96. *
  97. * @ingroup oauth2_section_2
  98. */
  99. public function getClientCredentials(RequestInterface $request, ResponseInterface $response = null)
  100. {
  101. if (!is_null($request->headers('PHP_AUTH_USER')) && !is_null($request->headers('PHP_AUTH_PW'))) {
  102. return array('client_id' => $request->headers('PHP_AUTH_USER'), 'client_secret' => $request->headers('PHP_AUTH_PW'));
  103. }
  104. if ($this->config['allow_credentials_in_request_body']) {
  105. // Using POST for HttpBasic authorization is not recommended, but is supported by specification
  106. if (!is_null($request->request('client_id'))) {
  107. /**
  108. * client_secret can be null if the client's password is an empty string
  109. * @see http://tools.ietf.org/html/rfc6749#section-2.3.1
  110. */
  111. return array('client_id' => $request->request('client_id'), 'client_secret' => $request->request('client_secret'));
  112. }
  113. }
  114. if ($response) {
  115. $message = $this->config['allow_credentials_in_request_body'] ? ' or body' : '';
  116. $response->setError(400, 'invalid_client', 'Client credentials were not found in the headers'.$message);
  117. }
  118. return null;
  119. }
  120. }