Cheetah
DynamoDB.php
Go to the documentation of this file.
1 <?php
2 
3 namespace OAuth2\Storage;
4 
5 use Aws\DynamoDb\DynamoDbClient;
6 
8 use OAuth2\OpenID\Storage\AuthorizationCodeInterface as OpenIDAuthorizationCodeInterface;
34 class DynamoDB implements
44  OpenIDAuthorizationCodeInterface
45 {
46  protected $client;
47  protected $config;
48 
49  public function __construct($connection, $config = array())
50  {
51  if (!($connection instanceof DynamoDbClient)) {
52  if (!is_array($connection)) {
53  throw new \InvalidArgumentException('First argument to OAuth2\Storage\Dynamodb must be an instance a configuration array containt key, secret, region');
54  }
55  if (!array_key_exists("key",$connection) || !array_key_exists("secret",$connection) || !array_key_exists("region",$connection) ) {
56  throw new \InvalidArgumentException('First argument to OAuth2\Storage\Dynamodb must be an instance a configuration array containt key, secret, region');
57  }
58  $this->client = DynamoDbClient::factory(array(
59  'key' => $connection["key"],
60  'secret' => $connection["secret"],
61  'region' =>$connection["region"]
62  ));
63  } else {
64  $this->client = $connection;
65  }
66 
67  $this->config = array_merge(array(
68  'client_table' => 'oauth_clients',
69  'access_token_table' => 'oauth_access_tokens',
70  'refresh_token_table' => 'oauth_refresh_tokens',
71  'code_table' => 'oauth_authorization_codes',
72  'user_table' => 'oauth_users',
73  'jwt_table' => 'oauth_jwt',
74  'scope_table' => 'oauth_scopes',
75  'public_key_table' => 'oauth_public_keys',
76  ), $config);
77  }
78 
79  /* OAuth2\Storage\ClientCredentialsInterface */
80  public function checkClientCredentials($client_id, $client_secret = null)
81  {
82  $result = $this->client->getItem(array(
83  "TableName"=> $this->config['client_table'],
84  "Key" => array('client_id' => array('S' => $client_id))
85  ));
86 
87  return $result->count()==1 && $result["Item"]["client_secret"]["S"] == $client_secret;
88  }
89 
90  public function isPublicClient($client_id)
91  {
92  $result = $this->client->getItem(array(
93  "TableName"=> $this->config['client_table'],
94  "Key" => array('client_id' => array('S' => $client_id))
95  ));
96 
97  if ($result->count()==0) {
98  return false ;
99  }
100 
101  return empty($result["Item"]["client_secret"]);
102  }
103 
104  /* OAuth2\Storage\ClientInterface */
105  public function getClientDetails($client_id)
106  {
107  $result = $this->client->getItem(array(
108  "TableName"=> $this->config['client_table'],
109  "Key" => array('client_id' => array('S' => $client_id))
110  ));
111  if ($result->count()==0) {
112  return false ;
113  }
114  $result = $this->dynamo2array($result);
115  foreach (array('client_id', 'client_secret', 'redirect_uri', 'grant_types', 'scope', 'user_id') as $key => $val) {
116  if (!array_key_exists ($val, $result)) {
117  $result[$val] = null;
118  }
119  }
120 
121  return $result;
122  }
123 
124  public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null)
125  {
126  $clientData = compact('client_id', 'client_secret', 'redirect_uri', 'grant_types', 'scope', 'user_id');
127  $clientData = array_filter($clientData, function ($value) { return !is_null($value); });
128 
129  $result = $this->client->putItem(array(
130  'TableName' => $this->config['client_table'],
131  'Item' => $this->client->formatAttributes($clientData)
132  ));
133 
134  return true;
135  }
136 
137  public function checkRestrictedGrantType($client_id, $grant_type)
138  {
139  $details = $this->getClientDetails($client_id);
140  if (isset($details['grant_types'])) {
141  $grant_types = explode(' ', $details['grant_types']);
142 
143  return in_array($grant_type, (array) $grant_types);
144  }
145 
146  // if grant_types are not defined, then none are restricted
147  return true;
148  }
149 
150  /* OAuth2\Storage\AccessTokenInterface */
151  public function getAccessToken($access_token)
152  {
153  $result = $this->client->getItem(array(
154  "TableName"=> $this->config['access_token_table'],
155  "Key" => array('access_token' => array('S' => $access_token))
156  ));
157  if ($result->count()==0) {
158  return false ;
159  }
160  $token = $this->dynamo2array($result);
161  if (array_key_exists ('expires', $token)) {
162  $token['expires'] = strtotime($token['expires']);
163  }
164 
165  return $token;
166  }
167 
168  public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null)
169  {
170  // convert expires to datestring
171  $expires = date('Y-m-d H:i:s', $expires);
172 
173  $clientData = compact('access_token', 'client_id', 'user_id', 'expires', 'scope');
174  $clientData = array_filter($clientData, function ($value) { return !empty($value); });
175 
176  $result = $this->client->putItem(array(
177  'TableName' => $this->config['access_token_table'],
178  'Item' => $this->client->formatAttributes($clientData)
179  ));
180 
181  return true;
182 
183  }
184 
185  public function unsetAccessToken($access_token)
186  {
187  $result = $this->client->deleteItem(array(
188  'TableName' => $this->config['access_token_table'],
189  'Key' => $this->client->formatAttributes(array("access_token" => $access_token))
190  ));
191 
192  return true;
193  }
194 
195  /* OAuth2\Storage\AuthorizationCodeInterface */
196  public function getAuthorizationCode($code)
197  {
198  $result = $this->client->getItem(array(
199  "TableName"=> $this->config['code_table'],
200  "Key" => array('authorization_code' => array('S' => $code))
201  ));
202  if ($result->count()==0) {
203  return false ;
204  }
205  $token = $this->dynamo2array($result);
206  if (!array_key_exists("id_token", $token )) {
207  $token['id_token'] = null;
208  }
209  $token['expires'] = strtotime($token['expires']);
210 
211  return $token;
212 
213  }
214 
215  public function setAuthorizationCode($authorization_code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null)
216  {
217  // convert expires to datestring
218  $expires = date('Y-m-d H:i:s', $expires);
219 
220  $clientData = compact('authorization_code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'id_token', 'scope');
221  $clientData = array_filter($clientData, function ($value) { return !empty($value); });
222 
223  $result = $this->client->putItem(array(
224  'TableName' => $this->config['code_table'],
225  'Item' => $this->client->formatAttributes($clientData)
226  ));
227 
228  return true;
229  }
230 
231  public function expireAuthorizationCode($code)
232  {
233 
234  $result = $this->client->deleteItem(array(
235  'TableName' => $this->config['code_table'],
236  'Key' => $this->client->formatAttributes(array("authorization_code" => $code))
237  ));
238 
239  return true;
240  }
241 
242  /* OAuth2\Storage\UserCredentialsInterface */
243  public function checkUserCredentials($username, $password)
244  {
245  if ($user = $this->getUser($username)) {
246  return $this->checkPassword($user, $password);
247  }
248 
249  return false;
250  }
251 
252  public function getUserDetails($username)
253  {
254  return $this->getUser($username);
255  }
256 
257  /* UserClaimsInterface */
258  public function getUserClaims($user_id, $claims)
259  {
260  if (!$userDetails = $this->getUserDetails($user_id)) {
261  return false;
262  }
263 
264  $claims = explode(' ', trim($claims));
265  $userClaims = array();
266 
267  // for each requested claim, if the user has the claim, set it in the response
268  $validClaims = explode(' ', self::VALID_CLAIMS);
269  foreach ($validClaims as $validClaim) {
270  if (in_array($validClaim, $claims)) {
271  if ($validClaim == 'address') {
272  // address is an object with subfields
273  $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails);
274  } else {
275  $userClaims = array_merge($userClaims, $this->getUserClaim($validClaim, $userDetails));
276  }
277  }
278  }
279 
280  return $userClaims;
281  }
282 
283  protected function getUserClaim($claim, $userDetails)
284  {
285  $userClaims = array();
286  $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim)));
287  $claimValues = explode(' ', $claimValuesString);
288 
289  foreach ($claimValues as $value) {
290  if ($value == 'email_verified') {
291  $userClaims[$value] = $userDetails[$value]=='true' ? true : false;
292  } else {
293  $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null;
294  }
295  }
296 
297  return $userClaims;
298  }
299 
300  /* OAuth2\Storage\RefreshTokenInterface */
301  public function getRefreshToken($refresh_token)
302  {
303  $result = $this->client->getItem(array(
304  "TableName"=> $this->config['refresh_token_table'],
305  "Key" => array('refresh_token' => array('S' => $refresh_token))
306  ));
307  if ($result->count()==0) {
308  return false ;
309  }
310  $token = $this->dynamo2array($result);
311  $token['expires'] = strtotime($token['expires']);
312 
313  return $token;
314  }
315 
316  public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null)
317  {
318  // convert expires to datestring
319  $expires = date('Y-m-d H:i:s', $expires);
320 
321  $clientData = compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope');
322  $clientData = array_filter($clientData, function ($value) { return !empty($value); });
323 
324  $result = $this->client->putItem(array(
325  'TableName' => $this->config['refresh_token_table'],
326  'Item' => $this->client->formatAttributes($clientData)
327  ));
328 
329  return true;
330  }
331 
332  public function unsetRefreshToken($refresh_token)
333  {
334  $result = $this->client->deleteItem(array(
335  'TableName' => $this->config['refresh_token_table'],
336  'Key' => $this->client->formatAttributes(array("refresh_token" => $refresh_token))
337  ));
338 
339  return true;
340  }
341 
342  // plaintext passwords are bad! Override this for your application
343  protected function checkPassword($user, $password)
344  {
345  return $user['password'] == sha1($password);
346  }
347 
348  public function getUser($username)
349  {
350  $result = $this->client->getItem(array(
351  "TableName"=> $this->config['user_table'],
352  "Key" => array('username' => array('S' => $username))
353  ));
354  if ($result->count()==0) {
355  return false ;
356  }
357  $token = $this->dynamo2array($result);
358  $token['user_id'] = $username;
359 
360  return $token;
361  }
362 
363  public function setUser($username, $password, $first_name = null, $last_name = null)
364  {
365  // do not store in plaintext
366  $password = sha1($password);
367 
368  $clientData = compact('username', 'password', 'first_name', 'last_name');
369  $clientData = array_filter($clientData, function ($value) { return !is_null($value); });
370 
371  $result = $this->client->putItem(array(
372  'TableName' => $this->config['user_table'],
373  'Item' => $this->client->formatAttributes($clientData)
374  ));
375 
376  return true;
377 
378  }
379 
380  /* ScopeInterface */
381  public function scopeExists($scope)
382  {
383  $scope = explode(' ', $scope);
384  $scope_query = array();
385  $count = 0;
386  foreach ($scope as $key => $val) {
387  $result = $this->client->query(array(
388  'TableName' => $this->config['scope_table'],
389  'Select' => 'COUNT',
390  'KeyConditions' => array(
391  'scope' => array(
392  'AttributeValueList' => array(array('S' => $val)),
393  'ComparisonOperator' => 'EQ'
394  )
395  )
396  ));
397  $count += $result['Count'];
398  }
399 
400  return $count == count($scope);
401  }
402 
403  public function getDefaultScope($client_id = null)
404  {
405 
406  $result = $this->client->query(array(
407  'TableName' => $this->config['scope_table'],
408  'IndexName' => 'is_default-index',
409  'Select' => 'ALL_ATTRIBUTES',
410  'KeyConditions' => array(
411  'is_default' => array(
412  'AttributeValueList' => array(array('S' => 'true')),
413  'ComparisonOperator' => 'EQ',
414  ),
415  )
416  ));
417  $defaultScope = array();
418  if ($result->count() > 0) {
419  $array = $result->toArray();
420  foreach ($array["Items"] as $item) {
421  $defaultScope[] = $item['scope']['S'];
422  }
423 
424  return empty($defaultScope) ? null : implode(' ', $defaultScope);
425  }
426 
427  return null;
428  }
429 
430  /* JWTBearerInterface */
431  public function getClientKey($client_id, $subject)
432  {
433  $result = $this->client->getItem(array(
434  "TableName"=> $this->config['jwt_table'],
435  "Key" => array('client_id' => array('S' => $client_id), 'subject' => array('S' => $subject))
436  ));
437  if ($result->count()==0) {
438  return false ;
439  }
440  $token = $this->dynamo2array($result);
441 
442  return $token['public_key'];
443  }
444 
445  public function getClientScope($client_id)
446  {
447  if (!$clientDetails = $this->getClientDetails($client_id)) {
448  return false;
449  }
450 
451  if (isset($clientDetails['scope'])) {
452  return $clientDetails['scope'];
453  }
454 
455  return null;
456  }
457 
458  public function getJti($client_id, $subject, $audience, $expires, $jti)
459  {
460  //TODO not use.
461  }
462 
463  public function setJti($client_id, $subject, $audience, $expires, $jti)
464  {
465  //TODO not use.
466  }
467 
468  /* PublicKeyInterface */
469  public function getPublicKey($client_id = '0')
470  {
471 
472  $result = $this->client->getItem(array(
473  "TableName"=> $this->config['public_key_table'],
474  "Key" => array('client_id' => array('S' => $client_id))
475  ));
476  if ($result->count()==0) {
477  return false ;
478  }
479  $token = $this->dynamo2array($result);
480 
481  return $token['public_key'];
482 
483  }
484 
485  public function getPrivateKey($client_id = '0')
486  {
487  $result = $this->client->getItem(array(
488  "TableName"=> $this->config['public_key_table'],
489  "Key" => array('client_id' => array('S' => $client_id))
490  ));
491  if ($result->count()==0) {
492  return false ;
493  }
494  $token = $this->dynamo2array($result);
495 
496  return $token['private_key'];
497  }
498 
499  public function getEncryptionAlgorithm($client_id = null)
500  {
501  $result = $this->client->getItem(array(
502  "TableName"=> $this->config['public_key_table'],
503  "Key" => array('client_id' => array('S' => $client_id))
504  ));
505  if ($result->count()==0) {
506  return 'RS256' ;
507  }
508  $token = $this->dynamo2array($result);
509 
510  return $token['encryption_algorithm'];
511  }
512 
518  private function dynamo2array($dynamodbResult)
519  {
520  $result = array();
521  foreach ($dynamodbResult["Item"] as $key => $val) {
522  $result[$key] = $val["S"];
523  $result[] = $val["S"];
524  }
525 
526  return $result;
527  }
528 }
OAuth2\OpenID\Storage\AuthorizationCodeInterface
Definition: AuthorizationCodeInterface.php:14
OAuth2\Storage\DynamoDB\unsetRefreshToken
unsetRefreshToken($refresh_token)
Definition: DynamoDB.php:332
OAuth2\Storage\DynamoDB\getPrivateKey
getPrivateKey($client_id='0')
Definition: DynamoDB.php:485
OAuth2\Storage\DynamoDB\getAccessToken
getAccessToken($access_token)
Definition: DynamoDB.php:151
true
if(!defined("TRUE_VAL")) define("TRUE_VAL" true
Definition: constants.inc.php:8
OAuth2\Storage\DynamoDB\getDefaultScope
getDefaultScope($client_id=null)
Definition: DynamoDB.php:403
OAuth2\Storage\DynamoDB\getUser
getUser($username)
Definition: DynamoDB.php:348
OAuth2\Storage\DynamoDB\__construct
__construct($connection, $config=array())
Definition: DynamoDB.php:49
OAuth2\Storage\DynamoDB\expireAuthorizationCode
expireAuthorizationCode($code)
Definition: DynamoDB.php:231
OAuth2\Storage\DynamoDB\getJti
getJti($client_id, $subject, $audience, $expires, $jti)
Definition: DynamoDB.php:458
OAuth2\OpenID\Storage\UserClaimsInterface
Definition: UserClaimsInterface.php:10
OAuth2\Storage\DynamoDB\$client
$client
Definition: DynamoDB.php:46
OAuth2\Storage\DynamoDB\checkClientCredentials
checkClientCredentials($client_id, $client_secret=null)
Definition: DynamoDB.php:80
use
GNU LESSER GENERAL PUBLIC LICENSE February Free Software Inc Franklin Fifth MA USA Everyone is permitted to copy and distribute verbatim copies of this license but changing it is not allowed[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it By the GNU General Public Licenses are intended to guarantee your freedom to share and change free software to make sure the software is free for all its users This the Lesser General Public applies to some specially designated software packages typically libraries of the Free Software Foundation and other authors who decide to use it You can use it but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular based on the explanations below When we speak of free we are referring to freedom of use
Definition: license.txt:27
OAuth2\Storage\PublicKeyInterface
Definition: PublicKeyInterface.php:12
OAuth2\Storage\DynamoDB\setUser
setUser($username, $password, $first_name=null, $last_name=null)
Definition: DynamoDB.php:363
php
OAuth2\Storage\DynamoDB\setAuthorizationCode
setAuthorizationCode($authorization_code, $client_id, $user_id, $redirect_uri, $expires, $scope=null, $id_token=null)
Definition: DynamoDB.php:215
OAuth2\Storage\ScopeInterface
Definition: ScopeInterface.php:13
OAuth2\Storage\DynamoDB\checkPassword
checkPassword($user, $password)
Definition: DynamoDB.php:343
null
Attr AllowedClasses this is null
Definition: Attr.AllowedClasses.txt:6
OAuth2\Storage\UserCredentialsInterface
Definition: UserCredentialsInterface.php:13
OAuth2\Storage\AuthorizationCodeInterface
Definition: AuthorizationCodeInterface.php:13
OAuth2\Storage\DynamoDB\checkUserCredentials
checkUserCredentials($username, $password)
Definition: DynamoDB.php:243
OAuth2\Storage\DynamoDB\getUserDetails
getUserDetails($username)
Definition: DynamoDB.php:252
OAuth2\Storage\DynamoDB\getEncryptionAlgorithm
getEncryptionAlgorithm($client_id=null)
Definition: DynamoDB.php:499
OAuth2\Storage\DynamoDB\getUserClaim
getUserClaim($claim, $userDetails)
Definition: DynamoDB.php:283
OAuth2\Storage\DynamoDB\isPublicClient
isPublicClient($client_id)
Definition: DynamoDB.php:90
OAuth2\Storage\DynamoDB\$config
$config
Definition: DynamoDB.php:47
OAuth2\Storage\DynamoDB\getClientScope
getClientScope($client_id)
Definition: DynamoDB.php:445
OAuth2\Storage\DynamoDB\setClientDetails
setClientDetails($client_id, $client_secret=null, $redirect_uri=null, $grant_types=null, $scope=null, $user_id=null)
Definition: DynamoDB.php:124
OAuth2\Storage\ClientCredentialsInterface
Definition: ClientCredentialsInterface.php:12
OAuth2\Storage\DynamoDB\getUserClaims
getUserClaims($user_id, $claims)
Definition: DynamoDB.php:258
OAuth2\Storage\DynamoDB\checkRestrictedGrantType
checkRestrictedGrantType($client_id, $grant_type)
Definition: DynamoDB.php:137
OAuth2\Storage\DynamoDB\setRefreshToken
setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope=null)
Definition: DynamoDB.php:316
OAuth2\Storage\DynamoDB\getClientDetails
getClientDetails($client_id)
Definition: DynamoDB.php:105
OAuth2\Storage\DynamoDB\getClientKey
getClientKey($client_id, $subject)
Definition: DynamoDB.php:431
OAuth2\Storage\RefreshTokenInterface
Definition: RefreshTokenInterface.php:13
OAuth2\Storage\DynamoDB\setJti
setJti($client_id, $subject, $audience, $expires, $jti)
Definition: DynamoDB.php:463
OAuth2\Storage\DynamoDB\getRefreshToken
getRefreshToken($refresh_token)
Definition: DynamoDB.php:301
OAuth2\Storage\DynamoDB\scopeExists
scopeExists($scope)
Definition: DynamoDB.php:381
OAuth2\Storage\DynamoDB\getPublicKey
getPublicKey($client_id='0')
Definition: DynamoDB.php:469
OAuth2\Storage\DynamoDB
Definition: DynamoDB.php:45
OAuth2\Storage\DynamoDB\getAuthorizationCode
getAuthorizationCode($code)
Definition: DynamoDB.php:196
OAuth2\Storage
Definition: AccessTokenInterface.php:3
OAuth2\Storage\DynamoDB\setAccessToken
setAccessToken($access_token, $client_id, $user_id, $expires, $scope=null)
Definition: DynamoDB.php:168
OAuth2\Storage\JwtBearerInterface
Definition: JwtBearerInterface.php:16
empty
Attr AllowedRel this is empty
Definition: Attr.AllowedRel.txt:7
OAuth2\Storage\DynamoDB\unsetAccessToken
unsetAccessToken($access_token)
Definition: DynamoDB.php:185
as
as
Definition: Filter.ExtractStyleBlocks.Escaping.txt:10
false
if(!defined("FALSE_VAL")) define("FALSE_VAL" false
Definition: constants.inc.php:9
OAuth2\Storage\AccessTokenInterface
Definition: AccessTokenInterface.php:12