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