This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * RefreshTokenService.php |
||
4 | * |
||
5 | * PHP version 5.6+ |
||
6 | * |
||
7 | * @author Philippe Gaultier <[email protected]> |
||
8 | * @copyright 2010-2017 Philippe Gaultier |
||
9 | * @license http://www.sweelix.net/license license |
||
10 | * @version 1.2.0 |
||
11 | * @link http://www.sweelix.net |
||
12 | * @package sweelix\oauth2\server\services\mySql |
||
13 | */ |
||
14 | |||
15 | namespace sweelix\oauth2\server\services\mySql; |
||
16 | |||
17 | use sweelix\oauth2\server\exceptions\DuplicateIndexException; |
||
18 | use sweelix\oauth2\server\exceptions\DuplicateKeyException; |
||
19 | use sweelix\oauth2\server\interfaces\RefreshTokenModelInterface; |
||
20 | use sweelix\oauth2\server\interfaces\RefreshTokenServiceInterface; |
||
21 | use yii\db\Exception as DatabaseException; |
||
22 | use Yii; |
||
23 | use yii\db\Query; |
||
24 | |||
25 | /** |
||
26 | * This is the refresh token service for mySql |
||
27 | * database structure |
||
28 | * * oauth2:refreshTokens:<rid> : hash (RefreshToken) |
||
29 | * * oauth2:users:<uid>:refreshTokens : set (RefreshTokens for user) |
||
30 | * * oauth2:clients:<cid>:refreshTokens : set (RefreshTokens for client) |
||
31 | * |
||
32 | * @author Philippe Gaultier <[email protected]> |
||
33 | * @copyright 2010-2017 Philippe Gaultier |
||
34 | * @license http://www.sweelix.net/license license |
||
35 | * @version 1.2.0 |
||
36 | * @link http://www.sweelix.net |
||
37 | * @package sweelix\oauth2\server\services\mySql |
||
38 | * @since 1.0.0 |
||
39 | */ |
||
40 | class RefreshTokenService extends BaseService implements RefreshTokenServiceInterface |
||
41 | { |
||
42 | /** |
||
43 | * @var string sql refreshTokens table |
||
44 | */ |
||
45 | public $refreshTokensTable = null; |
||
46 | |||
47 | /** |
||
48 | * @var string sql scope refreshToken table |
||
49 | */ |
||
50 | public $scopeRefreshTokenTable = null; |
||
51 | |||
52 | /** |
||
53 | * Save Refresh Token |
||
54 | * @param RefreshTokenModelInterface $refreshToken |
||
55 | * @param null|array $attributes attributes to save |
||
56 | * @return bool |
||
57 | * @throws DatabaseException |
||
58 | * @throws DuplicateIndexException |
||
59 | * @throws DuplicateKeyException |
||
60 | * @since 1.0.0 |
||
61 | */ |
||
62 | protected function insert(RefreshTokenModelInterface $refreshToken, $attributes) |
||
63 | { |
||
64 | $result = false; |
||
65 | if (!$refreshToken->beforeSave(true)) { |
||
66 | return $result; |
||
67 | } |
||
68 | $refreshTokenKey = $refreshToken->getKey(); |
||
69 | $entity = (new Query()) |
||
70 | ->select('*') |
||
71 | ->from($this->refreshTokensTable) |
||
72 | ->where('id = :id', [':id' => $refreshTokenKey]) |
||
73 | ->one($this->db); |
||
74 | if ($entity !== false) { |
||
75 | throw new DuplicateKeyException('Duplicate key "' . $refreshTokenKey . '"'); |
||
76 | } |
||
77 | $values = $refreshToken->getDirtyAttributes($attributes); |
||
0 ignored issues
–
show
|
|||
78 | $refreshTokenParameters = []; |
||
79 | $this->setAttributesDefinitions($refreshToken->attributesDefinition()); |
||
80 | foreach ($values as $key => $value) { |
||
81 | if (($value !== null) && ($key !== 'scopes')) { |
||
82 | $refreshTokenParameters[$key] = $this->convertToDatabase($key, $value); |
||
83 | } |
||
84 | } |
||
85 | $refreshTokenParameters['dateCreated'] = date('Y-m-d H:i:s'); |
||
86 | $refreshTokenParameters['dateUpdated'] = date('Y-m-d H:i:s'); |
||
87 | try { |
||
88 | $this->db->createCommand() |
||
89 | ->insert($this->refreshTokensTable, $refreshTokenParameters) |
||
90 | ->execute(); |
||
91 | if (!empty($values['scopes'])) { |
||
92 | $values['scopes'] = array_unique($values['scopes']); |
||
93 | foreach ($values['scopes'] as $scope) { |
||
94 | $scopeAccessTokenParams = [ |
||
95 | 'scopeId' => $scope, |
||
96 | 'refreshTokenId' => $refreshTokenKey |
||
97 | ]; |
||
98 | $this->db->createCommand() |
||
99 | ->insert($this->scopeRefreshTokenTable, $scopeAccessTokenParams) |
||
100 | ->execute(); |
||
101 | } |
||
102 | } |
||
103 | } catch (DatabaseException $e) { |
||
104 | // @codeCoverageIgnoreStart |
||
105 | // we have a MYSQL exception, we should not discard |
||
106 | Yii::debug('Error while inserting entity', __METHOD__); |
||
107 | throw $e; |
||
108 | // @codeCoverageIgnoreEnd |
||
109 | } |
||
110 | $changedAttributes = array_fill_keys(array_keys($values), null); |
||
111 | $refreshToken->setOldAttributes($values); |
||
112 | $refreshToken->afterSave(true, $changedAttributes); |
||
113 | $result = true; |
||
114 | return $result; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Update Refresh Token |
||
119 | * @param RefreshTokenModelInterface $refreshToken |
||
120 | * @param null|array $attributes attributes to save |
||
121 | * @return bool |
||
122 | * @throws DatabaseException |
||
123 | * @throws DuplicateIndexException |
||
124 | * @throws DuplicateKeyException |
||
125 | */ |
||
126 | protected function update(RefreshTokenModelInterface $refreshToken, $attributes) |
||
127 | { |
||
128 | if (!$refreshToken->beforeSave(false)) { |
||
129 | return false; |
||
130 | } |
||
131 | |||
132 | $values = $refreshToken->getDirtyAttributes($attributes); |
||
0 ignored issues
–
show
It seems like
$attributes defined by parameter $attributes on line 126 can also be of type array ; however, sweelix\oauth2\server\in...e::getDirtyAttributes() does only seem to accept array<integer,string>|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
133 | $modelKey = $refreshToken->key(); |
||
134 | if (isset($values[$modelKey]) === true) { |
||
135 | $entity = (new Query()) |
||
136 | ->select('*') |
||
137 | ->from($this->refreshTokensTable) |
||
138 | ->where('id = :id', [':id' => $values[$modelKey]]) |
||
139 | ->one($this->db); |
||
140 | if ($entity !== false) { |
||
141 | throw new DuplicateKeyException('Duplicate key "' . $values[$modelKey] . '"'); |
||
142 | } |
||
143 | } |
||
144 | $refreshTokenKey = isset($values[$modelKey]) ? $values[$modelKey] : $refreshToken->getKey(); |
||
145 | |||
146 | $refreshTokenParameters = []; |
||
147 | $this->setAttributesDefinitions($refreshToken->attributesDefinition()); |
||
148 | foreach ($values as $key => $value) { |
||
149 | if ($key !== 'scopes') { |
||
150 | $refreshTokenParameters[$key] = ($value !== null) ? $this->convertToDatabase($key, $value) : null; |
||
151 | } |
||
152 | } |
||
153 | $refreshTokenParameters['dateUpdated'] = date('Y-m-d H:i:s'); |
||
154 | try { |
||
155 | if (array_key_exists($modelKey, $values) === true) { |
||
156 | $oldRefreshTokenKey = $refreshToken->getOldKey(); |
||
157 | $this->db->createCommand() |
||
158 | ->update($this->refreshTokensTable, $refreshTokenParameters, 'id = :id', [':id' => $oldRefreshTokenKey]) |
||
159 | ->execute(); |
||
160 | } else { |
||
161 | $this->db->createCommand() |
||
162 | ->update($this->refreshTokensTable, $refreshTokenParameters, 'id = :id', [':id' => $refreshTokenKey]) |
||
163 | ->execute(); |
||
164 | } |
||
165 | if (isset($values['scopes'])) { |
||
166 | $values['scopes'] = array_unique($values['scopes']); |
||
167 | $scopeRefreshTokens = (new Query()) |
||
168 | ->select('*') |
||
169 | ->from($this->scopeRefreshTokenTable) |
||
170 | ->where('refreshTokenId = :refreshTokenId', [':refreshTokenId' => $refreshTokenKey]) |
||
171 | ->all($this->db); |
||
172 | foreach ($scopeRefreshTokens as $scopeRefreshToken) { |
||
173 | if (($index = array_search($scopeRefreshToken['scopeId'], $values['scopes'])) === false) { |
||
174 | $this->db->createCommand() |
||
175 | ->delete($this->scopeRefreshTokenTable, |
||
176 | 'refreshTokenId = :refreshTokenId AND scopeId = :scopeId', |
||
177 | [':refreshTokenId' => $refreshTokenKey, ':scopeId' => $scopeRefreshToken['scopeId']]) |
||
178 | ->execute(); |
||
179 | } else { |
||
180 | unset($values['scopes'][$index]); |
||
181 | } |
||
182 | } |
||
183 | foreach ($values['scopes'] as $scope) { |
||
184 | $scopeRefreshTokenParams = [ |
||
185 | 'scopeId' => $scope, |
||
186 | 'refreshTokenId' => $refreshTokenKey |
||
187 | ]; |
||
188 | $this->db->createCommand() |
||
189 | ->insert($this->scopeRefreshTokenTable, $scopeRefreshTokenParams) |
||
190 | ->execute(); |
||
191 | } |
||
192 | } |
||
193 | } catch (DatabaseException $e) { |
||
194 | // @codeCoverageIgnoreStart |
||
195 | // we have a MYSQL exception, we should not discard |
||
196 | Yii::debug('Error while updating entity', __METHOD__); |
||
197 | throw $e; |
||
198 | // @codeCoverageIgnoreEnd |
||
199 | } |
||
200 | |||
201 | $changedAttributes = []; |
||
202 | foreach ($values as $name => $value) { |
||
203 | $oldAttributes = $refreshToken->getOldAttributes(); |
||
204 | $changedAttributes[$name] = isset($oldAttributes[$name]) ? $oldAttributes[$name] : null; |
||
205 | $refreshToken->setOldAttribute($name, $value); |
||
206 | } |
||
207 | $refreshToken->afterSave(false, $changedAttributes); |
||
208 | return true; |
||
209 | } |
||
210 | |||
211 | /** |
||
212 | * @inheritdoc |
||
213 | */ |
||
214 | public function save(RefreshTokenModelInterface $refreshToken, $attributes) |
||
215 | { |
||
216 | if ($refreshToken->getIsNewRecord()) { |
||
217 | $result = $this->insert($refreshToken, $attributes); |
||
218 | } else { |
||
219 | $result = $this->update($refreshToken, $attributes); |
||
220 | } |
||
221 | return $result; |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * @inheritdoc |
||
226 | */ |
||
227 | public function findOne($key) |
||
228 | { |
||
229 | $record = null; |
||
230 | $refreshTokenData = (new Query()) |
||
231 | ->select('*') |
||
232 | ->from($this->refreshTokensTable) |
||
233 | ->where('id = :id', [':id' => $key]) |
||
234 | ->one($this->db); |
||
235 | |||
236 | if ($refreshTokenData !== false) { |
||
237 | $refreshTokenData['scopes'] = []; |
||
238 | $tmpScopes = (new Query()) |
||
239 | ->select('scopeId') |
||
240 | ->from($this->scopeRefreshTokenTable) |
||
241 | ->all($this->db); |
||
242 | foreach ($tmpScopes as $scope) { |
||
243 | $refreshTokenData['scopes'][] = $scope['scopeId']; |
||
244 | } |
||
245 | |||
246 | $record = Yii::createObject('sweelix\oauth2\server\interfaces\RefreshTokenModelInterface'); |
||
247 | /** @var RefreshTokenModelInterface $record */ |
||
248 | $properties = $record->attributesDefinition(); |
||
249 | $this->setAttributesDefinitions($properties); |
||
250 | $attributes = []; |
||
251 | foreach ($refreshTokenData as $key => $value) { |
||
252 | if (isset($properties[$key]) === true) { |
||
253 | $refreshTokenData[$key] = $this->convertToModel($key, $value); |
||
254 | $record->setAttribute($key, $refreshTokenData[$key]); |
||
255 | $attributes[$key] = $refreshTokenData[$key]; |
||
256 | // @codeCoverageIgnoreStart |
||
257 | } elseif ($record->canSetProperty($key)) { |
||
258 | // TODO: find a way to test attribute population |
||
259 | $record->{$key} = $value; |
||
260 | } |
||
261 | // @codeCoverageIgnoreEnd |
||
262 | } |
||
263 | if (empty($attributes) === false) { |
||
264 | $record->setOldAttributes($attributes); |
||
265 | } |
||
266 | $record->afterFind(); |
||
267 | } |
||
268 | return $record; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * @inheritdoc |
||
273 | */ |
||
274 | public function delete(RefreshTokenModelInterface $refreshToken) |
||
275 | { |
||
276 | $result = false; |
||
277 | if ($refreshToken->beforeDelete()) { |
||
278 | //TODO: check results to return correct information |
||
279 | $this->db->createCommand() |
||
280 | ->delete($this->refreshTokensTable, 'id = :id', [':id' => $refreshToken->getKey()]) |
||
281 | ->execute(); |
||
282 | $refreshToken->setIsNewRecord(true); |
||
283 | $refreshToken->afterDelete(); |
||
284 | $result = true; |
||
285 | } |
||
286 | return $result; |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * @inheritdoc |
||
291 | */ |
||
292 | public function findAllByUserId($userId) |
||
293 | { |
||
294 | $refreshTokensList = (new Query()) |
||
295 | ->select('*') |
||
296 | ->from($this->refreshTokensTable) |
||
297 | ->where('userId = :userId', [':userId' => $userId]) |
||
298 | ->all($this->db); |
||
299 | $refreshTokens = []; |
||
300 | foreach ($refreshTokensList as $refreshToken) { |
||
301 | $result = $this->findOne($refreshToken['id']); |
||
302 | if ($result instanceof RefreshTokenModelInterface) { |
||
303 | $refreshTokens[] = $result; |
||
304 | } |
||
305 | } |
||
306 | return $refreshTokens; |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * @inheritdoc |
||
311 | */ |
||
312 | public function deleteAllByUserId($userId) |
||
313 | { |
||
314 | $refreshTokens = $this->findAllByUserId($userId); |
||
315 | foreach ($refreshTokens as $refreshToken) { |
||
316 | $this->delete($refreshToken); |
||
317 | } |
||
318 | return true; |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * @inheritdoc |
||
323 | */ |
||
324 | public function findAllByClientId($clientId) |
||
325 | { |
||
326 | $refreshTokensList = (new Query()) |
||
327 | ->select('*') |
||
328 | ->from($this->refreshTokensTable) |
||
329 | ->where('clientId = :clientId', [':clientId' => $clientId]) |
||
330 | ->all($this->db); |
||
331 | $refreshTokens = []; |
||
332 | foreach ($refreshTokensList as $refreshToken) { |
||
333 | $result = $this->findOne($refreshToken['id']); |
||
334 | if ($result instanceof RefreshTokenModelInterface) { |
||
335 | $refreshTokens[] = $result; |
||
336 | } |
||
337 | } |
||
338 | return $refreshTokens; |
||
339 | } |
||
340 | |||
341 | /** |
||
342 | * @inheritdoc |
||
343 | */ |
||
344 | public function deleteAllByClientId($clientId) |
||
345 | { |
||
346 | $refreshTokens = $this->findAllByClientId($clientId); |
||
347 | foreach ($refreshTokens as $refreshToken) { |
||
348 | $this->delete($refreshToken); |
||
349 | } |
||
350 | return true; |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * @inheritdoc |
||
355 | */ |
||
356 | public function deleteAllExpired() |
||
357 | { |
||
358 | $refreshTokens = (new Query())->select('*') |
||
359 | ->from($this->refreshTokensTable) |
||
360 | ->where('expiry < :date', [':date' => date('Y-m-d H:i:s')]) |
||
361 | ->all($this->db); |
||
362 | foreach ($refreshTokens as $refreshTokenQuery) { |
||
363 | $refreshToken = $this->findOne($refreshTokenQuery['id']); |
||
364 | if ($refreshToken instanceof RefreshTokenModelInterface) { |
||
365 | $this->delete($refreshToken); |
||
366 | } |
||
367 | } |
||
368 | return true; |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * @inheritdoc |
||
373 | */ |
||
374 | public function findAll() |
||
375 | { |
||
376 | $refreshTokensList = (new Query()) |
||
377 | ->select('*') |
||
378 | ->from($this->refreshTokensTable) |
||
379 | ->all($this->db); |
||
380 | $refreshTokens = []; |
||
381 | foreach ($refreshTokensList as $refreshToken) { |
||
382 | $result = $this->findOne($refreshToken['id']); |
||
383 | if ($result instanceof RefreshTokenModelInterface) { |
||
384 | $refreshTokens[] = $result; |
||
385 | } |
||
386 | } |
||
387 | return $refreshTokens; |
||
388 | } |
||
389 | } |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.