30 OpenIDAuthorizationCodeInterface
37 if (!$connection instanceof \PDO) {
38 if (is_string($connection)) {
39 $connection = array(
'dsn' => $connection);
41 if (!is_array($connection)) {
42 throw new \InvalidArgumentException(
'First argument to OAuth2\Storage\Pdo must be an instance of PDO, a DSN string, or a configuration array');
44 if (!isset($connection[
'dsn'])) {
45 throw new \InvalidArgumentException(
'configuration array must contain "dsn"');
48 $connection = array_merge(array(
53 $connection = new \PDO($connection[
'dsn'], $connection[
'username'], $connection[
'password'], $connection[
'options']);
55 $this->db = $connection;
58 $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
60 $this->config = array_merge(array(
61 'client_table' =>
'oauth_clients',
62 'access_token_table' =>
'oauth_access_tokens',
63 'refresh_token_table' =>
'oauth_refresh_tokens',
64 'code_table' =>
'oauth_authorization_codes',
65 'user_table' =>
'oauth_users',
66 'jwt_table' =>
'oauth_jwt',
67 'jti_table' =>
'oauth_jti',
68 'scope_table' =>
'oauth_scopes',
69 'public_key_table' =>
'oauth_public_keys',
76 $stmt = $this->db->prepare(sprintf(
'SELECT * from %s where client_id = :client_id', $this->config[
'client_table']));
77 $stmt->execute(compact(
'client_id'));
78 $result = $stmt->fetch(\PDO::FETCH_ASSOC);
81 return $result && $result[
'client_secret'] == $client_secret;
86 $stmt = $this->db->prepare(sprintf(
'SELECT * from %s where client_id = :client_id', $this->config[
'client_table']));
87 $stmt->execute(compact(
'client_id'));
89 if (!$result = $stmt->fetch(\PDO::FETCH_ASSOC)) {
93 return empty($result[
'client_secret']);
99 $stmt = $this->db->prepare(sprintf(
'SELECT * from %s where client_id = :client_id', $this->config[
'client_table']));
100 $stmt->execute(compact(
'client_id'));
102 return $stmt->fetch(\PDO::FETCH_ASSOC);
105 public function setClientDetails($client_id, $client_secret =
null, $redirect_uri =
null, $grant_types =
null, $scope =
null, $user_id =
null)
109 $stmt = $this->db->prepare($sql = sprintf(
'UPDATE %s SET client_secret=:client_secret, redirect_uri=:redirect_uri, grant_types=:grant_types, scope=:scope, user_id=:user_id where client_id=:client_id', $this->config[
'client_table']));
111 $stmt = $this->db->prepare(sprintf(
'INSERT INTO %s (client_id, client_secret, redirect_uri, grant_types, scope, user_id) VALUES (:client_id, :client_secret, :redirect_uri, :grant_types, :scope, :user_id)', $this->config[
'client_table']));
114 return $stmt->execute(compact(
'client_id',
'client_secret',
'redirect_uri',
'grant_types',
'scope',
'user_id'));
120 if (isset($details[
'grant_types'])) {
121 $grant_types = explode(
' ', $details[
'grant_types']);
123 return in_array($grant_type, (array) $grant_types);
133 $stmt = $this->db->prepare(sprintf(
'SELECT * from %s where access_token = :access_token', $this->config[
'access_token_table']));
135 $token = $stmt->execute(compact(
'access_token'));
136 if ($token = $stmt->fetch(\PDO::FETCH_ASSOC)) {
138 $token[
'expires'] = strtotime($token[
'expires']);
144 public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope =
null)
147 $expires = date(
'Y-m-d H:i:s', $expires);
151 $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']));
153 $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']));
156 return $stmt->execute(compact(
'access_token',
'client_id',
'user_id',
'expires',
'scope'));
161 $stmt = $this->db->prepare(sprintf(
'DELETE FROM %s WHERE access_token = :access_token', $this->config[
'access_token_table']));
163 return $stmt->execute(compact(
'access_token'));
169 $stmt = $this->db->prepare(sprintf(
'SELECT * from %s where authorization_code = :code', $this->config[
'code_table']));
170 $stmt->execute(compact(
'code'));
172 if ($code = $stmt->fetch(\PDO::FETCH_ASSOC)) {
174 $code[
'expires'] = strtotime($code[
'expires']);
180 public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope =
null, $id_token =
null)
182 if (func_num_args() > 6) {
184 return call_user_func_array(array($this,
'setAuthorizationCodeWithIdToken'), func_get_args());
188 $expires = date(
'Y-m-d H:i:s', $expires);
192 $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']));
194 $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']));
197 return $stmt->execute(compact(
'code',
'client_id',
'user_id',
'redirect_uri',
'expires',
'scope'));
200 private function setAuthorizationCodeWithIdToken($code, $client_id, $user_id, $redirect_uri, $expires, $scope =
null, $id_token =
null)
203 $expires = date(
'Y-m-d H:i:s', $expires);
207 $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, id_token =:id_token where authorization_code=:code', $this->config[
'code_table']));
209 $stmt = $this->db->prepare(sprintf(
'INSERT INTO %s (authorization_code, client_id, user_id, redirect_uri, expires, scope, id_token) VALUES (:code, :client_id, :user_id, :redirect_uri, :expires, :scope, :id_token)', $this->config[
'code_table']));
212 return $stmt->execute(compact(
'code',
'client_id',
'user_id',
'redirect_uri',
'expires',
'scope',
'id_token'));
217 $stmt = $this->db->prepare(sprintf(
'DELETE FROM %s WHERE authorization_code = :code', $this->config[
'code_table']));
219 return $stmt->execute(compact(
'code'));
225 if ($user = $this->
getUser($username)) {
234 return $this->
getUser($username);
244 $claims = explode(
' ', trim($claims));
245 $userClaims = array();
248 $validClaims = explode(
' ', self::VALID_CLAIMS);
249 foreach ($validClaims
as $validClaim) {
250 if (in_array($validClaim, $claims)) {
251 if ($validClaim ==
'address') {
253 $userClaims[
'address'] = $this->
getUserClaim($validClaim, $userDetails[
'address'] ?: $userDetails);
255 $userClaims = array_merge($userClaims, $this->
getUserClaim($validClaim, $userDetails));
265 $userClaims = array();
266 $claimValuesString = constant(sprintf(
'self::%s_CLAIM_VALUES', strtoupper($claim)));
267 $claimValues = explode(
' ', $claimValuesString);
269 foreach ($claimValues
as $value) {
270 $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] :
null;
279 $stmt = $this->db->prepare(sprintf(
'SELECT * FROM %s WHERE refresh_token = :refresh_token', $this->config[
'refresh_token_table']));
281 $token = $stmt->execute(compact(
'refresh_token'));
282 if ($token = $stmt->fetch(\PDO::FETCH_ASSOC)) {
284 $token[
'expires'] = strtotime($token[
'expires']);
290 public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope =
null)
293 $expires = date(
'Y-m-d H:i:s', $expires);
295 $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']));
297 return $stmt->execute(compact(
'refresh_token',
'client_id',
'user_id',
'expires',
'scope'));
302 $stmt = $this->db->prepare(sprintf(
'DELETE FROM %s WHERE refresh_token = :refresh_token', $this->config[
'refresh_token_table']));
304 return $stmt->execute(compact(
'refresh_token'));
310 return $user[
'password'] == sha1($password);
315 $stmt = $this->db->prepare($sql = sprintf(
'SELECT * from %s where username=:username', $this->config[
'user_table']));
316 $stmt->execute(array(
'username' => $username));
318 if (!$userInfo = $stmt->fetch(\PDO::FETCH_ASSOC)) {
323 return array_merge(array(
324 'user_id' => $username
328 public function setUser($username, $password, $firstName =
null, $lastName =
null)
331 $password = sha1($password);
334 if ($this->
getUser($username)) {
335 $stmt = $this->db->prepare($sql = sprintf(
'UPDATE %s SET password=:password, first_name=:firstName, last_name=:lastName where username=:username', $this->config[
'user_table']));
337 $stmt = $this->db->prepare(sprintf(
'INSERT INTO %s (username, password, first_name, last_name) VALUES (:username, :password, :firstName, :lastName)', $this->config[
'user_table']));
340 return $stmt->execute(compact(
'username',
'password',
'firstName',
'lastName'));
346 $scope = explode(
' ', $scope);
347 $whereIn = implode(
',', array_fill(0, count($scope),
'?'));
348 $stmt = $this->db->prepare(sprintf(
'SELECT count(scope) as count FROM %s WHERE scope IN (%s)', $this->config[
'scope_table'], $whereIn));
349 $stmt->execute($scope);
351 if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) {
352 return $result[
'count'] == count($scope);
360 $stmt = $this->db->prepare(sprintf(
'SELECT scope FROM %s WHERE is_default=:is_default', $this->config[
'scope_table']));
361 $stmt->execute(array(
'is_default' =>
true));
363 if ($result = $stmt->fetchAll(\PDO::FETCH_ASSOC)) {
364 $defaultScope = array_map(
function ($row) {
365 return $row[
'scope'];
368 return implode(
' ', $defaultScope);
377 $stmt = $this->db->prepare($sql = sprintf(
'SELECT public_key from %s where client_id=:client_id AND subject=:subject', $this->config[
'jwt_table']));
379 $stmt->execute(array(
'client_id' => $client_id,
'subject' => $subject));
381 return $stmt->fetchColumn();
390 if (isset($clientDetails[
'scope'])) {
391 return $clientDetails[
'scope'];
397 public function getJti($client_id, $subject, $audience, $expires, $jti)
399 $stmt = $this->db->prepare($sql = sprintf(
'SELECT * FROM %s WHERE issuer=:client_id AND subject=:subject AND audience=:audience AND expires=:expires AND jti=:jti', $this->config[
'jti_table']));
401 $stmt->execute(compact(
'client_id',
'subject',
'audience',
'expires',
'jti'));
403 if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) {
405 'issuer' => $result[
'issuer'],
406 'subject' => $result[
'subject'],
407 'audience' => $result[
'audience'],
408 'expires' => $result[
'expires'],
409 'jti' => $result[
'jti'],
416 public function setJti($client_id, $subject, $audience, $expires, $jti)
418 $stmt = $this->db->prepare(sprintf(
'INSERT INTO %s (issuer, subject, audience, expires, jti) VALUES (:client_id, :subject, :audience, :expires, :jti)', $this->config[
'jti_table']));
420 return $stmt->execute(compact(
'client_id',
'subject',
'audience',
'expires',
'jti'));
426 $stmt = $this->db->prepare($sql = sprintf(
'SELECT public_key FROM %s WHERE client_id=:client_id OR client_id IS NULL ORDER BY client_id IS NOT NULL DESC', $this->config[
'public_key_table']));
428 $stmt->execute(compact(
'client_id'));
429 if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) {
430 return $result[
'public_key'];
436 $stmt = $this->db->prepare($sql = sprintf(
'SELECT private_key FROM %s WHERE client_id=:client_id OR client_id IS NULL ORDER BY client_id IS NOT NULL DESC', $this->config[
'public_key_table']));
438 $stmt->execute(compact(
'client_id'));
439 if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) {
440 return $result[
'private_key'];
446 $stmt = $this->db->prepare($sql = sprintf(
'SELECT encryption_algorithm FROM %s WHERE client_id=:client_id OR client_id IS NULL ORDER BY client_id IS NOT NULL DESC', $this->config[
'public_key_table']));
448 $stmt->execute(compact(
'client_id'));
449 if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) {
450 return $result[
'encryption_algorithm'];
464 CREATE TABLE {$this->config['client_table']} (
465 client_id VARCHAR(80) NOT NULL,
466 client_secret VARCHAR(80) NOT NULL,
467 redirect_uri VARCHAR(2000),
468 grant_types VARCHAR(80),
471 PRIMARY KEY (client_id)
474 CREATE TABLE {$this->config['access_token_table']} (
475 access_token VARCHAR(40) NOT NULL,
476 client_id VARCHAR(80) NOT NULL,
478 expires TIMESTAMP NOT NULL,
480 PRIMARY KEY (access_token)
483 CREATE TABLE {$this->config['code_table']} (
484 authorization_code VARCHAR(40) NOT NULL,
485 client_id VARCHAR(80) NOT NULL,
487 redirect_uri VARCHAR(2000),
488 expires TIMESTAMP NOT NULL,
490 id_token VARCHAR(1000),
491 PRIMARY KEY (authorization_code)
494 CREATE TABLE {$this->config['refresh_token_table']} (
495 refresh_token VARCHAR(40) NOT NULL,
496 client_id VARCHAR(80) NOT NULL,
498 expires TIMESTAMP NOT NULL,
500 PRIMARY KEY (refresh_token)
503 CREATE TABLE {$this->config['user_table']} (
504 username VARCHAR(80),
505 password VARCHAR(80),
506 first_name VARCHAR(80),
507 last_name VARCHAR(80),
509 email_verified BOOLEAN,
513 CREATE TABLE {$this->config['scope_table']} (
514 scope VARCHAR(80) NOT NULL,
519 CREATE TABLE {$this->config['jwt_table']} (
520 client_id VARCHAR(80) NOT NULL,
522 public_key VARCHAR(2000) NOT NULL
525 CREATE TABLE {$this->config['jti_table']} (
526 issuer VARCHAR(80) NOT NULL,
528 audiance VARCHAR(80),
529 expires TIMESTAMP NOT NULL,
530 jti VARCHAR(2000) NOT NULL
533 CREATE TABLE {$this->config['public_key_table']} (
534 client_id VARCHAR(80),
535 public_key VARCHAR(2000),
536 private_key VARCHAR(2000),
537 encryption_algorithm VARCHAR(100) DEFAULT 'RS256'