@@ -18,449 +18,449 @@ discard block |
||
18 | 18 | * @author Brent Shaffer <bshafs at gmail dot com> |
19 | 19 | */ |
20 | 20 | class Pdo implements |
21 | - AuthorizationCodeInterface, |
|
22 | - AccessTokenInterface, |
|
23 | - ClientCredentialsInterface, |
|
24 | - UserCredentialsInterface, |
|
25 | - RefreshTokenInterface, |
|
26 | - JwtBearerInterface, |
|
27 | - ScopeInterface, |
|
28 | - PublicKeyInterface, |
|
29 | - UserClaimsInterface, |
|
30 | - OpenIDAuthorizationCodeInterface |
|
21 | + AuthorizationCodeInterface, |
|
22 | + AccessTokenInterface, |
|
23 | + ClientCredentialsInterface, |
|
24 | + UserCredentialsInterface, |
|
25 | + RefreshTokenInterface, |
|
26 | + JwtBearerInterface, |
|
27 | + ScopeInterface, |
|
28 | + PublicKeyInterface, |
|
29 | + UserClaimsInterface, |
|
30 | + OpenIDAuthorizationCodeInterface |
|
31 | 31 | { |
32 | - protected $db; |
|
33 | - protected $config; |
|
34 | - |
|
35 | - public function __construct($connection, $config = array()) |
|
36 | - { |
|
37 | - if (!$connection instanceof \PDO) { |
|
38 | - if (is_string($connection)) { |
|
39 | - $connection = array('dsn' => $connection); |
|
40 | - } |
|
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'); |
|
43 | - } |
|
44 | - if (!isset($connection['dsn'])) { |
|
45 | - throw new \InvalidArgumentException('configuration array must contain "dsn"'); |
|
46 | - } |
|
47 | - // merge optional parameters |
|
48 | - $connection = array_merge(array( |
|
49 | - 'username' => null, |
|
50 | - 'password' => null, |
|
51 | - 'options' => array(), |
|
52 | - ), $connection); |
|
53 | - $connection = new \PDO($connection['dsn'], $connection['username'], $connection['password'], $connection['options']); |
|
54 | - } |
|
55 | - $this->db = $connection; |
|
56 | - |
|
57 | - // debugging |
|
58 | - $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); |
|
59 | - |
|
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', |
|
70 | - ), $config); |
|
71 | - } |
|
72 | - |
|
73 | - /* OAuth2\Storage\ClientCredentialsInterface */ |
|
74 | - public function checkClientCredentials($client_id, $client_secret = null) |
|
75 | - { |
|
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); |
|
79 | - |
|
80 | - // make this extensible |
|
81 | - return $result && $result['client_secret'] == $client_secret; |
|
82 | - } |
|
83 | - |
|
84 | - public function isPublicClient($client_id) |
|
85 | - { |
|
86 | - $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = :client_id', $this->config['client_table'])); |
|
87 | - $stmt->execute(compact('client_id')); |
|
88 | - |
|
89 | - if (!$result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
90 | - return false; |
|
91 | - } |
|
92 | - |
|
93 | - return empty($result['client_secret']); |
|
94 | - } |
|
95 | - |
|
96 | - /* OAuth2\Storage\ClientInterface */ |
|
97 | - public function getClientDetails($client_id) |
|
98 | - { |
|
99 | - $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = :client_id', $this->config['client_table'])); |
|
100 | - $stmt->execute(compact('client_id')); |
|
101 | - |
|
102 | - return $stmt->fetch(\PDO::FETCH_ASSOC); |
|
103 | - } |
|
104 | - |
|
105 | - public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
106 | - { |
|
107 | - // if it exists, update it. |
|
108 | - if ($this->getClientDetails($client_id)) { |
|
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'])); |
|
110 | - } else { |
|
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'])); |
|
112 | - } |
|
113 | - |
|
114 | - return $stmt->execute(compact('client_id', 'client_secret', 'redirect_uri', 'grant_types', 'scope', 'user_id')); |
|
115 | - } |
|
116 | - |
|
117 | - public function checkRestrictedGrantType($client_id, $grant_type) |
|
118 | - { |
|
119 | - $details = $this->getClientDetails($client_id); |
|
120 | - if (isset($details['grant_types'])) { |
|
121 | - $grant_types = explode(' ', $details['grant_types']); |
|
122 | - |
|
123 | - return in_array($grant_type, (array) $grant_types); |
|
124 | - } |
|
125 | - |
|
126 | - // if grant_types are not defined, then none are restricted |
|
127 | - return true; |
|
128 | - } |
|
129 | - |
|
130 | - /* OAuth2\Storage\AccessTokenInterface */ |
|
131 | - public function getAccessToken($access_token) |
|
132 | - { |
|
133 | - $stmt = $this->db->prepare(sprintf('SELECT * from %s where access_token = :access_token', $this->config['access_token_table'])); |
|
134 | - |
|
135 | - $token = $stmt->execute(compact('access_token')); |
|
136 | - if ($token = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
137 | - // convert date string back to timestamp |
|
138 | - $token['expires'] = strtotime($token['expires']); |
|
139 | - } |
|
140 | - |
|
141 | - return $token; |
|
142 | - } |
|
143 | - |
|
144 | - public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
145 | - { |
|
146 | - // convert expires to datestring |
|
147 | - $expires = date('Y-m-d H:i:s', $expires); |
|
148 | - |
|
149 | - // if it exists, update it. |
|
150 | - if ($this->getAccessToken($access_token)) { |
|
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'])); |
|
152 | - } else { |
|
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'])); |
|
154 | - } |
|
155 | - |
|
156 | - return $stmt->execute(compact('access_token', 'client_id', 'user_id', 'expires', 'scope')); |
|
157 | - } |
|
158 | - |
|
159 | - public function unsetAccessToken($access_token) |
|
160 | - { |
|
161 | - $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE access_token = :access_token', $this->config['access_token_table'])); |
|
162 | - |
|
163 | - return $stmt->execute(compact('access_token')); |
|
164 | - } |
|
165 | - |
|
166 | - /* OAuth2\Storage\AuthorizationCodeInterface */ |
|
167 | - public function getAuthorizationCode($code) |
|
168 | - { |
|
169 | - $stmt = $this->db->prepare(sprintf('SELECT * from %s where authorization_code = :code', $this->config['code_table'])); |
|
170 | - $stmt->execute(compact('code')); |
|
171 | - |
|
172 | - if ($code = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
173 | - // convert date string back to timestamp |
|
174 | - $code['expires'] = strtotime($code['expires']); |
|
175 | - } |
|
176 | - |
|
177 | - return $code; |
|
178 | - } |
|
179 | - |
|
180 | - public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
181 | - { |
|
182 | - if (func_num_args() > 6) { |
|
183 | - // we are calling with an id token |
|
184 | - return call_user_func_array(array($this, 'setAuthorizationCodeWithIdToken'), func_get_args()); |
|
185 | - } |
|
186 | - |
|
187 | - // convert expires to datestring |
|
188 | - $expires = date('Y-m-d H:i:s', $expires); |
|
189 | - |
|
190 | - // if it exists, update it. |
|
191 | - if ($this->getAuthorizationCode($code)) { |
|
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'])); |
|
193 | - } else { |
|
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'])); |
|
195 | - } |
|
196 | - |
|
197 | - return $stmt->execute(compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope')); |
|
198 | - } |
|
199 | - |
|
200 | - private function setAuthorizationCodeWithIdToken($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
201 | - { |
|
202 | - // convert expires to datestring |
|
203 | - $expires = date('Y-m-d H:i:s', $expires); |
|
204 | - |
|
205 | - // if it exists, update it. |
|
206 | - if ($this->getAuthorizationCode($code)) { |
|
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'])); |
|
208 | - } else { |
|
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'])); |
|
210 | - } |
|
211 | - |
|
212 | - return $stmt->execute(compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope', 'id_token')); |
|
213 | - } |
|
214 | - |
|
215 | - public function expireAuthorizationCode($code) |
|
216 | - { |
|
217 | - $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE authorization_code = :code', $this->config['code_table'])); |
|
218 | - |
|
219 | - return $stmt->execute(compact('code')); |
|
220 | - } |
|
221 | - |
|
222 | - /* OAuth2\Storage\UserCredentialsInterface */ |
|
223 | - public function checkUserCredentials($username, $password) |
|
224 | - { |
|
225 | - if ($user = $this->getUser($username)) { |
|
226 | - return $this->checkPassword($user, $password); |
|
227 | - } |
|
228 | - |
|
229 | - return false; |
|
230 | - } |
|
231 | - |
|
232 | - public function getUserDetails($username) |
|
233 | - { |
|
234 | - return $this->getUser($username); |
|
235 | - } |
|
236 | - |
|
237 | - /* UserClaimsInterface */ |
|
238 | - public function getUserClaims($user_id, $claims) |
|
239 | - { |
|
240 | - if (!$userDetails = $this->getUserDetails($user_id)) { |
|
241 | - return false; |
|
242 | - } |
|
243 | - |
|
244 | - $claims = explode(' ', trim($claims)); |
|
245 | - $userClaims = array(); |
|
246 | - |
|
247 | - // for each requested claim, if the user has the claim, set it in the response |
|
248 | - $validClaims = explode(' ', self::VALID_CLAIMS); |
|
249 | - foreach ($validClaims as $validClaim) { |
|
250 | - if (in_array($validClaim, $claims)) { |
|
251 | - if ($validClaim == 'address') { |
|
252 | - // address is an object with subfields |
|
253 | - $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails); |
|
254 | - } else { |
|
255 | - $userClaims = array_merge($userClaims, $this->getUserClaim($validClaim, $userDetails)); |
|
256 | - } |
|
257 | - } |
|
258 | - } |
|
259 | - |
|
260 | - return $userClaims; |
|
261 | - } |
|
262 | - |
|
263 | - protected function getUserClaim($claim, $userDetails) |
|
264 | - { |
|
265 | - $userClaims = array(); |
|
266 | - $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim))); |
|
267 | - $claimValues = explode(' ', $claimValuesString); |
|
268 | - |
|
269 | - foreach ($claimValues as $value) { |
|
270 | - $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null; |
|
271 | - } |
|
272 | - |
|
273 | - return $userClaims; |
|
274 | - } |
|
275 | - |
|
276 | - /* OAuth2\Storage\RefreshTokenInterface */ |
|
277 | - public function getRefreshToken($refresh_token) |
|
278 | - { |
|
279 | - $stmt = $this->db->prepare(sprintf('SELECT * FROM %s WHERE refresh_token = :refresh_token', $this->config['refresh_token_table'])); |
|
280 | - |
|
281 | - $token = $stmt->execute(compact('refresh_token')); |
|
282 | - if ($token = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
283 | - // convert expires to epoch time |
|
284 | - $token['expires'] = strtotime($token['expires']); |
|
285 | - } |
|
286 | - |
|
287 | - return $token; |
|
288 | - } |
|
289 | - |
|
290 | - public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
291 | - { |
|
292 | - // convert expires to datestring |
|
293 | - $expires = date('Y-m-d H:i:s', $expires); |
|
294 | - |
|
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'])); |
|
296 | - |
|
297 | - return $stmt->execute(compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope')); |
|
298 | - } |
|
299 | - |
|
300 | - public function unsetRefreshToken($refresh_token) |
|
301 | - { |
|
302 | - $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE refresh_token = :refresh_token', $this->config['refresh_token_table'])); |
|
303 | - |
|
304 | - return $stmt->execute(compact('refresh_token')); |
|
305 | - } |
|
306 | - |
|
307 | - // plaintext passwords are bad! Override this for your application |
|
308 | - protected function checkPassword($user, $password) |
|
309 | - { |
|
310 | - return $user['password'] == sha1($password); |
|
311 | - } |
|
312 | - |
|
313 | - public function getUser($username) |
|
314 | - { |
|
315 | - $stmt = $this->db->prepare($sql = sprintf('SELECT * from %s where username=:username', $this->config['user_table'])); |
|
316 | - $stmt->execute(array('username' => $username)); |
|
317 | - |
|
318 | - if (!$userInfo = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
319 | - return false; |
|
320 | - } |
|
321 | - |
|
322 | - // the default behavior is to use "username" as the user_id |
|
323 | - return array_merge(array( |
|
324 | - 'user_id' => $username |
|
325 | - ), $userInfo); |
|
326 | - } |
|
327 | - |
|
328 | - public function setUser($username, $password, $firstName = null, $lastName = null) |
|
329 | - { |
|
330 | - // do not store in plaintext |
|
331 | - $password = sha1($password); |
|
332 | - |
|
333 | - // if it exists, update it. |
|
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'])); |
|
336 | - } else { |
|
337 | - $stmt = $this->db->prepare(sprintf('INSERT INTO %s (username, password, first_name, last_name) VALUES (:username, :password, :firstName, :lastName)', $this->config['user_table'])); |
|
338 | - } |
|
339 | - |
|
340 | - return $stmt->execute(compact('username', 'password', 'firstName', 'lastName')); |
|
341 | - } |
|
342 | - |
|
343 | - /* ScopeInterface */ |
|
344 | - public function scopeExists($scope) |
|
345 | - { |
|
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); |
|
350 | - |
|
351 | - if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
352 | - return $result['count'] == count($scope); |
|
353 | - } |
|
354 | - |
|
355 | - return false; |
|
356 | - } |
|
357 | - |
|
358 | - public function getDefaultScope($client_id = null) |
|
359 | - { |
|
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)); |
|
362 | - |
|
363 | - if ($result = $stmt->fetchAll(\PDO::FETCH_ASSOC)) { |
|
364 | - $defaultScope = array_map(function ($row) { |
|
365 | - return $row['scope']; |
|
366 | - }, $result); |
|
367 | - |
|
368 | - return implode(' ', $defaultScope); |
|
369 | - } |
|
370 | - |
|
371 | - return null; |
|
372 | - } |
|
373 | - |
|
374 | - /* JWTBearerInterface */ |
|
375 | - public function getClientKey($client_id, $subject) |
|
376 | - { |
|
377 | - $stmt = $this->db->prepare($sql = sprintf('SELECT public_key from %s where client_id=:client_id AND subject=:subject', $this->config['jwt_table'])); |
|
378 | - |
|
379 | - $stmt->execute(array('client_id' => $client_id, 'subject' => $subject)); |
|
380 | - |
|
381 | - return $stmt->fetchColumn(); |
|
382 | - } |
|
383 | - |
|
384 | - public function getClientScope($client_id) |
|
385 | - { |
|
386 | - if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
387 | - return false; |
|
388 | - } |
|
389 | - |
|
390 | - if (isset($clientDetails['scope'])) { |
|
391 | - return $clientDetails['scope']; |
|
392 | - } |
|
393 | - |
|
394 | - return null; |
|
395 | - } |
|
396 | - |
|
397 | - public function getJti($client_id, $subject, $audience, $expires, $jti) |
|
398 | - { |
|
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'])); |
|
400 | - |
|
401 | - $stmt->execute(compact('client_id', 'subject', 'audience', 'expires', 'jti')); |
|
402 | - |
|
403 | - if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
404 | - return array( |
|
405 | - 'issuer' => $result['issuer'], |
|
406 | - 'subject' => $result['subject'], |
|
407 | - 'audience' => $result['audience'], |
|
408 | - 'expires' => $result['expires'], |
|
409 | - 'jti' => $result['jti'], |
|
410 | - ); |
|
411 | - } |
|
412 | - |
|
413 | - return null; |
|
414 | - } |
|
415 | - |
|
416 | - public function setJti($client_id, $subject, $audience, $expires, $jti) |
|
417 | - { |
|
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'])); |
|
419 | - |
|
420 | - return $stmt->execute(compact('client_id', 'subject', 'audience', 'expires', 'jti')); |
|
421 | - } |
|
422 | - |
|
423 | - /* PublicKeyInterface */ |
|
424 | - public function getPublicKey($client_id = null) |
|
425 | - { |
|
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'])); |
|
427 | - |
|
428 | - $stmt->execute(compact('client_id')); |
|
429 | - if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
430 | - return $result['public_key']; |
|
431 | - } |
|
432 | - } |
|
433 | - |
|
434 | - public function getPrivateKey($client_id = null) |
|
435 | - { |
|
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'])); |
|
437 | - |
|
438 | - $stmt->execute(compact('client_id')); |
|
439 | - if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
440 | - return $result['private_key']; |
|
441 | - } |
|
442 | - } |
|
443 | - |
|
444 | - public function getEncryptionAlgorithm($client_id = null) |
|
445 | - { |
|
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'])); |
|
447 | - |
|
448 | - $stmt->execute(compact('client_id')); |
|
449 | - if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
450 | - return $result['encryption_algorithm']; |
|
451 | - } |
|
452 | - |
|
453 | - return 'RS256'; |
|
454 | - } |
|
455 | - |
|
456 | - /** |
|
457 | - * DDL to create OAuth2 database and tables for PDO storage |
|
458 | - * |
|
459 | - * @see https://github.com/dsquier/oauth2-server-php-mysql |
|
460 | - */ |
|
461 | - public function getBuildSql($dbName = 'oauth2_server_php') |
|
462 | - { |
|
463 | - $sql = " |
|
32 | + protected $db; |
|
33 | + protected $config; |
|
34 | + |
|
35 | + public function __construct($connection, $config = array()) |
|
36 | + { |
|
37 | + if (!$connection instanceof \PDO) { |
|
38 | + if (is_string($connection)) { |
|
39 | + $connection = array('dsn' => $connection); |
|
40 | + } |
|
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'); |
|
43 | + } |
|
44 | + if (!isset($connection['dsn'])) { |
|
45 | + throw new \InvalidArgumentException('configuration array must contain "dsn"'); |
|
46 | + } |
|
47 | + // merge optional parameters |
|
48 | + $connection = array_merge(array( |
|
49 | + 'username' => null, |
|
50 | + 'password' => null, |
|
51 | + 'options' => array(), |
|
52 | + ), $connection); |
|
53 | + $connection = new \PDO($connection['dsn'], $connection['username'], $connection['password'], $connection['options']); |
|
54 | + } |
|
55 | + $this->db = $connection; |
|
56 | + |
|
57 | + // debugging |
|
58 | + $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); |
|
59 | + |
|
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', |
|
70 | + ), $config); |
|
71 | + } |
|
72 | + |
|
73 | + /* OAuth2\Storage\ClientCredentialsInterface */ |
|
74 | + public function checkClientCredentials($client_id, $client_secret = null) |
|
75 | + { |
|
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); |
|
79 | + |
|
80 | + // make this extensible |
|
81 | + return $result && $result['client_secret'] == $client_secret; |
|
82 | + } |
|
83 | + |
|
84 | + public function isPublicClient($client_id) |
|
85 | + { |
|
86 | + $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = :client_id', $this->config['client_table'])); |
|
87 | + $stmt->execute(compact('client_id')); |
|
88 | + |
|
89 | + if (!$result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
90 | + return false; |
|
91 | + } |
|
92 | + |
|
93 | + return empty($result['client_secret']); |
|
94 | + } |
|
95 | + |
|
96 | + /* OAuth2\Storage\ClientInterface */ |
|
97 | + public function getClientDetails($client_id) |
|
98 | + { |
|
99 | + $stmt = $this->db->prepare(sprintf('SELECT * from %s where client_id = :client_id', $this->config['client_table'])); |
|
100 | + $stmt->execute(compact('client_id')); |
|
101 | + |
|
102 | + return $stmt->fetch(\PDO::FETCH_ASSOC); |
|
103 | + } |
|
104 | + |
|
105 | + public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
106 | + { |
|
107 | + // if it exists, update it. |
|
108 | + if ($this->getClientDetails($client_id)) { |
|
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'])); |
|
110 | + } else { |
|
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'])); |
|
112 | + } |
|
113 | + |
|
114 | + return $stmt->execute(compact('client_id', 'client_secret', 'redirect_uri', 'grant_types', 'scope', 'user_id')); |
|
115 | + } |
|
116 | + |
|
117 | + public function checkRestrictedGrantType($client_id, $grant_type) |
|
118 | + { |
|
119 | + $details = $this->getClientDetails($client_id); |
|
120 | + if (isset($details['grant_types'])) { |
|
121 | + $grant_types = explode(' ', $details['grant_types']); |
|
122 | + |
|
123 | + return in_array($grant_type, (array) $grant_types); |
|
124 | + } |
|
125 | + |
|
126 | + // if grant_types are not defined, then none are restricted |
|
127 | + return true; |
|
128 | + } |
|
129 | + |
|
130 | + /* OAuth2\Storage\AccessTokenInterface */ |
|
131 | + public function getAccessToken($access_token) |
|
132 | + { |
|
133 | + $stmt = $this->db->prepare(sprintf('SELECT * from %s where access_token = :access_token', $this->config['access_token_table'])); |
|
134 | + |
|
135 | + $token = $stmt->execute(compact('access_token')); |
|
136 | + if ($token = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
137 | + // convert date string back to timestamp |
|
138 | + $token['expires'] = strtotime($token['expires']); |
|
139 | + } |
|
140 | + |
|
141 | + return $token; |
|
142 | + } |
|
143 | + |
|
144 | + public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
145 | + { |
|
146 | + // convert expires to datestring |
|
147 | + $expires = date('Y-m-d H:i:s', $expires); |
|
148 | + |
|
149 | + // if it exists, update it. |
|
150 | + if ($this->getAccessToken($access_token)) { |
|
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'])); |
|
152 | + } else { |
|
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'])); |
|
154 | + } |
|
155 | + |
|
156 | + return $stmt->execute(compact('access_token', 'client_id', 'user_id', 'expires', 'scope')); |
|
157 | + } |
|
158 | + |
|
159 | + public function unsetAccessToken($access_token) |
|
160 | + { |
|
161 | + $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE access_token = :access_token', $this->config['access_token_table'])); |
|
162 | + |
|
163 | + return $stmt->execute(compact('access_token')); |
|
164 | + } |
|
165 | + |
|
166 | + /* OAuth2\Storage\AuthorizationCodeInterface */ |
|
167 | + public function getAuthorizationCode($code) |
|
168 | + { |
|
169 | + $stmt = $this->db->prepare(sprintf('SELECT * from %s where authorization_code = :code', $this->config['code_table'])); |
|
170 | + $stmt->execute(compact('code')); |
|
171 | + |
|
172 | + if ($code = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
173 | + // convert date string back to timestamp |
|
174 | + $code['expires'] = strtotime($code['expires']); |
|
175 | + } |
|
176 | + |
|
177 | + return $code; |
|
178 | + } |
|
179 | + |
|
180 | + public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
181 | + { |
|
182 | + if (func_num_args() > 6) { |
|
183 | + // we are calling with an id token |
|
184 | + return call_user_func_array(array($this, 'setAuthorizationCodeWithIdToken'), func_get_args()); |
|
185 | + } |
|
186 | + |
|
187 | + // convert expires to datestring |
|
188 | + $expires = date('Y-m-d H:i:s', $expires); |
|
189 | + |
|
190 | + // if it exists, update it. |
|
191 | + if ($this->getAuthorizationCode($code)) { |
|
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'])); |
|
193 | + } else { |
|
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'])); |
|
195 | + } |
|
196 | + |
|
197 | + return $stmt->execute(compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope')); |
|
198 | + } |
|
199 | + |
|
200 | + private function setAuthorizationCodeWithIdToken($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
201 | + { |
|
202 | + // convert expires to datestring |
|
203 | + $expires = date('Y-m-d H:i:s', $expires); |
|
204 | + |
|
205 | + // if it exists, update it. |
|
206 | + if ($this->getAuthorizationCode($code)) { |
|
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'])); |
|
208 | + } else { |
|
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'])); |
|
210 | + } |
|
211 | + |
|
212 | + return $stmt->execute(compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope', 'id_token')); |
|
213 | + } |
|
214 | + |
|
215 | + public function expireAuthorizationCode($code) |
|
216 | + { |
|
217 | + $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE authorization_code = :code', $this->config['code_table'])); |
|
218 | + |
|
219 | + return $stmt->execute(compact('code')); |
|
220 | + } |
|
221 | + |
|
222 | + /* OAuth2\Storage\UserCredentialsInterface */ |
|
223 | + public function checkUserCredentials($username, $password) |
|
224 | + { |
|
225 | + if ($user = $this->getUser($username)) { |
|
226 | + return $this->checkPassword($user, $password); |
|
227 | + } |
|
228 | + |
|
229 | + return false; |
|
230 | + } |
|
231 | + |
|
232 | + public function getUserDetails($username) |
|
233 | + { |
|
234 | + return $this->getUser($username); |
|
235 | + } |
|
236 | + |
|
237 | + /* UserClaimsInterface */ |
|
238 | + public function getUserClaims($user_id, $claims) |
|
239 | + { |
|
240 | + if (!$userDetails = $this->getUserDetails($user_id)) { |
|
241 | + return false; |
|
242 | + } |
|
243 | + |
|
244 | + $claims = explode(' ', trim($claims)); |
|
245 | + $userClaims = array(); |
|
246 | + |
|
247 | + // for each requested claim, if the user has the claim, set it in the response |
|
248 | + $validClaims = explode(' ', self::VALID_CLAIMS); |
|
249 | + foreach ($validClaims as $validClaim) { |
|
250 | + if (in_array($validClaim, $claims)) { |
|
251 | + if ($validClaim == 'address') { |
|
252 | + // address is an object with subfields |
|
253 | + $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails); |
|
254 | + } else { |
|
255 | + $userClaims = array_merge($userClaims, $this->getUserClaim($validClaim, $userDetails)); |
|
256 | + } |
|
257 | + } |
|
258 | + } |
|
259 | + |
|
260 | + return $userClaims; |
|
261 | + } |
|
262 | + |
|
263 | + protected function getUserClaim($claim, $userDetails) |
|
264 | + { |
|
265 | + $userClaims = array(); |
|
266 | + $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim))); |
|
267 | + $claimValues = explode(' ', $claimValuesString); |
|
268 | + |
|
269 | + foreach ($claimValues as $value) { |
|
270 | + $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null; |
|
271 | + } |
|
272 | + |
|
273 | + return $userClaims; |
|
274 | + } |
|
275 | + |
|
276 | + /* OAuth2\Storage\RefreshTokenInterface */ |
|
277 | + public function getRefreshToken($refresh_token) |
|
278 | + { |
|
279 | + $stmt = $this->db->prepare(sprintf('SELECT * FROM %s WHERE refresh_token = :refresh_token', $this->config['refresh_token_table'])); |
|
280 | + |
|
281 | + $token = $stmt->execute(compact('refresh_token')); |
|
282 | + if ($token = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
283 | + // convert expires to epoch time |
|
284 | + $token['expires'] = strtotime($token['expires']); |
|
285 | + } |
|
286 | + |
|
287 | + return $token; |
|
288 | + } |
|
289 | + |
|
290 | + public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
291 | + { |
|
292 | + // convert expires to datestring |
|
293 | + $expires = date('Y-m-d H:i:s', $expires); |
|
294 | + |
|
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'])); |
|
296 | + |
|
297 | + return $stmt->execute(compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope')); |
|
298 | + } |
|
299 | + |
|
300 | + public function unsetRefreshToken($refresh_token) |
|
301 | + { |
|
302 | + $stmt = $this->db->prepare(sprintf('DELETE FROM %s WHERE refresh_token = :refresh_token', $this->config['refresh_token_table'])); |
|
303 | + |
|
304 | + return $stmt->execute(compact('refresh_token')); |
|
305 | + } |
|
306 | + |
|
307 | + // plaintext passwords are bad! Override this for your application |
|
308 | + protected function checkPassword($user, $password) |
|
309 | + { |
|
310 | + return $user['password'] == sha1($password); |
|
311 | + } |
|
312 | + |
|
313 | + public function getUser($username) |
|
314 | + { |
|
315 | + $stmt = $this->db->prepare($sql = sprintf('SELECT * from %s where username=:username', $this->config['user_table'])); |
|
316 | + $stmt->execute(array('username' => $username)); |
|
317 | + |
|
318 | + if (!$userInfo = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
319 | + return false; |
|
320 | + } |
|
321 | + |
|
322 | + // the default behavior is to use "username" as the user_id |
|
323 | + return array_merge(array( |
|
324 | + 'user_id' => $username |
|
325 | + ), $userInfo); |
|
326 | + } |
|
327 | + |
|
328 | + public function setUser($username, $password, $firstName = null, $lastName = null) |
|
329 | + { |
|
330 | + // do not store in plaintext |
|
331 | + $password = sha1($password); |
|
332 | + |
|
333 | + // if it exists, update it. |
|
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'])); |
|
336 | + } else { |
|
337 | + $stmt = $this->db->prepare(sprintf('INSERT INTO %s (username, password, first_name, last_name) VALUES (:username, :password, :firstName, :lastName)', $this->config['user_table'])); |
|
338 | + } |
|
339 | + |
|
340 | + return $stmt->execute(compact('username', 'password', 'firstName', 'lastName')); |
|
341 | + } |
|
342 | + |
|
343 | + /* ScopeInterface */ |
|
344 | + public function scopeExists($scope) |
|
345 | + { |
|
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); |
|
350 | + |
|
351 | + if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
352 | + return $result['count'] == count($scope); |
|
353 | + } |
|
354 | + |
|
355 | + return false; |
|
356 | + } |
|
357 | + |
|
358 | + public function getDefaultScope($client_id = null) |
|
359 | + { |
|
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)); |
|
362 | + |
|
363 | + if ($result = $stmt->fetchAll(\PDO::FETCH_ASSOC)) { |
|
364 | + $defaultScope = array_map(function ($row) { |
|
365 | + return $row['scope']; |
|
366 | + }, $result); |
|
367 | + |
|
368 | + return implode(' ', $defaultScope); |
|
369 | + } |
|
370 | + |
|
371 | + return null; |
|
372 | + } |
|
373 | + |
|
374 | + /* JWTBearerInterface */ |
|
375 | + public function getClientKey($client_id, $subject) |
|
376 | + { |
|
377 | + $stmt = $this->db->prepare($sql = sprintf('SELECT public_key from %s where client_id=:client_id AND subject=:subject', $this->config['jwt_table'])); |
|
378 | + |
|
379 | + $stmt->execute(array('client_id' => $client_id, 'subject' => $subject)); |
|
380 | + |
|
381 | + return $stmt->fetchColumn(); |
|
382 | + } |
|
383 | + |
|
384 | + public function getClientScope($client_id) |
|
385 | + { |
|
386 | + if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
387 | + return false; |
|
388 | + } |
|
389 | + |
|
390 | + if (isset($clientDetails['scope'])) { |
|
391 | + return $clientDetails['scope']; |
|
392 | + } |
|
393 | + |
|
394 | + return null; |
|
395 | + } |
|
396 | + |
|
397 | + public function getJti($client_id, $subject, $audience, $expires, $jti) |
|
398 | + { |
|
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'])); |
|
400 | + |
|
401 | + $stmt->execute(compact('client_id', 'subject', 'audience', 'expires', 'jti')); |
|
402 | + |
|
403 | + if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
404 | + return array( |
|
405 | + 'issuer' => $result['issuer'], |
|
406 | + 'subject' => $result['subject'], |
|
407 | + 'audience' => $result['audience'], |
|
408 | + 'expires' => $result['expires'], |
|
409 | + 'jti' => $result['jti'], |
|
410 | + ); |
|
411 | + } |
|
412 | + |
|
413 | + return null; |
|
414 | + } |
|
415 | + |
|
416 | + public function setJti($client_id, $subject, $audience, $expires, $jti) |
|
417 | + { |
|
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'])); |
|
419 | + |
|
420 | + return $stmt->execute(compact('client_id', 'subject', 'audience', 'expires', 'jti')); |
|
421 | + } |
|
422 | + |
|
423 | + /* PublicKeyInterface */ |
|
424 | + public function getPublicKey($client_id = null) |
|
425 | + { |
|
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'])); |
|
427 | + |
|
428 | + $stmt->execute(compact('client_id')); |
|
429 | + if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
430 | + return $result['public_key']; |
|
431 | + } |
|
432 | + } |
|
433 | + |
|
434 | + public function getPrivateKey($client_id = null) |
|
435 | + { |
|
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'])); |
|
437 | + |
|
438 | + $stmt->execute(compact('client_id')); |
|
439 | + if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
440 | + return $result['private_key']; |
|
441 | + } |
|
442 | + } |
|
443 | + |
|
444 | + public function getEncryptionAlgorithm($client_id = null) |
|
445 | + { |
|
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'])); |
|
447 | + |
|
448 | + $stmt->execute(compact('client_id')); |
|
449 | + if ($result = $stmt->fetch(\PDO::FETCH_ASSOC)) { |
|
450 | + return $result['encryption_algorithm']; |
|
451 | + } |
|
452 | + |
|
453 | + return 'RS256'; |
|
454 | + } |
|
455 | + |
|
456 | + /** |
|
457 | + * DDL to create OAuth2 database and tables for PDO storage |
|
458 | + * |
|
459 | + * @see https://github.com/dsquier/oauth2-server-php-mysql |
|
460 | + */ |
|
461 | + public function getBuildSql($dbName = 'oauth2_server_php') |
|
462 | + { |
|
463 | + $sql = " |
|
464 | 464 | CREATE TABLE {$this->config['client_table']} ( |
465 | 465 | client_id VARCHAR(80) NOT NULL, |
466 | 466 | client_secret VARCHAR(80) NOT NULL, |
@@ -538,6 +538,6 @@ discard block |
||
538 | 538 | ) |
539 | 539 | "; |
540 | 540 | |
541 | - return $sql; |
|
542 | - } |
|
541 | + return $sql; |
|
542 | + } |
|
543 | 543 | } |
@@ -361,7 +361,7 @@ |
||
361 | 361 | $stmt->execute(array('is_default' => true)); |
362 | 362 | |
363 | 363 | if ($result = $stmt->fetchAll(\PDO::FETCH_ASSOC)) { |
364 | - $defaultScope = array_map(function ($row) { |
|
364 | + $defaultScope = array_map(function($row) { |
|
365 | 365 | return $row['scope']; |
366 | 366 | }, $result); |
367 | 367 |
@@ -11,42 +11,42 @@ |
||
11 | 11 | */ |
12 | 12 | interface UserCredentialsInterface |
13 | 13 | { |
14 | - /** |
|
15 | - * Grant access tokens for basic user credentials. |
|
16 | - * |
|
17 | - * Check the supplied username and password for validity. |
|
18 | - * |
|
19 | - * You can also use the $client_id param to do any checks required based |
|
20 | - * on a client, if you need that. |
|
21 | - * |
|
22 | - * Required for OAuth2::GRANT_TYPE_USER_CREDENTIALS. |
|
23 | - * |
|
24 | - * @param $username |
|
25 | - * Username to be check with. |
|
26 | - * @param $password |
|
27 | - * Password to be check with. |
|
28 | - * |
|
29 | - * @return |
|
30 | - * TRUE if the username and password are valid, and FALSE if it isn't. |
|
31 | - * Moreover, if the username and password are valid, and you want to |
|
32 | - * |
|
33 | - * @see http://tools.ietf.org/html/rfc6749#section-4.3 |
|
34 | - * |
|
35 | - * @ingroup oauth2_section_4 |
|
36 | - */ |
|
37 | - public function checkUserCredentials($username, $password); |
|
14 | + /** |
|
15 | + * Grant access tokens for basic user credentials. |
|
16 | + * |
|
17 | + * Check the supplied username and password for validity. |
|
18 | + * |
|
19 | + * You can also use the $client_id param to do any checks required based |
|
20 | + * on a client, if you need that. |
|
21 | + * |
|
22 | + * Required for OAuth2::GRANT_TYPE_USER_CREDENTIALS. |
|
23 | + * |
|
24 | + * @param $username |
|
25 | + * Username to be check with. |
|
26 | + * @param $password |
|
27 | + * Password to be check with. |
|
28 | + * |
|
29 | + * @return |
|
30 | + * TRUE if the username and password are valid, and FALSE if it isn't. |
|
31 | + * Moreover, if the username and password are valid, and you want to |
|
32 | + * |
|
33 | + * @see http://tools.ietf.org/html/rfc6749#section-4.3 |
|
34 | + * |
|
35 | + * @ingroup oauth2_section_4 |
|
36 | + */ |
|
37 | + public function checkUserCredentials($username, $password); |
|
38 | 38 | |
39 | - /** |
|
40 | - * @return |
|
41 | - * ARRAY the associated "user_id" and optional "scope" values |
|
42 | - * This function MUST return FALSE if the requested user does not exist or is |
|
43 | - * invalid. "scope" is a space-separated list of restricted scopes. |
|
44 | - * @code |
|
45 | - * return array( |
|
46 | - * "user_id" => USER_ID, // REQUIRED user_id to be stored with the authorization code or access token |
|
47 | - * "scope" => SCOPE // OPTIONAL space-separated list of restricted scopes |
|
48 | - * ); |
|
49 | - * @endcode |
|
50 | - */ |
|
51 | - public function getUserDetails($username); |
|
39 | + /** |
|
40 | + * @return |
|
41 | + * ARRAY the associated "user_id" and optional "scope" values |
|
42 | + * This function MUST return FALSE if the requested user does not exist or is |
|
43 | + * invalid. "scope" is a space-separated list of restricted scopes. |
|
44 | + * @code |
|
45 | + * return array( |
|
46 | + * "user_id" => USER_ID, // REQUIRED user_id to be stored with the authorization code or access token |
|
47 | + * "scope" => SCOPE // OPTIONAL space-separated list of restricted scopes |
|
48 | + * ); |
|
49 | + * @endcode |
|
50 | + */ |
|
51 | + public function getUserDetails($username); |
|
52 | 52 | } |
@@ -10,7 +10,7 @@ |
||
10 | 10 | */ |
11 | 11 | interface PublicKeyInterface |
12 | 12 | { |
13 | - public function getPublicKey($client_id = null); |
|
14 | - public function getPrivateKey($client_id = null); |
|
15 | - public function getEncryptionAlgorithm($client_id = null); |
|
13 | + public function getPublicKey($client_id = null); |
|
14 | + public function getPrivateKey($client_id = null); |
|
15 | + public function getEncryptionAlgorithm($client_id = null); |
|
16 | 16 | } |
@@ -11,78 +11,78 @@ |
||
11 | 11 | */ |
12 | 12 | class JwtAccessToken implements JwtAccessTokenInterface |
13 | 13 | { |
14 | - protected $publicKeyStorage; |
|
15 | - protected $tokenStorage; |
|
16 | - protected $encryptionUtil; |
|
14 | + protected $publicKeyStorage; |
|
15 | + protected $tokenStorage; |
|
16 | + protected $encryptionUtil; |
|
17 | 17 | |
18 | - /** |
|
19 | - * @param OAuth2\Encryption\PublicKeyInterface $publicKeyStorage the public key encryption to use |
|
20 | - * @param OAuth2\Storage\AccessTokenInterface $tokenStorage OPTIONAL persist the access token to another storage. This is useful if |
|
21 | - * you want to retain access token grant information somewhere, but |
|
22 | - * is not necessary when using this grant type. |
|
23 | - * @param OAuth2\Encryption\EncryptionInterface $encryptionUtil OPTIONAL class to use for "encode" and "decode" functions. |
|
24 | - */ |
|
25 | - public function __construct(PublicKeyInterface $publicKeyStorage, AccessTokenInterface $tokenStorage = null, EncryptionInterface $encryptionUtil = null) |
|
26 | - { |
|
27 | - $this->publicKeyStorage = $publicKeyStorage; |
|
28 | - $this->tokenStorage = $tokenStorage; |
|
29 | - if (is_null($encryptionUtil)) { |
|
30 | - $encryptionUtil = new Jwt; |
|
31 | - } |
|
32 | - $this->encryptionUtil = $encryptionUtil; |
|
33 | - } |
|
18 | + /** |
|
19 | + * @param OAuth2\Encryption\PublicKeyInterface $publicKeyStorage the public key encryption to use |
|
20 | + * @param OAuth2\Storage\AccessTokenInterface $tokenStorage OPTIONAL persist the access token to another storage. This is useful if |
|
21 | + * you want to retain access token grant information somewhere, but |
|
22 | + * is not necessary when using this grant type. |
|
23 | + * @param OAuth2\Encryption\EncryptionInterface $encryptionUtil OPTIONAL class to use for "encode" and "decode" functions. |
|
24 | + */ |
|
25 | + public function __construct(PublicKeyInterface $publicKeyStorage, AccessTokenInterface $tokenStorage = null, EncryptionInterface $encryptionUtil = null) |
|
26 | + { |
|
27 | + $this->publicKeyStorage = $publicKeyStorage; |
|
28 | + $this->tokenStorage = $tokenStorage; |
|
29 | + if (is_null($encryptionUtil)) { |
|
30 | + $encryptionUtil = new Jwt; |
|
31 | + } |
|
32 | + $this->encryptionUtil = $encryptionUtil; |
|
33 | + } |
|
34 | 34 | |
35 | - public function getAccessToken($oauth_token) |
|
36 | - { |
|
37 | - // just decode the token, don't verify |
|
38 | - if (!$tokenData = $this->encryptionUtil->decode($oauth_token, null, false)) { |
|
39 | - return false; |
|
40 | - } |
|
35 | + public function getAccessToken($oauth_token) |
|
36 | + { |
|
37 | + // just decode the token, don't verify |
|
38 | + if (!$tokenData = $this->encryptionUtil->decode($oauth_token, null, false)) { |
|
39 | + return false; |
|
40 | + } |
|
41 | 41 | |
42 | - $client_id = isset($tokenData['aud']) ? $tokenData['aud'] : null; |
|
43 | - $public_key = $this->publicKeyStorage->getPublicKey($client_id); |
|
44 | - $algorithm = $this->publicKeyStorage->getEncryptionAlgorithm($client_id); |
|
42 | + $client_id = isset($tokenData['aud']) ? $tokenData['aud'] : null; |
|
43 | + $public_key = $this->publicKeyStorage->getPublicKey($client_id); |
|
44 | + $algorithm = $this->publicKeyStorage->getEncryptionAlgorithm($client_id); |
|
45 | 45 | |
46 | - // now that we have the client_id, verify the token |
|
47 | - if (false === $this->encryptionUtil->decode($oauth_token, $public_key, array($algorithm))) { |
|
48 | - return false; |
|
49 | - } |
|
46 | + // now that we have the client_id, verify the token |
|
47 | + if (false === $this->encryptionUtil->decode($oauth_token, $public_key, array($algorithm))) { |
|
48 | + return false; |
|
49 | + } |
|
50 | 50 | |
51 | - // normalize the JWT claims to the format expected by other components in this library |
|
52 | - return $this->convertJwtToOAuth2($tokenData); |
|
53 | - } |
|
51 | + // normalize the JWT claims to the format expected by other components in this library |
|
52 | + return $this->convertJwtToOAuth2($tokenData); |
|
53 | + } |
|
54 | 54 | |
55 | - public function setAccessToken($oauth_token, $client_id, $user_id, $expires, $scope = null) |
|
56 | - { |
|
57 | - if ($this->tokenStorage) { |
|
58 | - return $this->tokenStorage->setAccessToken($oauth_token, $client_id, $user_id, $expires, $scope); |
|
59 | - } |
|
60 | - } |
|
55 | + public function setAccessToken($oauth_token, $client_id, $user_id, $expires, $scope = null) |
|
56 | + { |
|
57 | + if ($this->tokenStorage) { |
|
58 | + return $this->tokenStorage->setAccessToken($oauth_token, $client_id, $user_id, $expires, $scope); |
|
59 | + } |
|
60 | + } |
|
61 | 61 | |
62 | - public function unsetAccessToken($access_token) |
|
63 | - { |
|
64 | - if ($this->tokenStorage) { |
|
65 | - return $this->tokenStorage->unsetAccessToken($access_token); |
|
66 | - } |
|
67 | - } |
|
62 | + public function unsetAccessToken($access_token) |
|
63 | + { |
|
64 | + if ($this->tokenStorage) { |
|
65 | + return $this->tokenStorage->unsetAccessToken($access_token); |
|
66 | + } |
|
67 | + } |
|
68 | 68 | |
69 | 69 | |
70 | - // converts a JWT access token into an OAuth2-friendly format |
|
71 | - protected function convertJwtToOAuth2($tokenData) |
|
72 | - { |
|
73 | - $keyMapping = array( |
|
74 | - 'aud' => 'client_id', |
|
75 | - 'exp' => 'expires', |
|
76 | - 'sub' => 'user_id' |
|
77 | - ); |
|
70 | + // converts a JWT access token into an OAuth2-friendly format |
|
71 | + protected function convertJwtToOAuth2($tokenData) |
|
72 | + { |
|
73 | + $keyMapping = array( |
|
74 | + 'aud' => 'client_id', |
|
75 | + 'exp' => 'expires', |
|
76 | + 'sub' => 'user_id' |
|
77 | + ); |
|
78 | 78 | |
79 | - foreach ($keyMapping as $jwtKey => $oauth2Key) { |
|
80 | - if (isset($tokenData[$jwtKey])) { |
|
81 | - $tokenData[$oauth2Key] = $tokenData[$jwtKey]; |
|
82 | - unset($tokenData[$jwtKey]); |
|
83 | - } |
|
84 | - } |
|
79 | + foreach ($keyMapping as $jwtKey => $oauth2Key) { |
|
80 | + if (isset($tokenData[$jwtKey])) { |
|
81 | + $tokenData[$oauth2Key] = $tokenData[$jwtKey]; |
|
82 | + unset($tokenData[$jwtKey]); |
|
83 | + } |
|
84 | + } |
|
85 | 85 | |
86 | - return $tokenData; |
|
87 | - } |
|
86 | + return $tokenData; |
|
87 | + } |
|
88 | 88 | } |
@@ -11,76 +11,76 @@ |
||
11 | 11 | */ |
12 | 12 | interface AuthorizationCodeInterface |
13 | 13 | { |
14 | - /** |
|
15 | - * The Authorization Code grant type supports a response type of "code". |
|
16 | - * |
|
17 | - * @var string |
|
18 | - * @see http://tools.ietf.org/html/rfc6749#section-1.4.1 |
|
19 | - * @see http://tools.ietf.org/html/rfc6749#section-4.2 |
|
20 | - */ |
|
21 | - const RESPONSE_TYPE_CODE = "code"; |
|
14 | + /** |
|
15 | + * The Authorization Code grant type supports a response type of "code". |
|
16 | + * |
|
17 | + * @var string |
|
18 | + * @see http://tools.ietf.org/html/rfc6749#section-1.4.1 |
|
19 | + * @see http://tools.ietf.org/html/rfc6749#section-4.2 |
|
20 | + */ |
|
21 | + const RESPONSE_TYPE_CODE = "code"; |
|
22 | 22 | |
23 | - /** |
|
24 | - * Fetch authorization code data (probably the most common grant type). |
|
25 | - * |
|
26 | - * Retrieve the stored data for the given authorization code. |
|
27 | - * |
|
28 | - * Required for OAuth2::GRANT_TYPE_AUTH_CODE. |
|
29 | - * |
|
30 | - * @param $code |
|
31 | - * Authorization code to be check with. |
|
32 | - * |
|
33 | - * @return |
|
34 | - * An associative array as below, and NULL if the code is invalid |
|
35 | - * @code |
|
36 | - * return array( |
|
37 | - * "client_id" => CLIENT_ID, // REQUIRED Stored client identifier |
|
38 | - * "user_id" => USER_ID, // REQUIRED Stored user identifier |
|
39 | - * "expires" => EXPIRES, // REQUIRED Stored expiration in unix timestamp |
|
40 | - * "redirect_uri" => REDIRECT_URI, // REQUIRED Stored redirect URI |
|
41 | - * "scope" => SCOPE, // OPTIONAL Stored scope values in space-separated string |
|
42 | - * ); |
|
43 | - * @endcode |
|
44 | - * |
|
45 | - * @see http://tools.ietf.org/html/rfc6749#section-4.1 |
|
46 | - * |
|
47 | - * @ingroup oauth2_section_4 |
|
48 | - */ |
|
49 | - public function getAuthorizationCode($code); |
|
23 | + /** |
|
24 | + * Fetch authorization code data (probably the most common grant type). |
|
25 | + * |
|
26 | + * Retrieve the stored data for the given authorization code. |
|
27 | + * |
|
28 | + * Required for OAuth2::GRANT_TYPE_AUTH_CODE. |
|
29 | + * |
|
30 | + * @param $code |
|
31 | + * Authorization code to be check with. |
|
32 | + * |
|
33 | + * @return |
|
34 | + * An associative array as below, and NULL if the code is invalid |
|
35 | + * @code |
|
36 | + * return array( |
|
37 | + * "client_id" => CLIENT_ID, // REQUIRED Stored client identifier |
|
38 | + * "user_id" => USER_ID, // REQUIRED Stored user identifier |
|
39 | + * "expires" => EXPIRES, // REQUIRED Stored expiration in unix timestamp |
|
40 | + * "redirect_uri" => REDIRECT_URI, // REQUIRED Stored redirect URI |
|
41 | + * "scope" => SCOPE, // OPTIONAL Stored scope values in space-separated string |
|
42 | + * ); |
|
43 | + * @endcode |
|
44 | + * |
|
45 | + * @see http://tools.ietf.org/html/rfc6749#section-4.1 |
|
46 | + * |
|
47 | + * @ingroup oauth2_section_4 |
|
48 | + */ |
|
49 | + public function getAuthorizationCode($code); |
|
50 | 50 | |
51 | - /** |
|
52 | - * Take the provided authorization code values and store them somewhere. |
|
53 | - * |
|
54 | - * This function should be the storage counterpart to getAuthCode(). |
|
55 | - * |
|
56 | - * If storage fails for some reason, we're not currently checking for |
|
57 | - * any sort of success/failure, so you should bail out of the script |
|
58 | - * and provide a descriptive fail message. |
|
59 | - * |
|
60 | - * Required for OAuth2::GRANT_TYPE_AUTH_CODE. |
|
61 | - * |
|
62 | - * @param string $code Authorization code to be stored. |
|
63 | - * @param mixed $client_id Client identifier to be stored. |
|
64 | - * @param mixed $user_id User identifier to be stored. |
|
65 | - * @param string $redirect_uri Redirect URI(s) to be stored in a space-separated string. |
|
66 | - * @param int $expires Expiration to be stored as a Unix timestamp. |
|
67 | - * @param string $scope OPTIONAL Scopes to be stored in space-separated string. |
|
68 | - * |
|
69 | - * @ingroup oauth2_section_4 |
|
70 | - */ |
|
71 | - public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null); |
|
51 | + /** |
|
52 | + * Take the provided authorization code values and store them somewhere. |
|
53 | + * |
|
54 | + * This function should be the storage counterpart to getAuthCode(). |
|
55 | + * |
|
56 | + * If storage fails for some reason, we're not currently checking for |
|
57 | + * any sort of success/failure, so you should bail out of the script |
|
58 | + * and provide a descriptive fail message. |
|
59 | + * |
|
60 | + * Required for OAuth2::GRANT_TYPE_AUTH_CODE. |
|
61 | + * |
|
62 | + * @param string $code Authorization code to be stored. |
|
63 | + * @param mixed $client_id Client identifier to be stored. |
|
64 | + * @param mixed $user_id User identifier to be stored. |
|
65 | + * @param string $redirect_uri Redirect URI(s) to be stored in a space-separated string. |
|
66 | + * @param int $expires Expiration to be stored as a Unix timestamp. |
|
67 | + * @param string $scope OPTIONAL Scopes to be stored in space-separated string. |
|
68 | + * |
|
69 | + * @ingroup oauth2_section_4 |
|
70 | + */ |
|
71 | + public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null); |
|
72 | 72 | |
73 | - /** |
|
74 | - * once an Authorization Code is used, it must be exipired |
|
75 | - * |
|
76 | - * @see http://tools.ietf.org/html/rfc6749#section-4.1.2 |
|
77 | - * |
|
78 | - * The client MUST NOT use the authorization code |
|
79 | - * more than once. If an authorization code is used more than |
|
80 | - * once, the authorization server MUST deny the request and SHOULD |
|
81 | - * revoke (when possible) all tokens previously issued based on |
|
82 | - * that authorization code |
|
83 | - * |
|
84 | - */ |
|
85 | - public function expireAuthorizationCode($code); |
|
73 | + /** |
|
74 | + * once an Authorization Code is used, it must be exipired |
|
75 | + * |
|
76 | + * @see http://tools.ietf.org/html/rfc6749#section-4.1.2 |
|
77 | + * |
|
78 | + * The client MUST NOT use the authorization code |
|
79 | + * more than once. If an authorization code is used more than |
|
80 | + * once, the authorization server MUST deny the request and SHOULD |
|
81 | + * revoke (when possible) all tokens previously issued based on |
|
82 | + * that authorization code |
|
83 | + * |
|
84 | + */ |
|
85 | + public function expireAuthorizationCode($code); |
|
86 | 86 | } |
@@ -17,317 +17,317 @@ |
||
17 | 17 | * @author Julien Chaumond <[email protected]> |
18 | 18 | */ |
19 | 19 | class Mongo implements AuthorizationCodeInterface, |
20 | - AccessTokenInterface, |
|
21 | - ClientCredentialsInterface, |
|
22 | - UserCredentialsInterface, |
|
23 | - RefreshTokenInterface, |
|
24 | - JwtBearerInterface, |
|
25 | - OpenIDAuthorizationCodeInterface |
|
20 | + AccessTokenInterface, |
|
21 | + ClientCredentialsInterface, |
|
22 | + UserCredentialsInterface, |
|
23 | + RefreshTokenInterface, |
|
24 | + JwtBearerInterface, |
|
25 | + OpenIDAuthorizationCodeInterface |
|
26 | 26 | { |
27 | - protected $db; |
|
28 | - protected $config; |
|
29 | - |
|
30 | - public function __construct($connection, $config = array()) |
|
31 | - { |
|
32 | - if ($connection instanceof \MongoDB) { |
|
33 | - $this->db = $connection; |
|
34 | - } else { |
|
35 | - if (!is_array($connection)) { |
|
36 | - throw new \InvalidArgumentException('First argument to OAuth2\Storage\Mongo must be an instance of MongoDB or a configuration array'); |
|
37 | - } |
|
38 | - $server = sprintf('mongodb://%s:%d', $connection['host'], $connection['port']); |
|
39 | - $m = new \MongoClient($server); |
|
40 | - $this->db = $m->{$connection['database']}; |
|
41 | - } |
|
42 | - |
|
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 | - |
|
53 | - // Helper function to access a MongoDB collection by `type`: |
|
54 | - protected function collection($name) |
|
55 | - { |
|
56 | - return $this->db->{$this->config[$name]}; |
|
57 | - } |
|
58 | - |
|
59 | - /* ClientCredentialsInterface */ |
|
60 | - public function checkClientCredentials($client_id, $client_secret = null) |
|
61 | - { |
|
62 | - if ($result = $this->collection('client_table')->findOne(array('client_id' => $client_id))) { |
|
63 | - return $result['client_secret'] == $client_secret; |
|
64 | - } |
|
65 | - |
|
66 | - return false; |
|
67 | - } |
|
68 | - |
|
69 | - public function isPublicClient($client_id) |
|
70 | - { |
|
71 | - if (!$result = $this->collection('client_table')->findOne(array('client_id' => $client_id))) { |
|
72 | - return false; |
|
73 | - } |
|
74 | - |
|
75 | - return empty($result['client_secret']); |
|
76 | - } |
|
77 | - |
|
78 | - /* ClientInterface */ |
|
79 | - public function getClientDetails($client_id) |
|
80 | - { |
|
81 | - $result = $this->collection('client_table')->findOne(array('client_id' => $client_id)); |
|
82 | - |
|
83 | - return is_null($result) ? false : $result; |
|
84 | - } |
|
85 | - |
|
86 | - public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
87 | - { |
|
88 | - if ($this->getClientDetails($client_id)) { |
|
89 | - $this->collection('client_table')->update( |
|
90 | - array('client_id' => $client_id), |
|
91 | - array('$set' => array( |
|
92 | - 'client_secret' => $client_secret, |
|
93 | - 'redirect_uri' => $redirect_uri, |
|
94 | - 'grant_types' => $grant_types, |
|
95 | - 'scope' => $scope, |
|
96 | - 'user_id' => $user_id, |
|
97 | - )) |
|
98 | - ); |
|
99 | - } else { |
|
100 | - $client = array( |
|
101 | - 'client_id' => $client_id, |
|
102 | - 'client_secret' => $client_secret, |
|
103 | - 'redirect_uri' => $redirect_uri, |
|
104 | - 'grant_types' => $grant_types, |
|
105 | - 'scope' => $scope, |
|
106 | - 'user_id' => $user_id, |
|
107 | - ); |
|
108 | - $this->collection('client_table')->insert($client); |
|
109 | - } |
|
110 | - |
|
111 | - return true; |
|
112 | - } |
|
113 | - |
|
114 | - public function checkRestrictedGrantType($client_id, $grant_type) |
|
115 | - { |
|
116 | - $details = $this->getClientDetails($client_id); |
|
117 | - if (isset($details['grant_types'])) { |
|
118 | - $grant_types = explode(' ', $details['grant_types']); |
|
119 | - |
|
120 | - return in_array($grant_type, $grant_types); |
|
121 | - } |
|
122 | - |
|
123 | - // if grant_types are not defined, then none are restricted |
|
124 | - return true; |
|
125 | - } |
|
126 | - |
|
127 | - /* AccessTokenInterface */ |
|
128 | - public function getAccessToken($access_token) |
|
129 | - { |
|
130 | - $token = $this->collection('access_token_table')->findOne(array('access_token' => $access_token)); |
|
131 | - |
|
132 | - return is_null($token) ? false : $token; |
|
133 | - } |
|
134 | - |
|
135 | - public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
136 | - { |
|
137 | - // if it exists, update it. |
|
138 | - if ($this->getAccessToken($access_token)) { |
|
139 | - $this->collection('access_token_table')->update( |
|
140 | - array('access_token' => $access_token), |
|
141 | - array('$set' => array( |
|
142 | - 'client_id' => $client_id, |
|
143 | - 'expires' => $expires, |
|
144 | - 'user_id' => $user_id, |
|
145 | - 'scope' => $scope |
|
146 | - )) |
|
147 | - ); |
|
148 | - } else { |
|
149 | - $token = array( |
|
150 | - 'access_token' => $access_token, |
|
151 | - 'client_id' => $client_id, |
|
152 | - 'expires' => $expires, |
|
153 | - 'user_id' => $user_id, |
|
154 | - 'scope' => $scope |
|
155 | - ); |
|
156 | - $this->collection('access_token_table')->insert($token); |
|
157 | - } |
|
158 | - |
|
159 | - return true; |
|
160 | - } |
|
161 | - |
|
162 | - public function unsetAccessToken($access_token) |
|
163 | - { |
|
164 | - $this->collection('access_token_table')->remove(array('access_token' => $access_token)); |
|
165 | - } |
|
166 | - |
|
167 | - |
|
168 | - /* AuthorizationCodeInterface */ |
|
169 | - public function getAuthorizationCode($code) |
|
170 | - { |
|
171 | - $code = $this->collection('code_table')->findOne(array('authorization_code' => $code)); |
|
172 | - |
|
173 | - return is_null($code) ? false : $code; |
|
174 | - } |
|
175 | - |
|
176 | - public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
177 | - { |
|
178 | - // if it exists, update it. |
|
179 | - if ($this->getAuthorizationCode($code)) { |
|
180 | - $this->collection('code_table')->update( |
|
181 | - array('authorization_code' => $code), |
|
182 | - array('$set' => array( |
|
183 | - 'client_id' => $client_id, |
|
184 | - 'user_id' => $user_id, |
|
185 | - 'redirect_uri' => $redirect_uri, |
|
186 | - 'expires' => $expires, |
|
187 | - 'scope' => $scope, |
|
188 | - 'id_token' => $id_token, |
|
189 | - )) |
|
190 | - ); |
|
191 | - } else { |
|
192 | - $token = array( |
|
193 | - 'authorization_code' => $code, |
|
194 | - 'client_id' => $client_id, |
|
195 | - 'user_id' => $user_id, |
|
196 | - 'redirect_uri' => $redirect_uri, |
|
197 | - 'expires' => $expires, |
|
198 | - 'scope' => $scope, |
|
199 | - 'id_token' => $id_token, |
|
200 | - ); |
|
201 | - $this->collection('code_table')->insert($token); |
|
202 | - } |
|
203 | - |
|
204 | - return true; |
|
205 | - } |
|
206 | - |
|
207 | - public function expireAuthorizationCode($code) |
|
208 | - { |
|
209 | - $this->collection('code_table')->remove(array('authorization_code' => $code)); |
|
210 | - |
|
211 | - return true; |
|
212 | - } |
|
213 | - |
|
214 | - /* UserCredentialsInterface */ |
|
215 | - public function checkUserCredentials($username, $password) |
|
216 | - { |
|
217 | - if ($user = $this->getUser($username)) { |
|
218 | - return $this->checkPassword($user, $password); |
|
219 | - } |
|
220 | - |
|
221 | - return false; |
|
222 | - } |
|
223 | - |
|
224 | - public function getUserDetails($username) |
|
225 | - { |
|
226 | - if ($user = $this->getUser($username)) { |
|
227 | - $user['user_id'] = $user['username']; |
|
228 | - } |
|
229 | - |
|
230 | - return $user; |
|
231 | - } |
|
232 | - |
|
233 | - /* RefreshTokenInterface */ |
|
234 | - public function getRefreshToken($refresh_token) |
|
235 | - { |
|
236 | - $token = $this->collection('refresh_token_table')->findOne(array('refresh_token' => $refresh_token)); |
|
237 | - |
|
238 | - return is_null($token) ? false : $token; |
|
239 | - } |
|
240 | - |
|
241 | - public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
242 | - { |
|
243 | - $token = array( |
|
244 | - 'refresh_token' => $refresh_token, |
|
245 | - 'client_id' => $client_id, |
|
246 | - 'user_id' => $user_id, |
|
247 | - 'expires' => $expires, |
|
248 | - 'scope' => $scope |
|
249 | - ); |
|
250 | - $this->collection('refresh_token_table')->insert($token); |
|
251 | - |
|
252 | - return true; |
|
253 | - } |
|
254 | - |
|
255 | - public function unsetRefreshToken($refresh_token) |
|
256 | - { |
|
257 | - $this->collection('refresh_token_table')->remove(array('refresh_token' => $refresh_token)); |
|
258 | - |
|
259 | - return true; |
|
260 | - } |
|
261 | - |
|
262 | - // plaintext passwords are bad! Override this for your application |
|
263 | - protected function checkPassword($user, $password) |
|
264 | - { |
|
265 | - return $user['password'] == $password; |
|
266 | - } |
|
267 | - |
|
268 | - public function getUser($username) |
|
269 | - { |
|
270 | - $result = $this->collection('user_table')->findOne(array('username' => $username)); |
|
271 | - |
|
272 | - return is_null($result) ? false : $result; |
|
273 | - } |
|
274 | - |
|
275 | - public function setUser($username, $password, $firstName = null, $lastName = null) |
|
276 | - { |
|
277 | - if ($this->getUser($username)) { |
|
278 | - $this->collection('user_table')->update( |
|
279 | - array('username' => $username), |
|
280 | - array('$set' => array( |
|
281 | - 'password' => $password, |
|
282 | - 'first_name' => $firstName, |
|
283 | - 'last_name' => $lastName |
|
284 | - )) |
|
285 | - ); |
|
286 | - } else { |
|
287 | - $user = array( |
|
288 | - 'username' => $username, |
|
289 | - 'password' => $password, |
|
290 | - 'first_name' => $firstName, |
|
291 | - 'last_name' => $lastName |
|
292 | - ); |
|
293 | - $this->collection('user_table')->insert($user); |
|
294 | - } |
|
295 | - |
|
296 | - return true; |
|
297 | - } |
|
298 | - |
|
299 | - public function getClientKey($client_id, $subject) |
|
300 | - { |
|
301 | - $result = $this->collection('jwt_table')->findOne(array( |
|
302 | - 'client_id' => $client_id, |
|
303 | - 'subject' => $subject |
|
304 | - )); |
|
305 | - |
|
306 | - return is_null($result) ? false : $result['key']; |
|
307 | - } |
|
308 | - |
|
309 | - public function getClientScope($client_id) |
|
310 | - { |
|
311 | - if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
312 | - return false; |
|
313 | - } |
|
314 | - |
|
315 | - if (isset($clientDetails['scope'])) { |
|
316 | - return $clientDetails['scope']; |
|
317 | - } |
|
318 | - |
|
319 | - return null; |
|
320 | - } |
|
321 | - |
|
322 | - public function getJti($client_id, $subject, $audience, $expiration, $jti) |
|
323 | - { |
|
324 | - //TODO: Needs mongodb implementation. |
|
325 | - throw new \Exception('getJti() for the MongoDB driver is currently unimplemented.'); |
|
326 | - } |
|
327 | - |
|
328 | - public function setJti($client_id, $subject, $audience, $expiration, $jti) |
|
329 | - { |
|
330 | - //TODO: Needs mongodb implementation. |
|
331 | - throw new \Exception('setJti() for the MongoDB driver is currently unimplemented.'); |
|
332 | - } |
|
27 | + protected $db; |
|
28 | + protected $config; |
|
29 | + |
|
30 | + public function __construct($connection, $config = array()) |
|
31 | + { |
|
32 | + if ($connection instanceof \MongoDB) { |
|
33 | + $this->db = $connection; |
|
34 | + } else { |
|
35 | + if (!is_array($connection)) { |
|
36 | + throw new \InvalidArgumentException('First argument to OAuth2\Storage\Mongo must be an instance of MongoDB or a configuration array'); |
|
37 | + } |
|
38 | + $server = sprintf('mongodb://%s:%d', $connection['host'], $connection['port']); |
|
39 | + $m = new \MongoClient($server); |
|
40 | + $this->db = $m->{$connection['database']}; |
|
41 | + } |
|
42 | + |
|
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 | + |
|
53 | + // Helper function to access a MongoDB collection by `type`: |
|
54 | + protected function collection($name) |
|
55 | + { |
|
56 | + return $this->db->{$this->config[$name]}; |
|
57 | + } |
|
58 | + |
|
59 | + /* ClientCredentialsInterface */ |
|
60 | + public function checkClientCredentials($client_id, $client_secret = null) |
|
61 | + { |
|
62 | + if ($result = $this->collection('client_table')->findOne(array('client_id' => $client_id))) { |
|
63 | + return $result['client_secret'] == $client_secret; |
|
64 | + } |
|
65 | + |
|
66 | + return false; |
|
67 | + } |
|
68 | + |
|
69 | + public function isPublicClient($client_id) |
|
70 | + { |
|
71 | + if (!$result = $this->collection('client_table')->findOne(array('client_id' => $client_id))) { |
|
72 | + return false; |
|
73 | + } |
|
74 | + |
|
75 | + return empty($result['client_secret']); |
|
76 | + } |
|
77 | + |
|
78 | + /* ClientInterface */ |
|
79 | + public function getClientDetails($client_id) |
|
80 | + { |
|
81 | + $result = $this->collection('client_table')->findOne(array('client_id' => $client_id)); |
|
82 | + |
|
83 | + return is_null($result) ? false : $result; |
|
84 | + } |
|
85 | + |
|
86 | + public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
87 | + { |
|
88 | + if ($this->getClientDetails($client_id)) { |
|
89 | + $this->collection('client_table')->update( |
|
90 | + array('client_id' => $client_id), |
|
91 | + array('$set' => array( |
|
92 | + 'client_secret' => $client_secret, |
|
93 | + 'redirect_uri' => $redirect_uri, |
|
94 | + 'grant_types' => $grant_types, |
|
95 | + 'scope' => $scope, |
|
96 | + 'user_id' => $user_id, |
|
97 | + )) |
|
98 | + ); |
|
99 | + } else { |
|
100 | + $client = array( |
|
101 | + 'client_id' => $client_id, |
|
102 | + 'client_secret' => $client_secret, |
|
103 | + 'redirect_uri' => $redirect_uri, |
|
104 | + 'grant_types' => $grant_types, |
|
105 | + 'scope' => $scope, |
|
106 | + 'user_id' => $user_id, |
|
107 | + ); |
|
108 | + $this->collection('client_table')->insert($client); |
|
109 | + } |
|
110 | + |
|
111 | + return true; |
|
112 | + } |
|
113 | + |
|
114 | + public function checkRestrictedGrantType($client_id, $grant_type) |
|
115 | + { |
|
116 | + $details = $this->getClientDetails($client_id); |
|
117 | + if (isset($details['grant_types'])) { |
|
118 | + $grant_types = explode(' ', $details['grant_types']); |
|
119 | + |
|
120 | + return in_array($grant_type, $grant_types); |
|
121 | + } |
|
122 | + |
|
123 | + // if grant_types are not defined, then none are restricted |
|
124 | + return true; |
|
125 | + } |
|
126 | + |
|
127 | + /* AccessTokenInterface */ |
|
128 | + public function getAccessToken($access_token) |
|
129 | + { |
|
130 | + $token = $this->collection('access_token_table')->findOne(array('access_token' => $access_token)); |
|
131 | + |
|
132 | + return is_null($token) ? false : $token; |
|
133 | + } |
|
134 | + |
|
135 | + public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
136 | + { |
|
137 | + // if it exists, update it. |
|
138 | + if ($this->getAccessToken($access_token)) { |
|
139 | + $this->collection('access_token_table')->update( |
|
140 | + array('access_token' => $access_token), |
|
141 | + array('$set' => array( |
|
142 | + 'client_id' => $client_id, |
|
143 | + 'expires' => $expires, |
|
144 | + 'user_id' => $user_id, |
|
145 | + 'scope' => $scope |
|
146 | + )) |
|
147 | + ); |
|
148 | + } else { |
|
149 | + $token = array( |
|
150 | + 'access_token' => $access_token, |
|
151 | + 'client_id' => $client_id, |
|
152 | + 'expires' => $expires, |
|
153 | + 'user_id' => $user_id, |
|
154 | + 'scope' => $scope |
|
155 | + ); |
|
156 | + $this->collection('access_token_table')->insert($token); |
|
157 | + } |
|
158 | + |
|
159 | + return true; |
|
160 | + } |
|
161 | + |
|
162 | + public function unsetAccessToken($access_token) |
|
163 | + { |
|
164 | + $this->collection('access_token_table')->remove(array('access_token' => $access_token)); |
|
165 | + } |
|
166 | + |
|
167 | + |
|
168 | + /* AuthorizationCodeInterface */ |
|
169 | + public function getAuthorizationCode($code) |
|
170 | + { |
|
171 | + $code = $this->collection('code_table')->findOne(array('authorization_code' => $code)); |
|
172 | + |
|
173 | + return is_null($code) ? false : $code; |
|
174 | + } |
|
175 | + |
|
176 | + public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
177 | + { |
|
178 | + // if it exists, update it. |
|
179 | + if ($this->getAuthorizationCode($code)) { |
|
180 | + $this->collection('code_table')->update( |
|
181 | + array('authorization_code' => $code), |
|
182 | + array('$set' => array( |
|
183 | + 'client_id' => $client_id, |
|
184 | + 'user_id' => $user_id, |
|
185 | + 'redirect_uri' => $redirect_uri, |
|
186 | + 'expires' => $expires, |
|
187 | + 'scope' => $scope, |
|
188 | + 'id_token' => $id_token, |
|
189 | + )) |
|
190 | + ); |
|
191 | + } else { |
|
192 | + $token = array( |
|
193 | + 'authorization_code' => $code, |
|
194 | + 'client_id' => $client_id, |
|
195 | + 'user_id' => $user_id, |
|
196 | + 'redirect_uri' => $redirect_uri, |
|
197 | + 'expires' => $expires, |
|
198 | + 'scope' => $scope, |
|
199 | + 'id_token' => $id_token, |
|
200 | + ); |
|
201 | + $this->collection('code_table')->insert($token); |
|
202 | + } |
|
203 | + |
|
204 | + return true; |
|
205 | + } |
|
206 | + |
|
207 | + public function expireAuthorizationCode($code) |
|
208 | + { |
|
209 | + $this->collection('code_table')->remove(array('authorization_code' => $code)); |
|
210 | + |
|
211 | + return true; |
|
212 | + } |
|
213 | + |
|
214 | + /* UserCredentialsInterface */ |
|
215 | + public function checkUserCredentials($username, $password) |
|
216 | + { |
|
217 | + if ($user = $this->getUser($username)) { |
|
218 | + return $this->checkPassword($user, $password); |
|
219 | + } |
|
220 | + |
|
221 | + return false; |
|
222 | + } |
|
223 | + |
|
224 | + public function getUserDetails($username) |
|
225 | + { |
|
226 | + if ($user = $this->getUser($username)) { |
|
227 | + $user['user_id'] = $user['username']; |
|
228 | + } |
|
229 | + |
|
230 | + return $user; |
|
231 | + } |
|
232 | + |
|
233 | + /* RefreshTokenInterface */ |
|
234 | + public function getRefreshToken($refresh_token) |
|
235 | + { |
|
236 | + $token = $this->collection('refresh_token_table')->findOne(array('refresh_token' => $refresh_token)); |
|
237 | + |
|
238 | + return is_null($token) ? false : $token; |
|
239 | + } |
|
240 | + |
|
241 | + public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
242 | + { |
|
243 | + $token = array( |
|
244 | + 'refresh_token' => $refresh_token, |
|
245 | + 'client_id' => $client_id, |
|
246 | + 'user_id' => $user_id, |
|
247 | + 'expires' => $expires, |
|
248 | + 'scope' => $scope |
|
249 | + ); |
|
250 | + $this->collection('refresh_token_table')->insert($token); |
|
251 | + |
|
252 | + return true; |
|
253 | + } |
|
254 | + |
|
255 | + public function unsetRefreshToken($refresh_token) |
|
256 | + { |
|
257 | + $this->collection('refresh_token_table')->remove(array('refresh_token' => $refresh_token)); |
|
258 | + |
|
259 | + return true; |
|
260 | + } |
|
261 | + |
|
262 | + // plaintext passwords are bad! Override this for your application |
|
263 | + protected function checkPassword($user, $password) |
|
264 | + { |
|
265 | + return $user['password'] == $password; |
|
266 | + } |
|
267 | + |
|
268 | + public function getUser($username) |
|
269 | + { |
|
270 | + $result = $this->collection('user_table')->findOne(array('username' => $username)); |
|
271 | + |
|
272 | + return is_null($result) ? false : $result; |
|
273 | + } |
|
274 | + |
|
275 | + public function setUser($username, $password, $firstName = null, $lastName = null) |
|
276 | + { |
|
277 | + if ($this->getUser($username)) { |
|
278 | + $this->collection('user_table')->update( |
|
279 | + array('username' => $username), |
|
280 | + array('$set' => array( |
|
281 | + 'password' => $password, |
|
282 | + 'first_name' => $firstName, |
|
283 | + 'last_name' => $lastName |
|
284 | + )) |
|
285 | + ); |
|
286 | + } else { |
|
287 | + $user = array( |
|
288 | + 'username' => $username, |
|
289 | + 'password' => $password, |
|
290 | + 'first_name' => $firstName, |
|
291 | + 'last_name' => $lastName |
|
292 | + ); |
|
293 | + $this->collection('user_table')->insert($user); |
|
294 | + } |
|
295 | + |
|
296 | + return true; |
|
297 | + } |
|
298 | + |
|
299 | + public function getClientKey($client_id, $subject) |
|
300 | + { |
|
301 | + $result = $this->collection('jwt_table')->findOne(array( |
|
302 | + 'client_id' => $client_id, |
|
303 | + 'subject' => $subject |
|
304 | + )); |
|
305 | + |
|
306 | + return is_null($result) ? false : $result['key']; |
|
307 | + } |
|
308 | + |
|
309 | + public function getClientScope($client_id) |
|
310 | + { |
|
311 | + if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
312 | + return false; |
|
313 | + } |
|
314 | + |
|
315 | + if (isset($clientDetails['scope'])) { |
|
316 | + return $clientDetails['scope']; |
|
317 | + } |
|
318 | + |
|
319 | + return null; |
|
320 | + } |
|
321 | + |
|
322 | + public function getJti($client_id, $subject, $audience, $expiration, $jti) |
|
323 | + { |
|
324 | + //TODO: Needs mongodb implementation. |
|
325 | + throw new \Exception('getJti() for the MongoDB driver is currently unimplemented.'); |
|
326 | + } |
|
327 | + |
|
328 | + public function setJti($client_id, $subject, $audience, $expiration, $jti) |
|
329 | + { |
|
330 | + //TODO: Needs mongodb implementation. |
|
331 | + throw new \Exception('setJti() for the MongoDB driver is currently unimplemented.'); |
|
332 | + } |
|
333 | 333 | } |
@@ -11,36 +11,36 @@ |
||
11 | 11 | */ |
12 | 12 | interface ScopeInterface |
13 | 13 | { |
14 | - /** |
|
15 | - * Check if the provided scope exists. |
|
16 | - * |
|
17 | - * @param $scope |
|
18 | - * A space-separated string of scopes. |
|
19 | - * |
|
20 | - * @return |
|
21 | - * TRUE if it exists, FALSE otherwise. |
|
22 | - */ |
|
23 | - public function scopeExists($scope); |
|
14 | + /** |
|
15 | + * Check if the provided scope exists. |
|
16 | + * |
|
17 | + * @param $scope |
|
18 | + * A space-separated string of scopes. |
|
19 | + * |
|
20 | + * @return |
|
21 | + * TRUE if it exists, FALSE otherwise. |
|
22 | + */ |
|
23 | + public function scopeExists($scope); |
|
24 | 24 | |
25 | - /** |
|
26 | - * The default scope to use in the event the client |
|
27 | - * does not request one. By returning "false", a |
|
28 | - * request_error is returned by the server to force a |
|
29 | - * scope request by the client. By returning "null", |
|
30 | - * opt out of requiring scopes |
|
31 | - * |
|
32 | - * @param $client_id |
|
33 | - * An optional client id that can be used to return customized default scopes. |
|
34 | - * |
|
35 | - * @return |
|
36 | - * string representation of default scope, null if |
|
37 | - * scopes are not defined, or false to force scope |
|
38 | - * request by the client |
|
39 | - * |
|
40 | - * ex: |
|
41 | - * 'default' |
|
42 | - * ex: |
|
43 | - * null |
|
44 | - */ |
|
45 | - public function getDefaultScope($client_id = null); |
|
25 | + /** |
|
26 | + * The default scope to use in the event the client |
|
27 | + * does not request one. By returning "false", a |
|
28 | + * request_error is returned by the server to force a |
|
29 | + * scope request by the client. By returning "null", |
|
30 | + * opt out of requiring scopes |
|
31 | + * |
|
32 | + * @param $client_id |
|
33 | + * An optional client id that can be used to return customized default scopes. |
|
34 | + * |
|
35 | + * @return |
|
36 | + * string representation of default scope, null if |
|
37 | + * scopes are not defined, or false to force scope |
|
38 | + * request by the client |
|
39 | + * |
|
40 | + * ex: |
|
41 | + * 'default' |
|
42 | + * ex: |
|
43 | + * null |
|
44 | + */ |
|
45 | + public function getDefaultScope($client_id = null); |
|
46 | 46 | } |
@@ -15,317 +15,317 @@ |
||
15 | 15 | * @author Tom Park <[email protected]> |
16 | 16 | */ |
17 | 17 | class CouchbaseDB implements AuthorizationCodeInterface, |
18 | - AccessTokenInterface, |
|
19 | - ClientCredentialsInterface, |
|
20 | - UserCredentialsInterface, |
|
21 | - RefreshTokenInterface, |
|
22 | - JwtBearerInterface, |
|
23 | - OpenIDAuthorizationCodeInterface |
|
18 | + AccessTokenInterface, |
|
19 | + ClientCredentialsInterface, |
|
20 | + UserCredentialsInterface, |
|
21 | + RefreshTokenInterface, |
|
22 | + JwtBearerInterface, |
|
23 | + OpenIDAuthorizationCodeInterface |
|
24 | 24 | { |
25 | - protected $db; |
|
26 | - protected $config; |
|
27 | - |
|
28 | - public function __construct($connection, $config = array()) |
|
29 | - { |
|
30 | - if ($connection instanceof \Couchbase) { |
|
31 | - $this->db = $connection; |
|
32 | - } else { |
|
33 | - if (!is_array($connection) || !is_array($connection['servers'])) { |
|
34 | - throw new \InvalidArgumentException('First argument to OAuth2\Storage\CouchbaseDB must be an instance of Couchbase or a configuration array containing a server array'); |
|
35 | - } |
|
36 | - |
|
37 | - $this->db = new \Couchbase($connection['servers'], (!isset($connection['username'])) ? '' : $connection['username'], (!isset($connection['password'])) ? '' : $connection['password'], $connection['bucket'], false); |
|
38 | - } |
|
39 | - |
|
40 | - $this->config = array_merge(array( |
|
41 | - 'client_table' => 'oauth_clients', |
|
42 | - 'access_token_table' => 'oauth_access_tokens', |
|
43 | - 'refresh_token_table' => 'oauth_refresh_tokens', |
|
44 | - 'code_table' => 'oauth_authorization_codes', |
|
45 | - 'user_table' => 'oauth_users', |
|
46 | - 'jwt_table' => 'oauth_jwt', |
|
47 | - ), $config); |
|
48 | - } |
|
49 | - |
|
50 | - // Helper function to access couchbase item by type: |
|
51 | - protected function getObjectByType($name,$id) |
|
52 | - { |
|
53 | - return json_decode($this->db->get($this->config[$name].'-'.$id),true); |
|
54 | - } |
|
55 | - |
|
56 | - // Helper function to set couchbase item by type: |
|
57 | - protected function setObjectByType($name,$id,$array) |
|
58 | - { |
|
59 | - $array['type'] = $name; |
|
60 | - |
|
61 | - return $this->db->set($this->config[$name].'-'.$id,json_encode($array)); |
|
62 | - } |
|
63 | - |
|
64 | - // Helper function to delete couchbase item by type, wait for persist to at least 1 node |
|
65 | - protected function deleteObjectByType($name,$id) |
|
66 | - { |
|
67 | - $this->db->delete($this->config[$name].'-'.$id,"",1); |
|
68 | - } |
|
69 | - |
|
70 | - /* ClientCredentialsInterface */ |
|
71 | - public function checkClientCredentials($client_id, $client_secret = null) |
|
72 | - { |
|
73 | - if ($result = $this->getObjectByType('client_table',$client_id)) { |
|
74 | - return $result['client_secret'] == $client_secret; |
|
75 | - } |
|
76 | - |
|
77 | - return false; |
|
78 | - } |
|
79 | - |
|
80 | - public function isPublicClient($client_id) |
|
81 | - { |
|
82 | - if (!$result = $this->getObjectByType('client_table',$client_id)) { |
|
83 | - return false; |
|
84 | - } |
|
85 | - |
|
86 | - return empty($result['client_secret']); |
|
87 | - } |
|
88 | - |
|
89 | - /* ClientInterface */ |
|
90 | - public function getClientDetails($client_id) |
|
91 | - { |
|
92 | - $result = $this->getObjectByType('client_table',$client_id); |
|
93 | - |
|
94 | - return is_null($result) ? false : $result; |
|
95 | - } |
|
96 | - |
|
97 | - public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
98 | - { |
|
99 | - if ($this->getClientDetails($client_id)) { |
|
100 | - |
|
101 | - $this->setObjectByType('client_table',$client_id, array( |
|
102 | - 'client_id' => $client_id, |
|
103 | - 'client_secret' => $client_secret, |
|
104 | - 'redirect_uri' => $redirect_uri, |
|
105 | - 'grant_types' => $grant_types, |
|
106 | - 'scope' => $scope, |
|
107 | - 'user_id' => $user_id, |
|
108 | - )); |
|
109 | - } else { |
|
110 | - $this->setObjectByType('client_table',$client_id, array( |
|
111 | - 'client_id' => $client_id, |
|
112 | - 'client_secret' => $client_secret, |
|
113 | - 'redirect_uri' => $redirect_uri, |
|
114 | - 'grant_types' => $grant_types, |
|
115 | - 'scope' => $scope, |
|
116 | - 'user_id' => $user_id, |
|
117 | - )); |
|
118 | - } |
|
119 | - |
|
120 | - return true; |
|
121 | - } |
|
122 | - |
|
123 | - public function checkRestrictedGrantType($client_id, $grant_type) |
|
124 | - { |
|
125 | - $details = $this->getClientDetails($client_id); |
|
126 | - if (isset($details['grant_types'])) { |
|
127 | - $grant_types = explode(' ', $details['grant_types']); |
|
128 | - |
|
129 | - return in_array($grant_type, $grant_types); |
|
130 | - } |
|
131 | - |
|
132 | - // if grant_types are not defined, then none are restricted |
|
133 | - return true; |
|
134 | - } |
|
135 | - |
|
136 | - /* AccessTokenInterface */ |
|
137 | - public function getAccessToken($access_token) |
|
138 | - { |
|
139 | - $token = $this->getObjectByType('access_token_table',$access_token); |
|
140 | - |
|
141 | - return is_null($token) ? false : $token; |
|
142 | - } |
|
143 | - |
|
144 | - public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
145 | - { |
|
146 | - // if it exists, update it. |
|
147 | - if ($this->getAccessToken($access_token)) { |
|
148 | - $this->setObjectByType('access_token_table',$access_token, array( |
|
149 | - 'access_token' => $access_token, |
|
150 | - 'client_id' => $client_id, |
|
151 | - 'expires' => $expires, |
|
152 | - 'user_id' => $user_id, |
|
153 | - 'scope' => $scope |
|
154 | - )); |
|
155 | - } else { |
|
156 | - $this->setObjectByType('access_token_table',$access_token, array( |
|
157 | - 'access_token' => $access_token, |
|
158 | - 'client_id' => $client_id, |
|
159 | - 'expires' => $expires, |
|
160 | - 'user_id' => $user_id, |
|
161 | - 'scope' => $scope |
|
162 | - )); |
|
163 | - } |
|
164 | - |
|
165 | - return true; |
|
166 | - } |
|
167 | - |
|
168 | - /* AuthorizationCodeInterface */ |
|
169 | - public function getAuthorizationCode($code) |
|
170 | - { |
|
171 | - $code = $this->getObjectByType('code_table',$code); |
|
172 | - |
|
173 | - return is_null($code) ? false : $code; |
|
174 | - } |
|
175 | - |
|
176 | - public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
177 | - { |
|
178 | - // if it exists, update it. |
|
179 | - if ($this->getAuthorizationCode($code)) { |
|
180 | - $this->setObjectByType('code_table',$code, array( |
|
181 | - 'authorization_code' => $code, |
|
182 | - 'client_id' => $client_id, |
|
183 | - 'user_id' => $user_id, |
|
184 | - 'redirect_uri' => $redirect_uri, |
|
185 | - 'expires' => $expires, |
|
186 | - 'scope' => $scope, |
|
187 | - 'id_token' => $id_token, |
|
188 | - )); |
|
189 | - } else { |
|
190 | - $this->setObjectByType('code_table',$code,array( |
|
191 | - 'authorization_code' => $code, |
|
192 | - 'client_id' => $client_id, |
|
193 | - 'user_id' => $user_id, |
|
194 | - 'redirect_uri' => $redirect_uri, |
|
195 | - 'expires' => $expires, |
|
196 | - 'scope' => $scope, |
|
197 | - 'id_token' => $id_token, |
|
198 | - )); |
|
199 | - } |
|
200 | - |
|
201 | - return true; |
|
202 | - } |
|
203 | - |
|
204 | - public function expireAuthorizationCode($code) |
|
205 | - { |
|
206 | - $this->deleteObjectByType('code_table',$code); |
|
207 | - |
|
208 | - return true; |
|
209 | - } |
|
210 | - |
|
211 | - /* UserCredentialsInterface */ |
|
212 | - public function checkUserCredentials($username, $password) |
|
213 | - { |
|
214 | - if ($user = $this->getUser($username)) { |
|
215 | - return $this->checkPassword($user, $password); |
|
216 | - } |
|
217 | - |
|
218 | - return false; |
|
219 | - } |
|
220 | - |
|
221 | - public function getUserDetails($username) |
|
222 | - { |
|
223 | - if ($user = $this->getUser($username)) { |
|
224 | - $user['user_id'] = $user['username']; |
|
225 | - } |
|
226 | - |
|
227 | - return $user; |
|
228 | - } |
|
229 | - |
|
230 | - /* RefreshTokenInterface */ |
|
231 | - public function getRefreshToken($refresh_token) |
|
232 | - { |
|
233 | - $token = $this->getObjectByType('refresh_token_table',$refresh_token); |
|
234 | - |
|
235 | - return is_null($token) ? false : $token; |
|
236 | - } |
|
237 | - |
|
238 | - public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
239 | - { |
|
240 | - $this->setObjectByType('refresh_token_table',$refresh_token, array( |
|
241 | - 'refresh_token' => $refresh_token, |
|
242 | - 'client_id' => $client_id, |
|
243 | - 'user_id' => $user_id, |
|
244 | - 'expires' => $expires, |
|
245 | - 'scope' => $scope |
|
246 | - )); |
|
247 | - |
|
248 | - return true; |
|
249 | - } |
|
250 | - |
|
251 | - public function unsetRefreshToken($refresh_token) |
|
252 | - { |
|
253 | - $this->deleteObjectByType('refresh_token_table',$refresh_token); |
|
254 | - |
|
255 | - return true; |
|
256 | - } |
|
257 | - |
|
258 | - // plaintext passwords are bad! Override this for your application |
|
259 | - protected function checkPassword($user, $password) |
|
260 | - { |
|
261 | - return $user['password'] == $password; |
|
262 | - } |
|
263 | - |
|
264 | - public function getUser($username) |
|
265 | - { |
|
266 | - $result = $this->getObjectByType('user_table',$username); |
|
267 | - |
|
268 | - return is_null($result) ? false : $result; |
|
269 | - } |
|
270 | - |
|
271 | - public function setUser($username, $password, $firstName = null, $lastName = null) |
|
272 | - { |
|
273 | - if ($this->getUser($username)) { |
|
274 | - $this->setObjectByType('user_table',$username, array( |
|
275 | - 'username' => $username, |
|
276 | - 'password' => $password, |
|
277 | - 'first_name' => $firstName, |
|
278 | - 'last_name' => $lastName |
|
279 | - )); |
|
280 | - |
|
281 | - } else { |
|
282 | - $this->setObjectByType('user_table',$username, array( |
|
283 | - 'username' => $username, |
|
284 | - 'password' => $password, |
|
285 | - 'first_name' => $firstName, |
|
286 | - 'last_name' => $lastName |
|
287 | - )); |
|
288 | - |
|
289 | - } |
|
290 | - |
|
291 | - return true; |
|
292 | - } |
|
293 | - |
|
294 | - public function getClientKey($client_id, $subject) |
|
295 | - { |
|
296 | - if (!$jwt = $this->getObjectByType('jwt_table',$client_id)) { |
|
297 | - return false; |
|
298 | - } |
|
299 | - |
|
300 | - if (isset($jwt['subject']) && $jwt['subject'] == $subject) { |
|
301 | - return $jwt['key']; |
|
302 | - } |
|
303 | - |
|
304 | - return false; |
|
305 | - } |
|
306 | - |
|
307 | - public function getClientScope($client_id) |
|
308 | - { |
|
309 | - if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
310 | - return false; |
|
311 | - } |
|
312 | - |
|
313 | - if (isset($clientDetails['scope'])) { |
|
314 | - return $clientDetails['scope']; |
|
315 | - } |
|
316 | - |
|
317 | - return null; |
|
318 | - } |
|
319 | - |
|
320 | - public function getJti($client_id, $subject, $audience, $expiration, $jti) |
|
321 | - { |
|
322 | - //TODO: Needs couchbase implementation. |
|
323 | - throw new \Exception('getJti() for the Couchbase driver is currently unimplemented.'); |
|
324 | - } |
|
325 | - |
|
326 | - public function setJti($client_id, $subject, $audience, $expiration, $jti) |
|
327 | - { |
|
328 | - //TODO: Needs couchbase implementation. |
|
329 | - throw new \Exception('setJti() for the Couchbase driver is currently unimplemented.'); |
|
330 | - } |
|
25 | + protected $db; |
|
26 | + protected $config; |
|
27 | + |
|
28 | + public function __construct($connection, $config = array()) |
|
29 | + { |
|
30 | + if ($connection instanceof \Couchbase) { |
|
31 | + $this->db = $connection; |
|
32 | + } else { |
|
33 | + if (!is_array($connection) || !is_array($connection['servers'])) { |
|
34 | + throw new \InvalidArgumentException('First argument to OAuth2\Storage\CouchbaseDB must be an instance of Couchbase or a configuration array containing a server array'); |
|
35 | + } |
|
36 | + |
|
37 | + $this->db = new \Couchbase($connection['servers'], (!isset($connection['username'])) ? '' : $connection['username'], (!isset($connection['password'])) ? '' : $connection['password'], $connection['bucket'], false); |
|
38 | + } |
|
39 | + |
|
40 | + $this->config = array_merge(array( |
|
41 | + 'client_table' => 'oauth_clients', |
|
42 | + 'access_token_table' => 'oauth_access_tokens', |
|
43 | + 'refresh_token_table' => 'oauth_refresh_tokens', |
|
44 | + 'code_table' => 'oauth_authorization_codes', |
|
45 | + 'user_table' => 'oauth_users', |
|
46 | + 'jwt_table' => 'oauth_jwt', |
|
47 | + ), $config); |
|
48 | + } |
|
49 | + |
|
50 | + // Helper function to access couchbase item by type: |
|
51 | + protected function getObjectByType($name,$id) |
|
52 | + { |
|
53 | + return json_decode($this->db->get($this->config[$name].'-'.$id),true); |
|
54 | + } |
|
55 | + |
|
56 | + // Helper function to set couchbase item by type: |
|
57 | + protected function setObjectByType($name,$id,$array) |
|
58 | + { |
|
59 | + $array['type'] = $name; |
|
60 | + |
|
61 | + return $this->db->set($this->config[$name].'-'.$id,json_encode($array)); |
|
62 | + } |
|
63 | + |
|
64 | + // Helper function to delete couchbase item by type, wait for persist to at least 1 node |
|
65 | + protected function deleteObjectByType($name,$id) |
|
66 | + { |
|
67 | + $this->db->delete($this->config[$name].'-'.$id,"",1); |
|
68 | + } |
|
69 | + |
|
70 | + /* ClientCredentialsInterface */ |
|
71 | + public function checkClientCredentials($client_id, $client_secret = null) |
|
72 | + { |
|
73 | + if ($result = $this->getObjectByType('client_table',$client_id)) { |
|
74 | + return $result['client_secret'] == $client_secret; |
|
75 | + } |
|
76 | + |
|
77 | + return false; |
|
78 | + } |
|
79 | + |
|
80 | + public function isPublicClient($client_id) |
|
81 | + { |
|
82 | + if (!$result = $this->getObjectByType('client_table',$client_id)) { |
|
83 | + return false; |
|
84 | + } |
|
85 | + |
|
86 | + return empty($result['client_secret']); |
|
87 | + } |
|
88 | + |
|
89 | + /* ClientInterface */ |
|
90 | + public function getClientDetails($client_id) |
|
91 | + { |
|
92 | + $result = $this->getObjectByType('client_table',$client_id); |
|
93 | + |
|
94 | + return is_null($result) ? false : $result; |
|
95 | + } |
|
96 | + |
|
97 | + public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
98 | + { |
|
99 | + if ($this->getClientDetails($client_id)) { |
|
100 | + |
|
101 | + $this->setObjectByType('client_table',$client_id, array( |
|
102 | + 'client_id' => $client_id, |
|
103 | + 'client_secret' => $client_secret, |
|
104 | + 'redirect_uri' => $redirect_uri, |
|
105 | + 'grant_types' => $grant_types, |
|
106 | + 'scope' => $scope, |
|
107 | + 'user_id' => $user_id, |
|
108 | + )); |
|
109 | + } else { |
|
110 | + $this->setObjectByType('client_table',$client_id, array( |
|
111 | + 'client_id' => $client_id, |
|
112 | + 'client_secret' => $client_secret, |
|
113 | + 'redirect_uri' => $redirect_uri, |
|
114 | + 'grant_types' => $grant_types, |
|
115 | + 'scope' => $scope, |
|
116 | + 'user_id' => $user_id, |
|
117 | + )); |
|
118 | + } |
|
119 | + |
|
120 | + return true; |
|
121 | + } |
|
122 | + |
|
123 | + public function checkRestrictedGrantType($client_id, $grant_type) |
|
124 | + { |
|
125 | + $details = $this->getClientDetails($client_id); |
|
126 | + if (isset($details['grant_types'])) { |
|
127 | + $grant_types = explode(' ', $details['grant_types']); |
|
128 | + |
|
129 | + return in_array($grant_type, $grant_types); |
|
130 | + } |
|
131 | + |
|
132 | + // if grant_types are not defined, then none are restricted |
|
133 | + return true; |
|
134 | + } |
|
135 | + |
|
136 | + /* AccessTokenInterface */ |
|
137 | + public function getAccessToken($access_token) |
|
138 | + { |
|
139 | + $token = $this->getObjectByType('access_token_table',$access_token); |
|
140 | + |
|
141 | + return is_null($token) ? false : $token; |
|
142 | + } |
|
143 | + |
|
144 | + public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
145 | + { |
|
146 | + // if it exists, update it. |
|
147 | + if ($this->getAccessToken($access_token)) { |
|
148 | + $this->setObjectByType('access_token_table',$access_token, array( |
|
149 | + 'access_token' => $access_token, |
|
150 | + 'client_id' => $client_id, |
|
151 | + 'expires' => $expires, |
|
152 | + 'user_id' => $user_id, |
|
153 | + 'scope' => $scope |
|
154 | + )); |
|
155 | + } else { |
|
156 | + $this->setObjectByType('access_token_table',$access_token, array( |
|
157 | + 'access_token' => $access_token, |
|
158 | + 'client_id' => $client_id, |
|
159 | + 'expires' => $expires, |
|
160 | + 'user_id' => $user_id, |
|
161 | + 'scope' => $scope |
|
162 | + )); |
|
163 | + } |
|
164 | + |
|
165 | + return true; |
|
166 | + } |
|
167 | + |
|
168 | + /* AuthorizationCodeInterface */ |
|
169 | + public function getAuthorizationCode($code) |
|
170 | + { |
|
171 | + $code = $this->getObjectByType('code_table',$code); |
|
172 | + |
|
173 | + return is_null($code) ? false : $code; |
|
174 | + } |
|
175 | + |
|
176 | + public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
177 | + { |
|
178 | + // if it exists, update it. |
|
179 | + if ($this->getAuthorizationCode($code)) { |
|
180 | + $this->setObjectByType('code_table',$code, array( |
|
181 | + 'authorization_code' => $code, |
|
182 | + 'client_id' => $client_id, |
|
183 | + 'user_id' => $user_id, |
|
184 | + 'redirect_uri' => $redirect_uri, |
|
185 | + 'expires' => $expires, |
|
186 | + 'scope' => $scope, |
|
187 | + 'id_token' => $id_token, |
|
188 | + )); |
|
189 | + } else { |
|
190 | + $this->setObjectByType('code_table',$code,array( |
|
191 | + 'authorization_code' => $code, |
|
192 | + 'client_id' => $client_id, |
|
193 | + 'user_id' => $user_id, |
|
194 | + 'redirect_uri' => $redirect_uri, |
|
195 | + 'expires' => $expires, |
|
196 | + 'scope' => $scope, |
|
197 | + 'id_token' => $id_token, |
|
198 | + )); |
|
199 | + } |
|
200 | + |
|
201 | + return true; |
|
202 | + } |
|
203 | + |
|
204 | + public function expireAuthorizationCode($code) |
|
205 | + { |
|
206 | + $this->deleteObjectByType('code_table',$code); |
|
207 | + |
|
208 | + return true; |
|
209 | + } |
|
210 | + |
|
211 | + /* UserCredentialsInterface */ |
|
212 | + public function checkUserCredentials($username, $password) |
|
213 | + { |
|
214 | + if ($user = $this->getUser($username)) { |
|
215 | + return $this->checkPassword($user, $password); |
|
216 | + } |
|
217 | + |
|
218 | + return false; |
|
219 | + } |
|
220 | + |
|
221 | + public function getUserDetails($username) |
|
222 | + { |
|
223 | + if ($user = $this->getUser($username)) { |
|
224 | + $user['user_id'] = $user['username']; |
|
225 | + } |
|
226 | + |
|
227 | + return $user; |
|
228 | + } |
|
229 | + |
|
230 | + /* RefreshTokenInterface */ |
|
231 | + public function getRefreshToken($refresh_token) |
|
232 | + { |
|
233 | + $token = $this->getObjectByType('refresh_token_table',$refresh_token); |
|
234 | + |
|
235 | + return is_null($token) ? false : $token; |
|
236 | + } |
|
237 | + |
|
238 | + public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
239 | + { |
|
240 | + $this->setObjectByType('refresh_token_table',$refresh_token, array( |
|
241 | + 'refresh_token' => $refresh_token, |
|
242 | + 'client_id' => $client_id, |
|
243 | + 'user_id' => $user_id, |
|
244 | + 'expires' => $expires, |
|
245 | + 'scope' => $scope |
|
246 | + )); |
|
247 | + |
|
248 | + return true; |
|
249 | + } |
|
250 | + |
|
251 | + public function unsetRefreshToken($refresh_token) |
|
252 | + { |
|
253 | + $this->deleteObjectByType('refresh_token_table',$refresh_token); |
|
254 | + |
|
255 | + return true; |
|
256 | + } |
|
257 | + |
|
258 | + // plaintext passwords are bad! Override this for your application |
|
259 | + protected function checkPassword($user, $password) |
|
260 | + { |
|
261 | + return $user['password'] == $password; |
|
262 | + } |
|
263 | + |
|
264 | + public function getUser($username) |
|
265 | + { |
|
266 | + $result = $this->getObjectByType('user_table',$username); |
|
267 | + |
|
268 | + return is_null($result) ? false : $result; |
|
269 | + } |
|
270 | + |
|
271 | + public function setUser($username, $password, $firstName = null, $lastName = null) |
|
272 | + { |
|
273 | + if ($this->getUser($username)) { |
|
274 | + $this->setObjectByType('user_table',$username, array( |
|
275 | + 'username' => $username, |
|
276 | + 'password' => $password, |
|
277 | + 'first_name' => $firstName, |
|
278 | + 'last_name' => $lastName |
|
279 | + )); |
|
280 | + |
|
281 | + } else { |
|
282 | + $this->setObjectByType('user_table',$username, array( |
|
283 | + 'username' => $username, |
|
284 | + 'password' => $password, |
|
285 | + 'first_name' => $firstName, |
|
286 | + 'last_name' => $lastName |
|
287 | + )); |
|
288 | + |
|
289 | + } |
|
290 | + |
|
291 | + return true; |
|
292 | + } |
|
293 | + |
|
294 | + public function getClientKey($client_id, $subject) |
|
295 | + { |
|
296 | + if (!$jwt = $this->getObjectByType('jwt_table',$client_id)) { |
|
297 | + return false; |
|
298 | + } |
|
299 | + |
|
300 | + if (isset($jwt['subject']) && $jwt['subject'] == $subject) { |
|
301 | + return $jwt['key']; |
|
302 | + } |
|
303 | + |
|
304 | + return false; |
|
305 | + } |
|
306 | + |
|
307 | + public function getClientScope($client_id) |
|
308 | + { |
|
309 | + if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
310 | + return false; |
|
311 | + } |
|
312 | + |
|
313 | + if (isset($clientDetails['scope'])) { |
|
314 | + return $clientDetails['scope']; |
|
315 | + } |
|
316 | + |
|
317 | + return null; |
|
318 | + } |
|
319 | + |
|
320 | + public function getJti($client_id, $subject, $audience, $expiration, $jti) |
|
321 | + { |
|
322 | + //TODO: Needs couchbase implementation. |
|
323 | + throw new \Exception('getJti() for the Couchbase driver is currently unimplemented.'); |
|
324 | + } |
|
325 | + |
|
326 | + public function setJti($client_id, $subject, $audience, $expiration, $jti) |
|
327 | + { |
|
328 | + //TODO: Needs couchbase implementation. |
|
329 | + throw new \Exception('setJti() for the Couchbase driver is currently unimplemented.'); |
|
330 | + } |
|
331 | 331 | } |
@@ -48,29 +48,29 @@ discard block |
||
48 | 48 | } |
49 | 49 | |
50 | 50 | // Helper function to access couchbase item by type: |
51 | - protected function getObjectByType($name,$id) |
|
51 | + protected function getObjectByType($name, $id) |
|
52 | 52 | { |
53 | - return json_decode($this->db->get($this->config[$name].'-'.$id),true); |
|
53 | + return json_decode($this->db->get($this->config[$name] . '-' . $id), true); |
|
54 | 54 | } |
55 | 55 | |
56 | 56 | // Helper function to set couchbase item by type: |
57 | - protected function setObjectByType($name,$id,$array) |
|
57 | + protected function setObjectByType($name, $id, $array) |
|
58 | 58 | { |
59 | 59 | $array['type'] = $name; |
60 | 60 | |
61 | - return $this->db->set($this->config[$name].'-'.$id,json_encode($array)); |
|
61 | + return $this->db->set($this->config[$name] . '-' . $id, json_encode($array)); |
|
62 | 62 | } |
63 | 63 | |
64 | 64 | // Helper function to delete couchbase item by type, wait for persist to at least 1 node |
65 | - protected function deleteObjectByType($name,$id) |
|
65 | + protected function deleteObjectByType($name, $id) |
|
66 | 66 | { |
67 | - $this->db->delete($this->config[$name].'-'.$id,"",1); |
|
67 | + $this->db->delete($this->config[$name] . '-' . $id, "", 1); |
|
68 | 68 | } |
69 | 69 | |
70 | 70 | /* ClientCredentialsInterface */ |
71 | 71 | public function checkClientCredentials($client_id, $client_secret = null) |
72 | 72 | { |
73 | - if ($result = $this->getObjectByType('client_table',$client_id)) { |
|
73 | + if ($result = $this->getObjectByType('client_table', $client_id)) { |
|
74 | 74 | return $result['client_secret'] == $client_secret; |
75 | 75 | } |
76 | 76 | |
@@ -79,7 +79,7 @@ discard block |
||
79 | 79 | |
80 | 80 | public function isPublicClient($client_id) |
81 | 81 | { |
82 | - if (!$result = $this->getObjectByType('client_table',$client_id)) { |
|
82 | + if (!$result = $this->getObjectByType('client_table', $client_id)) { |
|
83 | 83 | return false; |
84 | 84 | } |
85 | 85 | |
@@ -89,7 +89,7 @@ discard block |
||
89 | 89 | /* ClientInterface */ |
90 | 90 | public function getClientDetails($client_id) |
91 | 91 | { |
92 | - $result = $this->getObjectByType('client_table',$client_id); |
|
92 | + $result = $this->getObjectByType('client_table', $client_id); |
|
93 | 93 | |
94 | 94 | return is_null($result) ? false : $result; |
95 | 95 | } |
@@ -98,7 +98,7 @@ discard block |
||
98 | 98 | { |
99 | 99 | if ($this->getClientDetails($client_id)) { |
100 | 100 | |
101 | - $this->setObjectByType('client_table',$client_id, array( |
|
101 | + $this->setObjectByType('client_table', $client_id, array( |
|
102 | 102 | 'client_id' => $client_id, |
103 | 103 | 'client_secret' => $client_secret, |
104 | 104 | 'redirect_uri' => $redirect_uri, |
@@ -107,7 +107,7 @@ discard block |
||
107 | 107 | 'user_id' => $user_id, |
108 | 108 | )); |
109 | 109 | } else { |
110 | - $this->setObjectByType('client_table',$client_id, array( |
|
110 | + $this->setObjectByType('client_table', $client_id, array( |
|
111 | 111 | 'client_id' => $client_id, |
112 | 112 | 'client_secret' => $client_secret, |
113 | 113 | 'redirect_uri' => $redirect_uri, |
@@ -136,7 +136,7 @@ discard block |
||
136 | 136 | /* AccessTokenInterface */ |
137 | 137 | public function getAccessToken($access_token) |
138 | 138 | { |
139 | - $token = $this->getObjectByType('access_token_table',$access_token); |
|
139 | + $token = $this->getObjectByType('access_token_table', $access_token); |
|
140 | 140 | |
141 | 141 | return is_null($token) ? false : $token; |
142 | 142 | } |
@@ -145,7 +145,7 @@ discard block |
||
145 | 145 | { |
146 | 146 | // if it exists, update it. |
147 | 147 | if ($this->getAccessToken($access_token)) { |
148 | - $this->setObjectByType('access_token_table',$access_token, array( |
|
148 | + $this->setObjectByType('access_token_table', $access_token, array( |
|
149 | 149 | 'access_token' => $access_token, |
150 | 150 | 'client_id' => $client_id, |
151 | 151 | 'expires' => $expires, |
@@ -153,7 +153,7 @@ discard block |
||
153 | 153 | 'scope' => $scope |
154 | 154 | )); |
155 | 155 | } else { |
156 | - $this->setObjectByType('access_token_table',$access_token, array( |
|
156 | + $this->setObjectByType('access_token_table', $access_token, array( |
|
157 | 157 | 'access_token' => $access_token, |
158 | 158 | 'client_id' => $client_id, |
159 | 159 | 'expires' => $expires, |
@@ -168,7 +168,7 @@ discard block |
||
168 | 168 | /* AuthorizationCodeInterface */ |
169 | 169 | public function getAuthorizationCode($code) |
170 | 170 | { |
171 | - $code = $this->getObjectByType('code_table',$code); |
|
171 | + $code = $this->getObjectByType('code_table', $code); |
|
172 | 172 | |
173 | 173 | return is_null($code) ? false : $code; |
174 | 174 | } |
@@ -177,7 +177,7 @@ discard block |
||
177 | 177 | { |
178 | 178 | // if it exists, update it. |
179 | 179 | if ($this->getAuthorizationCode($code)) { |
180 | - $this->setObjectByType('code_table',$code, array( |
|
180 | + $this->setObjectByType('code_table', $code, array( |
|
181 | 181 | 'authorization_code' => $code, |
182 | 182 | 'client_id' => $client_id, |
183 | 183 | 'user_id' => $user_id, |
@@ -187,7 +187,7 @@ discard block |
||
187 | 187 | 'id_token' => $id_token, |
188 | 188 | )); |
189 | 189 | } else { |
190 | - $this->setObjectByType('code_table',$code,array( |
|
190 | + $this->setObjectByType('code_table', $code, array( |
|
191 | 191 | 'authorization_code' => $code, |
192 | 192 | 'client_id' => $client_id, |
193 | 193 | 'user_id' => $user_id, |
@@ -203,7 +203,7 @@ discard block |
||
203 | 203 | |
204 | 204 | public function expireAuthorizationCode($code) |
205 | 205 | { |
206 | - $this->deleteObjectByType('code_table',$code); |
|
206 | + $this->deleteObjectByType('code_table', $code); |
|
207 | 207 | |
208 | 208 | return true; |
209 | 209 | } |
@@ -230,14 +230,14 @@ discard block |
||
230 | 230 | /* RefreshTokenInterface */ |
231 | 231 | public function getRefreshToken($refresh_token) |
232 | 232 | { |
233 | - $token = $this->getObjectByType('refresh_token_table',$refresh_token); |
|
233 | + $token = $this->getObjectByType('refresh_token_table', $refresh_token); |
|
234 | 234 | |
235 | 235 | return is_null($token) ? false : $token; |
236 | 236 | } |
237 | 237 | |
238 | 238 | public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
239 | 239 | { |
240 | - $this->setObjectByType('refresh_token_table',$refresh_token, array( |
|
240 | + $this->setObjectByType('refresh_token_table', $refresh_token, array( |
|
241 | 241 | 'refresh_token' => $refresh_token, |
242 | 242 | 'client_id' => $client_id, |
243 | 243 | 'user_id' => $user_id, |
@@ -250,7 +250,7 @@ discard block |
||
250 | 250 | |
251 | 251 | public function unsetRefreshToken($refresh_token) |
252 | 252 | { |
253 | - $this->deleteObjectByType('refresh_token_table',$refresh_token); |
|
253 | + $this->deleteObjectByType('refresh_token_table', $refresh_token); |
|
254 | 254 | |
255 | 255 | return true; |
256 | 256 | } |
@@ -263,7 +263,7 @@ discard block |
||
263 | 263 | |
264 | 264 | public function getUser($username) |
265 | 265 | { |
266 | - $result = $this->getObjectByType('user_table',$username); |
|
266 | + $result = $this->getObjectByType('user_table', $username); |
|
267 | 267 | |
268 | 268 | return is_null($result) ? false : $result; |
269 | 269 | } |
@@ -271,7 +271,7 @@ discard block |
||
271 | 271 | public function setUser($username, $password, $firstName = null, $lastName = null) |
272 | 272 | { |
273 | 273 | if ($this->getUser($username)) { |
274 | - $this->setObjectByType('user_table',$username, array( |
|
274 | + $this->setObjectByType('user_table', $username, array( |
|
275 | 275 | 'username' => $username, |
276 | 276 | 'password' => $password, |
277 | 277 | 'first_name' => $firstName, |
@@ -279,7 +279,7 @@ discard block |
||
279 | 279 | )); |
280 | 280 | |
281 | 281 | } else { |
282 | - $this->setObjectByType('user_table',$username, array( |
|
282 | + $this->setObjectByType('user_table', $username, array( |
|
283 | 283 | 'username' => $username, |
284 | 284 | 'password' => $password, |
285 | 285 | 'first_name' => $firstName, |
@@ -293,7 +293,7 @@ discard block |
||
293 | 293 | |
294 | 294 | public function getClientKey($client_id, $subject) |
295 | 295 | { |
296 | - if (!$jwt = $this->getObjectByType('jwt_table',$client_id)) { |
|
296 | + if (!$jwt = $this->getObjectByType('jwt_table', $client_id)) { |
|
297 | 297 | return false; |
298 | 298 | } |
299 | 299 |
@@ -14,356 +14,356 @@ |
||
14 | 14 | * @author Brent Shaffer <bshafs at gmail dot com> |
15 | 15 | */ |
16 | 16 | class Memory implements AuthorizationCodeInterface, |
17 | - UserCredentialsInterface, |
|
18 | - UserClaimsInterface, |
|
19 | - AccessTokenInterface, |
|
20 | - ClientCredentialsInterface, |
|
21 | - RefreshTokenInterface, |
|
22 | - JwtBearerInterface, |
|
23 | - ScopeInterface, |
|
24 | - PublicKeyInterface, |
|
25 | - OpenIDAuthorizationCodeInterface |
|
17 | + UserCredentialsInterface, |
|
18 | + UserClaimsInterface, |
|
19 | + AccessTokenInterface, |
|
20 | + ClientCredentialsInterface, |
|
21 | + RefreshTokenInterface, |
|
22 | + JwtBearerInterface, |
|
23 | + ScopeInterface, |
|
24 | + PublicKeyInterface, |
|
25 | + OpenIDAuthorizationCodeInterface |
|
26 | 26 | { |
27 | - public $authorizationCodes; |
|
28 | - public $userCredentials; |
|
29 | - public $clientCredentials; |
|
30 | - public $refreshTokens; |
|
31 | - public $accessTokens; |
|
32 | - public $jwt; |
|
33 | - public $jti; |
|
34 | - public $supportedScopes; |
|
35 | - public $defaultScope; |
|
36 | - public $keys; |
|
37 | - |
|
38 | - public function __construct($params = array()) |
|
39 | - { |
|
40 | - $params = array_merge(array( |
|
41 | - 'authorization_codes' => array(), |
|
42 | - 'user_credentials' => array(), |
|
43 | - 'client_credentials' => array(), |
|
44 | - 'refresh_tokens' => array(), |
|
45 | - 'access_tokens' => array(), |
|
46 | - 'jwt' => array(), |
|
47 | - 'jti' => array(), |
|
48 | - 'default_scope' => null, |
|
49 | - 'supported_scopes' => array(), |
|
50 | - 'keys' => array(), |
|
51 | - ), $params); |
|
52 | - |
|
53 | - $this->authorizationCodes = $params['authorization_codes']; |
|
54 | - $this->userCredentials = $params['user_credentials']; |
|
55 | - $this->clientCredentials = $params['client_credentials']; |
|
56 | - $this->refreshTokens = $params['refresh_tokens']; |
|
57 | - $this->accessTokens = $params['access_tokens']; |
|
58 | - $this->jwt = $params['jwt']; |
|
59 | - $this->jti = $params['jti']; |
|
60 | - $this->supportedScopes = $params['supported_scopes']; |
|
61 | - $this->defaultScope = $params['default_scope']; |
|
62 | - $this->keys = $params['keys']; |
|
63 | - } |
|
64 | - |
|
65 | - /* AuthorizationCodeInterface */ |
|
66 | - public function getAuthorizationCode($code) |
|
67 | - { |
|
68 | - if (!isset($this->authorizationCodes[$code])) { |
|
69 | - return false; |
|
70 | - } |
|
71 | - |
|
72 | - return array_merge(array( |
|
73 | - 'authorization_code' => $code, |
|
74 | - ), $this->authorizationCodes[$code]); |
|
75 | - } |
|
76 | - |
|
77 | - public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
78 | - { |
|
79 | - $this->authorizationCodes[$code] = compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope', 'id_token'); |
|
80 | - |
|
81 | - return true; |
|
82 | - } |
|
83 | - |
|
84 | - public function setAuthorizationCodes($authorization_codes) |
|
85 | - { |
|
86 | - $this->authorizationCodes = $authorization_codes; |
|
87 | - } |
|
88 | - |
|
89 | - public function expireAuthorizationCode($code) |
|
90 | - { |
|
91 | - unset($this->authorizationCodes[$code]); |
|
92 | - } |
|
93 | - |
|
94 | - /* UserCredentialsInterface */ |
|
95 | - public function checkUserCredentials($username, $password) |
|
96 | - { |
|
97 | - $userDetails = $this->getUserDetails($username); |
|
98 | - |
|
99 | - return $userDetails && $userDetails['password'] && $userDetails['password'] === $password; |
|
100 | - } |
|
101 | - |
|
102 | - public function setUser($username, $password, $firstName = null, $lastName = null) |
|
103 | - { |
|
104 | - $this->userCredentials[$username] = array( |
|
105 | - 'password' => $password, |
|
106 | - 'first_name' => $firstName, |
|
107 | - 'last_name' => $lastName, |
|
108 | - ); |
|
109 | - |
|
110 | - return true; |
|
111 | - } |
|
112 | - |
|
113 | - public function getUserDetails($username) |
|
114 | - { |
|
115 | - if (!isset($this->userCredentials[$username])) { |
|
116 | - return false; |
|
117 | - } |
|
118 | - |
|
119 | - return array_merge(array( |
|
120 | - 'user_id' => $username, |
|
121 | - 'password' => null, |
|
122 | - 'first_name' => null, |
|
123 | - 'last_name' => null, |
|
124 | - ), $this->userCredentials[$username]); |
|
125 | - } |
|
126 | - |
|
127 | - /* UserClaimsInterface */ |
|
128 | - public function getUserClaims($user_id, $claims) |
|
129 | - { |
|
130 | - if (!$userDetails = $this->getUserDetails($user_id)) { |
|
131 | - return false; |
|
132 | - } |
|
133 | - |
|
134 | - $claims = explode(' ', trim($claims)); |
|
135 | - $userClaims = array(); |
|
136 | - |
|
137 | - // for each requested claim, if the user has the claim, set it in the response |
|
138 | - $validClaims = explode(' ', self::VALID_CLAIMS); |
|
139 | - foreach ($validClaims as $validClaim) { |
|
140 | - if (in_array($validClaim, $claims)) { |
|
141 | - if ($validClaim == 'address') { |
|
142 | - // address is an object with subfields |
|
143 | - $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails); |
|
144 | - } else { |
|
145 | - $userClaims = array_merge($this->getUserClaim($validClaim, $userDetails)); |
|
146 | - } |
|
147 | - } |
|
148 | - } |
|
149 | - |
|
150 | - return $userClaims; |
|
151 | - } |
|
152 | - |
|
153 | - protected function getUserClaim($claim, $userDetails) |
|
154 | - { |
|
155 | - $userClaims = array(); |
|
156 | - $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim))); |
|
157 | - $claimValues = explode(' ', $claimValuesString); |
|
158 | - |
|
159 | - foreach ($claimValues as $value) { |
|
160 | - $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null; |
|
161 | - } |
|
162 | - |
|
163 | - return $userClaims; |
|
164 | - } |
|
165 | - |
|
166 | - /* ClientCredentialsInterface */ |
|
167 | - public function checkClientCredentials($client_id, $client_secret = null) |
|
168 | - { |
|
169 | - return isset($this->clientCredentials[$client_id]['client_secret']) && $this->clientCredentials[$client_id]['client_secret'] === $client_secret; |
|
170 | - } |
|
171 | - |
|
172 | - public function isPublicClient($client_id) |
|
173 | - { |
|
174 | - if (!isset($this->clientCredentials[$client_id])) { |
|
175 | - return false; |
|
176 | - } |
|
177 | - |
|
178 | - return empty($this->clientCredentials[$client_id]['client_secret']); |
|
179 | - } |
|
180 | - |
|
181 | - /* ClientInterface */ |
|
182 | - public function getClientDetails($client_id) |
|
183 | - { |
|
184 | - if (!isset($this->clientCredentials[$client_id])) { |
|
185 | - return false; |
|
186 | - } |
|
187 | - |
|
188 | - $clientDetails = array_merge(array( |
|
189 | - 'client_id' => $client_id, |
|
190 | - 'client_secret' => null, |
|
191 | - 'redirect_uri' => null, |
|
192 | - 'scope' => null, |
|
193 | - ), $this->clientCredentials[$client_id]); |
|
194 | - |
|
195 | - return $clientDetails; |
|
196 | - } |
|
197 | - |
|
198 | - public function checkRestrictedGrantType($client_id, $grant_type) |
|
199 | - { |
|
200 | - if (isset($this->clientCredentials[$client_id]['grant_types'])) { |
|
201 | - $grant_types = explode(' ', $this->clientCredentials[$client_id]['grant_types']); |
|
202 | - |
|
203 | - return in_array($grant_type, $grant_types); |
|
204 | - } |
|
205 | - |
|
206 | - // if grant_types are not defined, then none are restricted |
|
207 | - return true; |
|
208 | - } |
|
209 | - |
|
210 | - public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
211 | - { |
|
212 | - $this->clientCredentials[$client_id] = array( |
|
213 | - 'client_id' => $client_id, |
|
214 | - 'client_secret' => $client_secret, |
|
215 | - 'redirect_uri' => $redirect_uri, |
|
216 | - 'grant_types' => $grant_types, |
|
217 | - 'scope' => $scope, |
|
218 | - 'user_id' => $user_id, |
|
219 | - ); |
|
220 | - |
|
221 | - return true; |
|
222 | - } |
|
223 | - |
|
224 | - /* RefreshTokenInterface */ |
|
225 | - public function getRefreshToken($refresh_token) |
|
226 | - { |
|
227 | - return isset($this->refreshTokens[$refresh_token]) ? $this->refreshTokens[$refresh_token] : false; |
|
228 | - } |
|
229 | - |
|
230 | - public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
231 | - { |
|
232 | - $this->refreshTokens[$refresh_token] = compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope'); |
|
233 | - |
|
234 | - return true; |
|
235 | - } |
|
236 | - |
|
237 | - public function unsetRefreshToken($refresh_token) |
|
238 | - { |
|
239 | - unset($this->refreshTokens[$refresh_token]); |
|
240 | - } |
|
241 | - |
|
242 | - public function setRefreshTokens($refresh_tokens) |
|
243 | - { |
|
244 | - $this->refreshTokens = $refresh_tokens; |
|
245 | - } |
|
246 | - |
|
247 | - /* AccessTokenInterface */ |
|
248 | - public function getAccessToken($access_token) |
|
249 | - { |
|
250 | - return isset($this->accessTokens[$access_token]) ? $this->accessTokens[$access_token] : false; |
|
251 | - } |
|
252 | - |
|
253 | - public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null, $id_token = null) |
|
254 | - { |
|
255 | - $this->accessTokens[$access_token] = compact('access_token', 'client_id', 'user_id', 'expires', 'scope', 'id_token'); |
|
256 | - |
|
257 | - return true; |
|
258 | - } |
|
259 | - |
|
260 | - public function unsetAccessToken($access_token) |
|
261 | - { |
|
262 | - unset($this->accessTokens[$access_token]); |
|
263 | - } |
|
264 | - |
|
265 | - public function scopeExists($scope) |
|
266 | - { |
|
267 | - $scope = explode(' ', trim($scope)); |
|
268 | - |
|
269 | - return (count(array_diff($scope, $this->supportedScopes)) == 0); |
|
270 | - } |
|
271 | - |
|
272 | - public function getDefaultScope($client_id = null) |
|
273 | - { |
|
274 | - return $this->defaultScope; |
|
275 | - } |
|
276 | - |
|
277 | - /*JWTBearerInterface */ |
|
278 | - public function getClientKey($client_id, $subject) |
|
279 | - { |
|
280 | - if (isset($this->jwt[$client_id])) { |
|
281 | - $jwt = $this->jwt[$client_id]; |
|
282 | - if ($jwt) { |
|
283 | - if ($jwt["subject"] == $subject) { |
|
284 | - return $jwt["key"]; |
|
285 | - } |
|
286 | - } |
|
287 | - } |
|
288 | - |
|
289 | - return false; |
|
290 | - } |
|
291 | - |
|
292 | - public function getClientScope($client_id) |
|
293 | - { |
|
294 | - if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
295 | - return false; |
|
296 | - } |
|
297 | - |
|
298 | - if (isset($clientDetails['scope'])) { |
|
299 | - return $clientDetails['scope']; |
|
300 | - } |
|
301 | - |
|
302 | - return null; |
|
303 | - } |
|
304 | - |
|
305 | - public function getJti($client_id, $subject, $audience, $expires, $jti) |
|
306 | - { |
|
307 | - foreach ($this->jti as $storedJti) { |
|
308 | - if ($storedJti['issuer'] == $client_id && $storedJti['subject'] == $subject && $storedJti['audience'] == $audience && $storedJti['expires'] == $expires && $storedJti['jti'] == $jti) { |
|
309 | - return array( |
|
310 | - 'issuer' => $storedJti['issuer'], |
|
311 | - 'subject' => $storedJti['subject'], |
|
312 | - 'audience' => $storedJti['audience'], |
|
313 | - 'expires' => $storedJti['expires'], |
|
314 | - 'jti' => $storedJti['jti'] |
|
315 | - ); |
|
316 | - } |
|
317 | - } |
|
318 | - |
|
319 | - return null; |
|
320 | - } |
|
321 | - |
|
322 | - public function setJti($client_id, $subject, $audience, $expires, $jti) |
|
323 | - { |
|
324 | - $this->jti[] = array('issuer' => $client_id, 'subject' => $subject, 'audience' => $audience, 'expires' => $expires, 'jti' => $jti); |
|
325 | - } |
|
326 | - |
|
327 | - /*PublicKeyInterface */ |
|
328 | - public function getPublicKey($client_id = null) |
|
329 | - { |
|
330 | - if (isset($this->keys[$client_id])) { |
|
331 | - return $this->keys[$client_id]['public_key']; |
|
332 | - } |
|
333 | - |
|
334 | - // use a global encryption pair |
|
335 | - if (isset($this->keys['public_key'])) { |
|
336 | - return $this->keys['public_key']; |
|
337 | - } |
|
338 | - |
|
339 | - return false; |
|
340 | - } |
|
341 | - |
|
342 | - public function getPrivateKey($client_id = null) |
|
343 | - { |
|
344 | - if (isset($this->keys[$client_id])) { |
|
345 | - return $this->keys[$client_id]['private_key']; |
|
346 | - } |
|
347 | - |
|
348 | - // use a global encryption pair |
|
349 | - if (isset($this->keys['private_key'])) { |
|
350 | - return $this->keys['private_key']; |
|
351 | - } |
|
352 | - |
|
353 | - return false; |
|
354 | - } |
|
355 | - |
|
356 | - public function getEncryptionAlgorithm($client_id = null) |
|
357 | - { |
|
358 | - if (isset($this->keys[$client_id]['encryption_algorithm'])) { |
|
359 | - return $this->keys[$client_id]['encryption_algorithm']; |
|
360 | - } |
|
361 | - |
|
362 | - // use a global encryption algorithm |
|
363 | - if (isset($this->keys['encryption_algorithm'])) { |
|
364 | - return $this->keys['encryption_algorithm']; |
|
365 | - } |
|
366 | - |
|
367 | - return 'RS256'; |
|
368 | - } |
|
27 | + public $authorizationCodes; |
|
28 | + public $userCredentials; |
|
29 | + public $clientCredentials; |
|
30 | + public $refreshTokens; |
|
31 | + public $accessTokens; |
|
32 | + public $jwt; |
|
33 | + public $jti; |
|
34 | + public $supportedScopes; |
|
35 | + public $defaultScope; |
|
36 | + public $keys; |
|
37 | + |
|
38 | + public function __construct($params = array()) |
|
39 | + { |
|
40 | + $params = array_merge(array( |
|
41 | + 'authorization_codes' => array(), |
|
42 | + 'user_credentials' => array(), |
|
43 | + 'client_credentials' => array(), |
|
44 | + 'refresh_tokens' => array(), |
|
45 | + 'access_tokens' => array(), |
|
46 | + 'jwt' => array(), |
|
47 | + 'jti' => array(), |
|
48 | + 'default_scope' => null, |
|
49 | + 'supported_scopes' => array(), |
|
50 | + 'keys' => array(), |
|
51 | + ), $params); |
|
52 | + |
|
53 | + $this->authorizationCodes = $params['authorization_codes']; |
|
54 | + $this->userCredentials = $params['user_credentials']; |
|
55 | + $this->clientCredentials = $params['client_credentials']; |
|
56 | + $this->refreshTokens = $params['refresh_tokens']; |
|
57 | + $this->accessTokens = $params['access_tokens']; |
|
58 | + $this->jwt = $params['jwt']; |
|
59 | + $this->jti = $params['jti']; |
|
60 | + $this->supportedScopes = $params['supported_scopes']; |
|
61 | + $this->defaultScope = $params['default_scope']; |
|
62 | + $this->keys = $params['keys']; |
|
63 | + } |
|
64 | + |
|
65 | + /* AuthorizationCodeInterface */ |
|
66 | + public function getAuthorizationCode($code) |
|
67 | + { |
|
68 | + if (!isset($this->authorizationCodes[$code])) { |
|
69 | + return false; |
|
70 | + } |
|
71 | + |
|
72 | + return array_merge(array( |
|
73 | + 'authorization_code' => $code, |
|
74 | + ), $this->authorizationCodes[$code]); |
|
75 | + } |
|
76 | + |
|
77 | + public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
78 | + { |
|
79 | + $this->authorizationCodes[$code] = compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope', 'id_token'); |
|
80 | + |
|
81 | + return true; |
|
82 | + } |
|
83 | + |
|
84 | + public function setAuthorizationCodes($authorization_codes) |
|
85 | + { |
|
86 | + $this->authorizationCodes = $authorization_codes; |
|
87 | + } |
|
88 | + |
|
89 | + public function expireAuthorizationCode($code) |
|
90 | + { |
|
91 | + unset($this->authorizationCodes[$code]); |
|
92 | + } |
|
93 | + |
|
94 | + /* UserCredentialsInterface */ |
|
95 | + public function checkUserCredentials($username, $password) |
|
96 | + { |
|
97 | + $userDetails = $this->getUserDetails($username); |
|
98 | + |
|
99 | + return $userDetails && $userDetails['password'] && $userDetails['password'] === $password; |
|
100 | + } |
|
101 | + |
|
102 | + public function setUser($username, $password, $firstName = null, $lastName = null) |
|
103 | + { |
|
104 | + $this->userCredentials[$username] = array( |
|
105 | + 'password' => $password, |
|
106 | + 'first_name' => $firstName, |
|
107 | + 'last_name' => $lastName, |
|
108 | + ); |
|
109 | + |
|
110 | + return true; |
|
111 | + } |
|
112 | + |
|
113 | + public function getUserDetails($username) |
|
114 | + { |
|
115 | + if (!isset($this->userCredentials[$username])) { |
|
116 | + return false; |
|
117 | + } |
|
118 | + |
|
119 | + return array_merge(array( |
|
120 | + 'user_id' => $username, |
|
121 | + 'password' => null, |
|
122 | + 'first_name' => null, |
|
123 | + 'last_name' => null, |
|
124 | + ), $this->userCredentials[$username]); |
|
125 | + } |
|
126 | + |
|
127 | + /* UserClaimsInterface */ |
|
128 | + public function getUserClaims($user_id, $claims) |
|
129 | + { |
|
130 | + if (!$userDetails = $this->getUserDetails($user_id)) { |
|
131 | + return false; |
|
132 | + } |
|
133 | + |
|
134 | + $claims = explode(' ', trim($claims)); |
|
135 | + $userClaims = array(); |
|
136 | + |
|
137 | + // for each requested claim, if the user has the claim, set it in the response |
|
138 | + $validClaims = explode(' ', self::VALID_CLAIMS); |
|
139 | + foreach ($validClaims as $validClaim) { |
|
140 | + if (in_array($validClaim, $claims)) { |
|
141 | + if ($validClaim == 'address') { |
|
142 | + // address is an object with subfields |
|
143 | + $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails); |
|
144 | + } else { |
|
145 | + $userClaims = array_merge($this->getUserClaim($validClaim, $userDetails)); |
|
146 | + } |
|
147 | + } |
|
148 | + } |
|
149 | + |
|
150 | + return $userClaims; |
|
151 | + } |
|
152 | + |
|
153 | + protected function getUserClaim($claim, $userDetails) |
|
154 | + { |
|
155 | + $userClaims = array(); |
|
156 | + $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim))); |
|
157 | + $claimValues = explode(' ', $claimValuesString); |
|
158 | + |
|
159 | + foreach ($claimValues as $value) { |
|
160 | + $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null; |
|
161 | + } |
|
162 | + |
|
163 | + return $userClaims; |
|
164 | + } |
|
165 | + |
|
166 | + /* ClientCredentialsInterface */ |
|
167 | + public function checkClientCredentials($client_id, $client_secret = null) |
|
168 | + { |
|
169 | + return isset($this->clientCredentials[$client_id]['client_secret']) && $this->clientCredentials[$client_id]['client_secret'] === $client_secret; |
|
170 | + } |
|
171 | + |
|
172 | + public function isPublicClient($client_id) |
|
173 | + { |
|
174 | + if (!isset($this->clientCredentials[$client_id])) { |
|
175 | + return false; |
|
176 | + } |
|
177 | + |
|
178 | + return empty($this->clientCredentials[$client_id]['client_secret']); |
|
179 | + } |
|
180 | + |
|
181 | + /* ClientInterface */ |
|
182 | + public function getClientDetails($client_id) |
|
183 | + { |
|
184 | + if (!isset($this->clientCredentials[$client_id])) { |
|
185 | + return false; |
|
186 | + } |
|
187 | + |
|
188 | + $clientDetails = array_merge(array( |
|
189 | + 'client_id' => $client_id, |
|
190 | + 'client_secret' => null, |
|
191 | + 'redirect_uri' => null, |
|
192 | + 'scope' => null, |
|
193 | + ), $this->clientCredentials[$client_id]); |
|
194 | + |
|
195 | + return $clientDetails; |
|
196 | + } |
|
197 | + |
|
198 | + public function checkRestrictedGrantType($client_id, $grant_type) |
|
199 | + { |
|
200 | + if (isset($this->clientCredentials[$client_id]['grant_types'])) { |
|
201 | + $grant_types = explode(' ', $this->clientCredentials[$client_id]['grant_types']); |
|
202 | + |
|
203 | + return in_array($grant_type, $grant_types); |
|
204 | + } |
|
205 | + |
|
206 | + // if grant_types are not defined, then none are restricted |
|
207 | + return true; |
|
208 | + } |
|
209 | + |
|
210 | + public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null) |
|
211 | + { |
|
212 | + $this->clientCredentials[$client_id] = array( |
|
213 | + 'client_id' => $client_id, |
|
214 | + 'client_secret' => $client_secret, |
|
215 | + 'redirect_uri' => $redirect_uri, |
|
216 | + 'grant_types' => $grant_types, |
|
217 | + 'scope' => $scope, |
|
218 | + 'user_id' => $user_id, |
|
219 | + ); |
|
220 | + |
|
221 | + return true; |
|
222 | + } |
|
223 | + |
|
224 | + /* RefreshTokenInterface */ |
|
225 | + public function getRefreshToken($refresh_token) |
|
226 | + { |
|
227 | + return isset($this->refreshTokens[$refresh_token]) ? $this->refreshTokens[$refresh_token] : false; |
|
228 | + } |
|
229 | + |
|
230 | + public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
231 | + { |
|
232 | + $this->refreshTokens[$refresh_token] = compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope'); |
|
233 | + |
|
234 | + return true; |
|
235 | + } |
|
236 | + |
|
237 | + public function unsetRefreshToken($refresh_token) |
|
238 | + { |
|
239 | + unset($this->refreshTokens[$refresh_token]); |
|
240 | + } |
|
241 | + |
|
242 | + public function setRefreshTokens($refresh_tokens) |
|
243 | + { |
|
244 | + $this->refreshTokens = $refresh_tokens; |
|
245 | + } |
|
246 | + |
|
247 | + /* AccessTokenInterface */ |
|
248 | + public function getAccessToken($access_token) |
|
249 | + { |
|
250 | + return isset($this->accessTokens[$access_token]) ? $this->accessTokens[$access_token] : false; |
|
251 | + } |
|
252 | + |
|
253 | + public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null, $id_token = null) |
|
254 | + { |
|
255 | + $this->accessTokens[$access_token] = compact('access_token', 'client_id', 'user_id', 'expires', 'scope', 'id_token'); |
|
256 | + |
|
257 | + return true; |
|
258 | + } |
|
259 | + |
|
260 | + public function unsetAccessToken($access_token) |
|
261 | + { |
|
262 | + unset($this->accessTokens[$access_token]); |
|
263 | + } |
|
264 | + |
|
265 | + public function scopeExists($scope) |
|
266 | + { |
|
267 | + $scope = explode(' ', trim($scope)); |
|
268 | + |
|
269 | + return (count(array_diff($scope, $this->supportedScopes)) == 0); |
|
270 | + } |
|
271 | + |
|
272 | + public function getDefaultScope($client_id = null) |
|
273 | + { |
|
274 | + return $this->defaultScope; |
|
275 | + } |
|
276 | + |
|
277 | + /*JWTBearerInterface */ |
|
278 | + public function getClientKey($client_id, $subject) |
|
279 | + { |
|
280 | + if (isset($this->jwt[$client_id])) { |
|
281 | + $jwt = $this->jwt[$client_id]; |
|
282 | + if ($jwt) { |
|
283 | + if ($jwt["subject"] == $subject) { |
|
284 | + return $jwt["key"]; |
|
285 | + } |
|
286 | + } |
|
287 | + } |
|
288 | + |
|
289 | + return false; |
|
290 | + } |
|
291 | + |
|
292 | + public function getClientScope($client_id) |
|
293 | + { |
|
294 | + if (!$clientDetails = $this->getClientDetails($client_id)) { |
|
295 | + return false; |
|
296 | + } |
|
297 | + |
|
298 | + if (isset($clientDetails['scope'])) { |
|
299 | + return $clientDetails['scope']; |
|
300 | + } |
|
301 | + |
|
302 | + return null; |
|
303 | + } |
|
304 | + |
|
305 | + public function getJti($client_id, $subject, $audience, $expires, $jti) |
|
306 | + { |
|
307 | + foreach ($this->jti as $storedJti) { |
|
308 | + if ($storedJti['issuer'] == $client_id && $storedJti['subject'] == $subject && $storedJti['audience'] == $audience && $storedJti['expires'] == $expires && $storedJti['jti'] == $jti) { |
|
309 | + return array( |
|
310 | + 'issuer' => $storedJti['issuer'], |
|
311 | + 'subject' => $storedJti['subject'], |
|
312 | + 'audience' => $storedJti['audience'], |
|
313 | + 'expires' => $storedJti['expires'], |
|
314 | + 'jti' => $storedJti['jti'] |
|
315 | + ); |
|
316 | + } |
|
317 | + } |
|
318 | + |
|
319 | + return null; |
|
320 | + } |
|
321 | + |
|
322 | + public function setJti($client_id, $subject, $audience, $expires, $jti) |
|
323 | + { |
|
324 | + $this->jti[] = array('issuer' => $client_id, 'subject' => $subject, 'audience' => $audience, 'expires' => $expires, 'jti' => $jti); |
|
325 | + } |
|
326 | + |
|
327 | + /*PublicKeyInterface */ |
|
328 | + public function getPublicKey($client_id = null) |
|
329 | + { |
|
330 | + if (isset($this->keys[$client_id])) { |
|
331 | + return $this->keys[$client_id]['public_key']; |
|
332 | + } |
|
333 | + |
|
334 | + // use a global encryption pair |
|
335 | + if (isset($this->keys['public_key'])) { |
|
336 | + return $this->keys['public_key']; |
|
337 | + } |
|
338 | + |
|
339 | + return false; |
|
340 | + } |
|
341 | + |
|
342 | + public function getPrivateKey($client_id = null) |
|
343 | + { |
|
344 | + if (isset($this->keys[$client_id])) { |
|
345 | + return $this->keys[$client_id]['private_key']; |
|
346 | + } |
|
347 | + |
|
348 | + // use a global encryption pair |
|
349 | + if (isset($this->keys['private_key'])) { |
|
350 | + return $this->keys['private_key']; |
|
351 | + } |
|
352 | + |
|
353 | + return false; |
|
354 | + } |
|
355 | + |
|
356 | + public function getEncryptionAlgorithm($client_id = null) |
|
357 | + { |
|
358 | + if (isset($this->keys[$client_id]['encryption_algorithm'])) { |
|
359 | + return $this->keys[$client_id]['encryption_algorithm']; |
|
360 | + } |
|
361 | + |
|
362 | + // use a global encryption algorithm |
|
363 | + if (isset($this->keys['encryption_algorithm'])) { |
|
364 | + return $this->keys['encryption_algorithm']; |
|
365 | + } |
|
366 | + |
|
367 | + return 'RS256'; |
|
368 | + } |
|
369 | 369 | } |