PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/OAuth2/Storage/Pdo.php

https://github.com/rich-choy/oauth2-server-php
PHP | 241 lines | 165 code | 42 blank | 34 comment | 17 complexity | e4522d49b847ec6f66031835f9a9526d MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. namespace OAuth2\Storage;
  3. /**
  4. * Simple PDO storage for all storage types
  5. *
  6. * NOTE: This class is meant to get users started
  7. * quickly. If your application requires further
  8. * customization, extend this class or create your own.
  9. *
  10. * NOTE: Passwords are stored in plaintext, which is never
  11. * a good idea. Be sure to override this for your application
  12. *
  13. * @author Brent Shaffer <bshafs at gmail dot com>
  14. */
  15. class Pdo implements AuthorizationCodeInterface,
  16. AccessTokenInterface,
  17. ClientCredentialsInterface,
  18. UserCredentialsInterface,
  19. RefreshTokenInterface,
  20. JwtBearerInterface
  21. {
  22. protected $db;
  23. protected $config;
  24. public function __construct($connection, $config = array())
  25. {
  26. if (!$connection instanceof \PDO) {
  27. if (!is_array($connection)) {
  28. throw new \InvalidArgumentException('First argument to OAuth2\Storage\Pdo must be an instance of PDO or a configuration array');
  29. }
  30. if (!isset($connection['dsn'])) {
  31. throw new \InvalidArgumentException('configuration array must contain "dsn"');
  32. }
  33. // merge optional parameters
  34. $connection = array_merge(array(
  35. 'username' => null,
  36. 'password' => null,
  37. ), $connection);
  38. $connection = new \PDO($connection['dsn'], $connection['username'], $connection['password']);
  39. }
  40. $this->db = $connection;
  41. // debugging
  42. $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
  43. $this->config = array_merge(array(
  44. 'client_table' => 'oauth_clients',
  45. 'access_token_table' => 'oauth_access_tokens',
  46. 'refresh_token_table' => 'oauth_refresh_tokens',
  47. 'code_table' => 'oauth_authorization_codes',
  48. 'user_table' => 'oauth_users',
  49. 'jwt_table' => 'oauth_jwt',
  50. ), $config);
  51. }
  52. /* OAuth2_Storage_ClientCredentialsInterface */
  53. public function checkClientCredentials($client_id, $client_secret = null)
  54. {
  55. $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = :client_id', $this->config['client_table']));
  56. $stmt->execute(compact('client_id'));
  57. $result = $stmt->fetch();
  58. // make this extensible
  59. return $result['client_secret'] == $client_secret;
  60. }
  61. public function getClientDetails($client_id)
  62. {
  63. $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = :client_id', $this->config['client_table']));
  64. $stmt->execute(compact('client_id'));
  65. return $stmt->fetch();
  66. }
  67. public function checkRestrictedGrantType($client_id, $grant_type)
  68. {
  69. $details = $this->getClientDetails($client_id);
  70. if (isset($details['grant_types'])) {
  71. $grant_types = explode(' ', $details['grant_types']);
  72. return in_array($grant_type, (array) $grant_types);
  73. }
  74. // if grant_types are not defined, then none are restricted
  75. return true;
  76. }
  77. /* OAuth2_Storage_AccessTokenInterface */
  78. public function getAccessToken($access_token)
  79. {
  80. $stmt = $this->db->prepare(sprintf('SELECT * from %s where access_token = :access_token', $this->config['access_token_table']));
  81. $token = $stmt->execute(compact('access_token'));
  82. if ($token = $stmt->fetch()) {
  83. // convert date string back to timestamp
  84. $token['expires'] = strtotime($token['expires']);
  85. }
  86. return $token;
  87. }
  88. public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null)
  89. {
  90. // convert expires to datestring
  91. $expires = date('Y-m-d H:i:s', $expires);
  92. // if it exists, update it.
  93. if ($this->getAccessToken($access_token)) {
  94. $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']));
  95. } else {
  96. $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']));
  97. }
  98. return $stmt->execute(compact('access_token', 'client_id', 'user_id', 'expires', 'scope'));
  99. }
  100. /* OAuth2_Storage_AuthorizationCodeInterface */
  101. public function getAuthorizationCode($code)
  102. {
  103. $stmt = $this->db->prepare(sprintf('SELECT * from %s where authorization_code = :code', $this->config['code_table']));
  104. $stmt->execute(compact('code'));
  105. if ($code = $stmt->fetch()) {
  106. // convert date string back to timestamp
  107. $code['expires'] = strtotime($code['expires']);
  108. }
  109. return $code;
  110. }
  111. public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null)
  112. {
  113. // convert expires to datestring
  114. $expires = date('Y-m-d H:i:s', $expires);
  115. // if it exists, update it.
  116. if ($this->getAuthorizationCode($code)) {
  117. $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']));
  118. } else {
  119. $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']));
  120. }
  121. return $stmt->execute(compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope'));
  122. }
  123. public function expireAuthorizationCode($code)
  124. {
  125. $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE authorization_code = :code', $this->config['code_table']));
  126. return $stmt->execute(compact('code'));
  127. }
  128. /* OAuth2_Storage_UserCredentialsInterface */
  129. public function checkUserCredentials($username, $password)
  130. {
  131. if ($user = $this->getUser($username)) {
  132. return $this->checkPassword($user, $password);
  133. }
  134. return false;
  135. }
  136. public function getUserDetails($username)
  137. {
  138. return $this->getUser($username);
  139. }
  140. /* OAuth2_Storage_RefreshTokenInterface */
  141. public function getRefreshToken($refresh_token)
  142. {
  143. $stmt = $this->db->prepare(sprintf('SELECT * FROM %s WHERE refresh_token = :refresh_token', $this->config['refresh_token_table']));
  144. $token = $stmt->execute(compact('refresh_token'));
  145. if ($token = $stmt->fetch()) {
  146. // convert expires to epoch time
  147. $token['expires'] = strtotime($token['expires']);
  148. }
  149. return $token;
  150. }
  151. public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null)
  152. {
  153. // convert expires to datestring
  154. $expires = date('Y-m-d H:i:s', $expires);
  155. $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']));
  156. return $stmt->execute(compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope'));
  157. }
  158. public function unsetRefreshToken($refresh_token)
  159. {
  160. $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE refresh_token = :refresh_token', $this->config['refresh_token_table']));
  161. return $stmt->execute(compact('refresh_token'));
  162. }
  163. // plaintext passwords are bad! Override this for your application
  164. protected function checkPassword($user, $password)
  165. {
  166. return $user['password'] == sha1($password);
  167. }
  168. public function getUser($username)
  169. {
  170. $stmt = $this->db->prepare($sql = sprintf('SELECT * from %s where username=:username', $this->config['user_table']));
  171. $stmt->execute(array('username' => $username));
  172. if (!$userInfo = $stmt->fetch()) {
  173. return false;
  174. }
  175. // the default behavior is to use "username" as the user_id
  176. return array_merge(array(
  177. 'user_id' => $username
  178. ), $userInfo);
  179. }
  180. public function setUser($username, $password, $firstName = null, $lastName = null)
  181. {
  182. // do not store in plaintext
  183. $password = sha1($password);
  184. // if it exists, update it.
  185. if ($this->getUser($username)) {
  186. $stmt = $this->db->prepare($sql = sprintf('UPDATE %s SET password=:password, first_name=:firstName, last_name=:lastName where username=:username', $this->config['user_table']));
  187. } else {
  188. $stmt = $this->db->prepare(sprintf('INSERT INTO %s (username, password, first_name, last_name) VALUES (:username, :password, :firstName, :lastName)', $this->config['user_table']));
  189. }
  190. return $stmt->execute(compact('username', 'password', 'firstName', 'lastName'));
  191. }
  192. /* OAuth2_Storage_JWTBearerInterface */
  193. public function getClientKey($client_id, $subject)
  194. {
  195. $stmt = $this->db->prepare($sql = sprintf('SELECT public_key from %s where client_id=:client_id AND subject=:subject', $this->config['jwt_table']));
  196. $stmt->execute(array('client_id' => $client_id, 'subject' => $subject));
  197. return $stmt->fetch();
  198. }
  199. }