Cheetah
Cassandra.php
Go to the documentation of this file.
1 <?php
2 
3 namespace OAuth2\Storage;
4 
5 use phpcassa\ColumnFamily;
6 use phpcassa\ColumnSlice;
7 use phpcassa\Connection\ConnectionPool;
9 use OAuth2\OpenID\Storage\AuthorizationCodeInterface as OpenIDAuthorizationCodeInterface;
10 
41  OpenIDAuthorizationCodeInterface
42 {
43 
44  private $cache;
45 
46  /* The cassandra client */
47  protected $cassandra;
48 
49  /* Configuration array */
50  protected $config;
51 
58  public function __construct($connection = array(), array $config = array())
59  {
60  if ($connection instanceof ConnectionPool) {
61  $this->cassandra = $connection;
62  } else {
63  if (!is_array($connection)) {
64  throw new \InvalidArgumentException('First argument to OAuth2\Storage\Cassandra must be an instance of phpcassa\Connection\ConnectionPool or a configuration array');
65  }
66  $connection = array_merge(array(
67  'keyspace' => 'oauth2',
68  'servers' => null,
69  ), $connection);
70 
71  $this->cassandra = new ConnectionPool($connection['keyspace'], $connection['servers']);
72  }
73 
74  $this->config = array_merge(array(
75  // cassandra config
76  'column_family' => 'auth',
77 
78  // key names
79  'client_key' => 'oauth_clients:',
80  'access_token_key' => 'oauth_access_tokens:',
81  'refresh_token_key' => 'oauth_refresh_tokens:',
82  'code_key' => 'oauth_authorization_codes:',
83  'user_key' => 'oauth_users:',
84  'jwt_key' => 'oauth_jwt:',
85  'scope_key' => 'oauth_scopes:',
86  'public_key_key' => 'oauth_public_keys:',
87  ), $config);
88  }
89 
90  protected function getValue($key)
91  {
92  if (isset($this->cache[$key])) {
93  return $this->cache[$key];
94  }
95  $cf = new ColumnFamily($this->cassandra, $this->config['column_family']);
96 
97  try {
98  $value = $cf->get($key, new ColumnSlice("", ""));
99  $value = array_shift($value);
100  } catch (\cassandra\NotFoundException $e) {
101  return false;
102  }
103 
104  return json_decode($value, true);
105  }
106 
107  protected function setValue($key, $value, $expire = 0)
108  {
109  $this->cache[$key] = $value;
110 
111  $cf = new ColumnFamily($this->cassandra, $this->config['column_family']);
112 
113  $str = json_encode($value);
114  if ($expire > 0) {
115  try {
116  $seconds = $expire - time();
117  // __data key set as C* requires a field, note: max TTL can only be 630720000 seconds
118  $cf->insert($key, array('__data' => $str), null, $seconds);
119  } catch (\Exception $e) {
120  return false;
121  }
122  } else {
123  try {
124  // __data key set as C* requires a field
125  $cf->insert($key, array('__data' => $str));
126  } catch (\Exception $e) {
127  return false;
128  }
129  }
130 
131  return true;
132  }
133 
134  protected function expireValue($key)
135  {
136  unset($this->cache[$key]);
137 
138  $cf = new ColumnFamily($this->cassandra, $this->config['column_family']);
139  try {
140  // __data key set as C* requires a field
141  $cf->remove($key, array('__data'));
142  } catch (\Exception $e) {
143  return false;
144  }
145 
146  return true;
147  }
148 
149  /* AuthorizationCodeInterface */
150  public function getAuthorizationCode($code)
151  {
152  return $this->getValue($this->config['code_key'] . $code);
153  }
154 
155  public function setAuthorizationCode($authorization_code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null)
156  {
157  return $this->setValue(
158  $this->config['code_key'] . $authorization_code,
159  compact('authorization_code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope', 'id_token'),
160  $expires
161  );
162  }
163 
164  public function expireAuthorizationCode($code)
165  {
166  $key = $this->config['code_key'] . $code;
167  unset($this->cache[$key]);
168 
169  return $this->expireValue($key);
170  }
171 
172  /* UserCredentialsInterface */
173  public function checkUserCredentials($username, $password)
174  {
175  if ($user = $this->getUser($username)) {
176  return $this->checkPassword($user, $password);
177  }
178 
179  return false;
180  }
181 
182  // plaintext passwords are bad! Override this for your application
183  protected function checkPassword($user, $password)
184  {
185  return $user['password'] == sha1($password);
186  }
187 
188  public function getUserDetails($username)
189  {
190  return $this->getUser($username);
191  }
192 
193  public function getUser($username)
194  {
195  if (!$userInfo = $this->getValue($this->config['user_key'] . $username)) {
196  return false;
197  }
198 
199  // the default behavior is to use "username" as the user_id
200  return array_merge(array(
201  'user_id' => $username,
202  ), $userInfo);
203  }
204 
205  public function setUser($username, $password, $first_name = null, $last_name = null)
206  {
207  $password = sha1($password);
208 
209  return $this->setValue(
210  $this->config['user_key'] . $username,
211  compact('username', 'password', 'first_name', 'last_name')
212  );
213  }
214 
215  /* ClientCredentialsInterface */
216  public function checkClientCredentials($client_id, $client_secret = null)
217  {
218  if (!$client = $this->getClientDetails($client_id)) {
219  return false;
220  }
221 
222  return isset($client['client_secret'])
223  && $client['client_secret'] == $client_secret;
224  }
225 
226  public function isPublicClient($client_id)
227  {
228  if (!$client = $this->getClientDetails($client_id)) {
229  return false;
230  }
231 
232  return empty($result['client_secret']);
233  }
234 
235  /* ClientInterface */
236  public function getClientDetails($client_id)
237  {
238  return $this->getValue($this->config['client_key'] . $client_id);
239  }
240 
241  public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null)
242  {
243  return $this->setValue(
244  $this->config['client_key'] . $client_id,
245  compact('client_id', 'client_secret', 'redirect_uri', 'grant_types', 'scope', 'user_id')
246  );
247  }
248 
249  public function checkRestrictedGrantType($client_id, $grant_type)
250  {
251  $details = $this->getClientDetails($client_id);
252  if (isset($details['grant_types'])) {
253  $grant_types = explode(' ', $details['grant_types']);
254 
255  return in_array($grant_type, (array) $grant_types);
256  }
257 
258  // if grant_types are not defined, then none are restricted
259  return true;
260  }
261 
262  /* RefreshTokenInterface */
263  public function getRefreshToken($refresh_token)
264  {
265  return $this->getValue($this->config['refresh_token_key'] . $refresh_token);
266  }
267 
268  public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null)
269  {
270  return $this->setValue(
271  $this->config['refresh_token_key'] . $refresh_token,
272  compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope'),
273  $expires
274  );
275  }
276 
277  public function unsetRefreshToken($refresh_token)
278  {
279  return $this->expireValue($this->config['refresh_token_key'] . $refresh_token);
280  }
281 
282  /* AccessTokenInterface */
283  public function getAccessToken($access_token)
284  {
285  return $this->getValue($this->config['access_token_key'].$access_token);
286  }
287 
288  public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null)
289  {
290  return $this->setValue(
291  $this->config['access_token_key'].$access_token,
292  compact('access_token', 'client_id', 'user_id', 'expires', 'scope'),
293  $expires
294  );
295  }
296 
297  public function unsetAccessToken($access_token)
298  {
299  return $this->expireValue($this->config['access_token_key'] . $access_token);
300  }
301 
302  /* ScopeInterface */
303  public function scopeExists($scope)
304  {
305  $scope = explode(' ', $scope);
306 
307  $result = $this->getValue($this->config['scope_key'].'supported:global');
308 
309  $supportedScope = explode(' ', (string) $result);
310 
311  return (count(array_diff($scope, $supportedScope)) == 0);
312  }
313 
314  public function getDefaultScope($client_id = null)
315  {
316  if (is_null($client_id) || !$result = $this->getValue($this->config['scope_key'].'default:'.$client_id)) {
317  $result = $this->getValue($this->config['scope_key'].'default:global');
318  }
319 
320  return $result;
321  }
322 
323  public function setScope($scope, $client_id = null, $type = 'supported')
324  {
325  if (!in_array($type, array('default', 'supported'))) {
326  throw new \InvalidArgumentException('"$type" must be one of "default", "supported"');
327  }
328 
329  if (is_null($client_id)) {
330  $key = $this->config['scope_key'].$type.':global';
331  } else {
332  $key = $this->config['scope_key'].$type.':'.$client_id;
333  }
334 
335  return $this->setValue($key, $scope);
336  }
337 
338  /*JWTBearerInterface */
339  public function getClientKey($client_id, $subject)
340  {
341  if (!$jwt = $this->getValue($this->config['jwt_key'] . $client_id)) {
342  return false;
343  }
344 
345  if (isset($jwt['subject']) && $jwt['subject'] == $subject ) {
346  return $jwt['key'];
347  }
348 
349  return null;
350  }
351 
352  public function setClientKey($client_id, $key, $subject = null)
353  {
354  return $this->setValue($this->config['jwt_key'] . $client_id, array(
355  'key' => $key,
356  'subject' => $subject
357  ));
358  }
359 
360  /*ScopeInterface */
361  public function getClientScope($client_id)
362  {
363  if (!$clientDetails = $this->getClientDetails($client_id)) {
364  return false;
365  }
366 
367  if (isset($clientDetails['scope'])) {
368  return $clientDetails['scope'];
369  }
370 
371  return null;
372  }
373 
374  public function getJti($client_id, $subject, $audience, $expiration, $jti)
375  {
376  //TODO: Needs cassandra implementation.
377  throw new \Exception('getJti() for the Cassandra driver is currently unimplemented.');
378  }
379 
380  public function setJti($client_id, $subject, $audience, $expiration, $jti)
381  {
382  //TODO: Needs cassandra implementation.
383  throw new \Exception('setJti() for the Cassandra driver is currently unimplemented.');
384  }
385 
386  /* PublicKeyInterface */
387  public function getPublicKey($client_id = '')
388  {
389  $public_key = $this->getValue($this->config['public_key_key'] . $client_id);
390  if (is_array($public_key)) {
391  return $public_key['public_key'];
392  }
393  $public_key = $this->getValue($this->config['public_key_key']);
394  if (is_array($public_key)) {
395  return $public_key['public_key'];
396  }
397  }
398 
399  public function getPrivateKey($client_id = '')
400  {
401  $public_key = $this->getValue($this->config['public_key_key'] . $client_id);
402  if (is_array($public_key)) {
403  return $public_key['private_key'];
404  }
405  $public_key = $this->getValue($this->config['public_key_key']);
406  if (is_array($public_key)) {
407  return $public_key['private_key'];
408  }
409  }
410 
411  public function getEncryptionAlgorithm($client_id = null)
412  {
413  $public_key = $this->getValue($this->config['public_key_key'] . $client_id);
414  if (is_array($public_key)) {
415  return $public_key['encryption_algorithm'];
416  }
417  $public_key = $this->getValue($this->config['public_key_key']);
418  if (is_array($public_key)) {
419  return $public_key['encryption_algorithm'];
420  }
421 
422  return 'RS256';
423  }
424 
425  /* UserClaimsInterface */
426  public function getUserClaims($user_id, $claims)
427  {
428  $userDetails = $this->getUserDetails($user_id);
429  if (!is_array($userDetails)) {
430  return false;
431  }
432 
433  $claims = explode(' ', trim($claims));
434  $userClaims = array();
435 
436  // for each requested claim, if the user has the claim, set it in the response
437  $validClaims = explode(' ', self::VALID_CLAIMS);
438  foreach ($validClaims as $validClaim) {
439  if (in_array($validClaim, $claims)) {
440  if ($validClaim == 'address') {
441  // address is an object with subfields
442  $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails);
443  } else {
444  $userClaims = array_merge($userClaims, $this->getUserClaim($validClaim, $userDetails));
445  }
446  }
447  }
448 
449  return $userClaims;
450  }
451 
452  protected function getUserClaim($claim, $userDetails)
453  {
454  $userClaims = array();
455  $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim)));
456  $claimValues = explode(' ', $claimValuesString);
457 
458  foreach ($claimValues as $value) {
459  if ($value == 'email_verified') {
460  $userClaims[$value] = $userDetails[$value]=='true' ? true : false;
461  } else {
462  $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null;
463  }
464  }
465 
466  return $userClaims;
467  }
468 
469 }
OAuth2\OpenID\Storage\AuthorizationCodeInterface
Definition: AuthorizationCodeInterface.php:14
OAuth2\Storage\Cassandra\getRefreshToken
getRefreshToken($refresh_token)
Definition: Cassandra.php:263
OAuth2\Storage\Cassandra\setClientDetails
setClientDetails($client_id, $client_secret=null, $redirect_uri=null, $grant_types=null, $scope=null, $user_id=null)
Definition: Cassandra.php:241
true
if(!defined("TRUE_VAL")) define("TRUE_VAL" true
Definition: constants.inc.php:8
OAuth2\Storage\Cassandra\getClientScope
getClientScope($client_id)
Definition: Cassandra.php:361
OAuth2\Storage\Cassandra\expireAuthorizationCode
expireAuthorizationCode($code)
Definition: Cassandra.php:164
OAuth2\Storage\Cassandra\setClientKey
setClientKey($client_id, $key, $subject=null)
Definition: Cassandra.php:352
OAuth2\Storage\Cassandra\getValue
getValue($key)
Definition: Cassandra.php:90
OAuth2\Storage\Cassandra\unsetRefreshToken
unsetRefreshToken($refresh_token)
Definition: Cassandra.php:277
OAuth2\Storage\Cassandra\$cassandra
$cassandra
Definition: Cassandra.php:47
OAuth2\OpenID\Storage\UserClaimsInterface
Definition: UserClaimsInterface.php:10
OAuth2\Storage\Cassandra\getUserClaim
getUserClaim($claim, $userDetails)
Definition: Cassandra.php:452
OAuth2\Storage\Cassandra\getUserDetails
getUserDetails($username)
Definition: Cassandra.php:188
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\Cassandra\scopeExists
scopeExists($scope)
Definition: Cassandra.php:303
php
OAuth2\Storage\Cassandra\getPublicKey
getPublicKey($client_id='')
Definition: Cassandra.php:387
OAuth2\Storage\Cassandra\checkClientCredentials
checkClientCredentials($client_id, $client_secret=null)
Definition: Cassandra.php:216
OAuth2\Storage\ScopeInterface
Definition: ScopeInterface.php:13
OAuth2\Storage\Cassandra\getAuthorizationCode
getAuthorizationCode($code)
Definition: Cassandra.php:150
OAuth2\Storage\Cassandra\getClientDetails
getClientDetails($client_id)
Definition: Cassandra.php:236
OAuth2\Storage\Cassandra\getDefaultScope
getDefaultScope($client_id=null)
Definition: Cassandra.php:314
OAuth2\Storage\UserCredentialsInterface
Definition: UserCredentialsInterface.php:13
OAuth2\Storage\AuthorizationCodeInterface
Definition: AuthorizationCodeInterface.php:13
OAuth2\Storage\Cassandra\setScope
setScope($scope, $client_id=null, $type='supported')
Definition: Cassandra.php:323
OAuth2\Storage\Cassandra\$config
$config
Definition: Cassandra.php:50
OAuth2\Storage\Cassandra\getClientKey
getClientKey($client_id, $subject)
Definition: Cassandra.php:339
OAuth2\Storage\Cassandra\setRefreshToken
setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope=null)
Definition: Cassandra.php:268
OAuth2\Storage\Cassandra\getUser
getUser($username)
Definition: Cassandra.php:193
OAuth2\Storage\Cassandra\checkUserCredentials
checkUserCredentials($username, $password)
Definition: Cassandra.php:173
OAuth2\Storage\Cassandra\__construct
__construct($connection=array(), array $config=array())
Definition: Cassandra.php:58
time
that in the case of a Adaptation or at a minimum such credit will if a credit for all contributing authors of the Adaptation or Collection then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors For the avoidance of You may only use the credit required by this Section for the purpose of attribution in the manner set out above by exercising Your rights under this You may not implicitly or explicitly assert or imply any connection sponsorship or endorsement by the Original Licensor and or Attribution as of You or Your use of the without the express prior written permission of the Original Licensor and or Attribution Parties Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable if You Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or You must not modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author s honor or reputation Licensor agrees that in those in which any exercise of the right granted in modification or other derogatory action prejudicial to the Original Author s honor and the Licensor will waive or not as this to the fullest extent permitted by the applicable national to enable You to reasonably exercise Your right under Warranties and Disclaimer UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN LICENSOR OFFERS THE WORK AS IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE STATUTORY OR WITHOUT WARRANTIES OF FITNESS FOR A PARTICULAR OR THE ABSENCE OF LATENT OR OTHER OR THE PRESENCE OF ABSENCE OF WHETHER OR NOT DISCOVERABLE SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED SO SUCH EXCLUSION MAY NOT APPLY TO YOU Limitation on Liability EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES Termination This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License Individuals or entities who have received Adaptations or Collections from You under this will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses and will survive any termination of this License Subject to the above terms and the license granted here is Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time
Definition: license.txt:56
OAuth2\Storage\ClientCredentialsInterface
Definition: ClientCredentialsInterface.php:12
OAuth2\Storage\Cassandra\isPublicClient
isPublicClient($client_id)
Definition: Cassandra.php:226
OAuth2\Storage\Cassandra\setAccessToken
setAccessToken($access_token, $client_id, $user_id, $expires, $scope=null)
Definition: Cassandra.php:288
OAuth2\Storage\Cassandra\getUserClaims
getUserClaims($user_id, $claims)
Definition: Cassandra.php:426
OAuth2\Storage\Cassandra
Definition: Cassandra.php:42
OAuth2\Storage\RefreshTokenInterface
Definition: RefreshTokenInterface.php:13
OAuth2\Storage\Cassandra\getAccessToken
getAccessToken($access_token)
Definition: Cassandra.php:283
OAuth2\Storage\Cassandra\setJti
setJti($client_id, $subject, $audience, $expiration, $jti)
Definition: Cassandra.php:380
OAuth2\Storage\Cassandra\getPrivateKey
getPrivateKey($client_id='')
Definition: Cassandra.php:399
OAuth2\Storage\Cassandra\checkPassword
checkPassword($user, $password)
Definition: Cassandra.php:183
OAuth2\Storage\Cassandra\setUser
setUser($username, $password, $first_name=null, $last_name=null)
Definition: Cassandra.php:205
OAuth2\Storage
Definition: AccessTokenInterface.php:3
OAuth2\Storage\Cassandra\setAuthorizationCode
setAuthorizationCode($authorization_code, $client_id, $user_id, $redirect_uri, $expires, $scope=null, $id_token=null)
Definition: Cassandra.php:155
OAuth2\Storage\Cassandra\setValue
setValue($key, $value, $expire=0)
Definition: Cassandra.php:107
OAuth2\Storage\JwtBearerInterface
Definition: JwtBearerInterface.php:16
OAuth2\Storage\Cassandra\checkRestrictedGrantType
checkRestrictedGrantType($client_id, $grant_type)
Definition: Cassandra.php:249
empty
Attr AllowedRel this is empty
Definition: Attr.AllowedRel.txt:7
OAuth2\Storage\Cassandra\unsetAccessToken
unsetAccessToken($access_token)
Definition: Cassandra.php:297
OAuth2\Storage\Cassandra\getJti
getJti($client_id, $subject, $audience, $expiration, $jti)
Definition: Cassandra.php:374
OAuth2\Storage\Cassandra\getEncryptionAlgorithm
getEncryptionAlgorithm($client_id=null)
Definition: Cassandra.php:411
OAuth2\Storage\Cassandra\expireValue
expireValue($key)
Definition: Cassandra.php:134
as
as
Definition: Filter.ExtractStyleBlocks.Escaping.txt:10
OAuth2\Storage\AccessTokenInterface
Definition: AccessTokenInterface.php:12