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 | * DefaultController.php |
||
4 | * |
||
5 | * PHP version 5.6+ |
||
6 | * |
||
7 | * @author pgaultier |
||
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\controllers |
||
13 | */ |
||
14 | |||
15 | namespace sweelix\oauth2\server\controllers; |
||
16 | |||
17 | use OAuth2\Request as OAuth2Request; |
||
18 | use OAuth2\Response as OAuth2Response; |
||
19 | use sweelix\oauth2\server\models\Client; |
||
20 | use sweelix\oauth2\server\models\Scope; |
||
21 | use sweelix\oauth2\server\Module; |
||
22 | use yii\filters\AccessControl; |
||
23 | use yii\web\Controller; |
||
24 | use yii\web\Response; |
||
25 | use Yii; |
||
26 | |||
27 | /** |
||
28 | * Oauth2 main controller |
||
29 | * |
||
30 | * @author pgaultier |
||
31 | * @copyright 2010-2017 Philippe Gaultier |
||
32 | * @license http://www.sweelix.net/license license |
||
33 | * @version 1.2.0 |
||
34 | * @link http://www.sweelix.net |
||
35 | * @package sweelix\oauth2\server\controllers |
||
36 | * @since 1.0.0 |
||
37 | */ |
||
38 | class AuthorizeController extends Controller |
||
39 | { |
||
40 | /** |
||
41 | * @var string |
||
42 | */ |
||
43 | private $userClass; |
||
44 | 10 | ||
45 | /** |
||
46 | 10 | * @inheritdoc |
|
47 | */ |
||
48 | 10 | public function init() |
|
49 | { |
||
50 | $module = Module::getInstance(); |
||
51 | |||
52 | 10 | if ($module->overrideLayout !== null) { |
|
0 ignored issues
–
show
|
|||
53 | $this->layout = $module->overrideLayout; |
||
0 ignored issues
–
show
The property
overrideLayout does not seem to exist. Did you mean layout ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
54 | } |
||
55 | |||
56 | 10 | if ($module->overrideViewPath !== null) { |
|
0 ignored issues
–
show
The property
overrideViewPath does not seem to exist. Did you mean viewPath ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
57 | 10 | $this->setViewPath($module->overrideViewPath); |
|
0 ignored issues
–
show
The property
overrideViewPath does not seem to exist. Did you mean viewPath ?
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
58 | } |
||
59 | |||
60 | parent::init(); |
||
61 | } |
||
62 | 10 | ||
63 | /** |
||
64 | 10 | * @inheritdoc |
|
65 | 10 | */ |
|
66 | 10 | public function behaviors() |
|
67 | 10 | { |
|
68 | $behaviors = parent::behaviors(); |
||
69 | $behaviors['access'] = [ |
||
70 | 10 | 'class' => AccessControl::class, |
|
71 | 10 | 'only' => ['authorize'], |
|
72 | 10 | 'rules' => [ |
|
73 | 10 | [ |
|
74 | 10 | 'allow' => true, |
|
75 | 'actions' => ['authorize'], |
||
76 | 10 | 'roles' => ['@'], |
|
77 | ], |
||
78 | ], |
||
79 | ]; |
||
80 | return $behaviors; |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | 9 | * Send back an oauth token |
|
85 | * |
||
86 | 9 | * @return Response |
|
87 | 9 | * @throws \yii\base\InvalidConfigException |
|
88 | * @since 1.0.0 |
||
89 | 9 | */ |
|
90 | 9 | public function actionIndex() |
|
91 | 9 | { |
|
92 | 9 | Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
|
93 | |||
94 | $status = false; |
||
95 | 9 | ||
96 | 5 | /** @var \OAuth2\Server $oauthServer */ |
|
97 | 4 | $oauthServer = Yii::createObject('OAuth2\Server'); |
|
98 | |||
99 | 4 | /** @var \OAuth2\Request $oauthRequest */ |
|
100 | 4 | $oauthRequest = OAuth2Request::createFromGlobals(); |
|
101 | 4 | ||
102 | 4 | $oauthResponse = new OAuth2Response(); |
|
103 | 2 | ||
104 | /** @var string $grantType */ |
||
105 | 2 | $grantType = Yii::$app->request->getQueryParam('response_type'); |
|
106 | 4 | $promptValues = key_exists('prompt', $oauthRequest->query) ? explode(" ", $oauthRequest->query['prompt']) : []; |
|
107 | 1 | ||
108 | 1 | switch ($grantType) { |
|
109 | case 'code': |
||
110 | 5 | // Authorization Code |
|
111 | if (Module::getInstance()->allowAuthorizationCode === true) { |
||
112 | 4 | /** @var \Oauth2\GrantType\AuthorizationCode $oauthGrantType */ |
|
113 | 4 | $oauthGrantType = Yii::createObject('OAuth2\GrantType\AuthorizationCode'); |
|
114 | 4 | $oauthServer->addGrantType($oauthGrantType); |
|
115 | 4 | $status = $oauthServer->validateAuthorizeRequest($oauthRequest, $oauthResponse); |
|
116 | 2 | } else { |
|
117 | $status = false; |
||
118 | 2 | $oauthResponse->setError(400, 'invalid_grant', 'Authorization code grant is not supported'); |
|
119 | 4 | } |
|
120 | break; |
||
121 | case 'token': |
||
122 | 9 | // Implicit |
|
123 | 4 | $status = $oauthServer->validateAuthorizeRequest($oauthRequest, $oauthResponse); |
|
124 | 4 | break; |
|
125 | 4 | } |
|
126 | 4 | ||
127 | 4 | if ($status === false) { |
|
128 | 4 | // handle request validation error |
|
129 | 4 | $this->handleErrorResponse($oauthResponse); |
|
130 | 1 | } else { |
|
131 | Yii::$app->session->set('oauthServer', $oauthServer); |
||
132 | 4 | if (isset($oauthRequest) === true) { |
|
133 | Yii::$app->session->set('oauthRequest', $oauthRequest); |
||
134 | 5 | } |
|
135 | |||
136 | 9 | if (Yii::$app->user->isGuest === true || in_array('login', $promptValues, true)) { |
|
137 | /** @var \Oauth2\Controller\AuthorizeController $authController */ |
||
138 | $authController = $oauthServer->getAuthorizeController(); |
||
139 | |||
140 | //TODO: check if the user should get logged out |
||
141 | if (in_array('none', $promptValues, true)) { |
||
142 | $response = new OAuth2Response(); |
||
143 | $response->setRedirect(302, $authController->getRedirectUri(), $authController->getState(), |
||
144 | 5 | 'login_required', |
|
145 | 'Authentication Request cannot be completed without user authentication.', |
||
146 | 5 | NULL |
|
147 | ); |
||
148 | 5 | $this->handleErrorResponse($response); |
|
149 | } else { |
||
150 | 5 | return $this->redirect(['login']); |
|
151 | 1 | } |
|
152 | 1 | } else { |
|
153 | 1 | return $this->redirect(['authorize']); |
|
154 | 1 | } |
|
155 | 1 | } |
|
156 | } |
||
157 | |||
158 | 4 | /** |
|
159 | 4 | * Display login page |
|
160 | * |
||
161 | 4 | * @return Response | string |
|
162 | * @throws \yii\base\InvalidConfigException |
||
163 | 4 | * @since 1.0.0 |
|
164 | 4 | */ |
|
165 | 4 | public function actionLogin() |
|
166 | 4 | { |
|
167 | Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
||
168 | 4 | ||
169 | 4 | /* @var \Oauth2\Server $oauthServer */ |
|
170 | 4 | $oauthServer = Yii::$app->session->get('oauthServer'); |
|
171 | 4 | ||
172 | 2 | if ($oauthServer === null) { |
|
173 | $response = new OAuth2Response(); |
||
174 | 4 | $response->setError(400, 'invalid_request', 'The request was not performed as expected.'); |
|
175 | 4 | $this->handleErrorResponse($response); |
|
176 | 4 | } |
|
177 | |||
178 | 4 | $response = null; |
|
179 | 4 | $oauthRequest = Yii::$app->session->get('oauthRequest'); |
|
180 | 4 | $promptValues = $oauthRequest && key_exists('prompt', $oauthRequest->query) ? explode(" ", $oauthRequest->query['prompt']) : []; |
|
181 | 4 | /* @var \sweelix\oauth2\server\forms\User $userForm */ |
|
182 | 4 | $userForm = Yii::createObject('sweelix\oauth2\server\forms\User'); |
|
183 | 4 | ||
184 | if (Yii::$app->request->isPost === true) { |
||
185 | //TODO: handle case when user decline the grants |
||
186 | $userForm->load(Yii::$app->request->bodyParams); |
||
187 | if ($userForm->validate() === true) { |
||
188 | $userClass = $this->getUserClass(); |
||
189 | /* @var \sweelix\oauth2\server\interfaces\UserModelInterface $realUser */ |
||
190 | $realUser = $userClass::findByUsernameAndPassword($userForm->username, $userForm->password); |
||
191 | 4 | if ($realUser !== null) { |
|
192 | Yii::$app->user->login($realUser, Module::getInstance()->loginDuration); |
||
193 | 4 | $response = $this->redirect(['authorize']); |
|
194 | 4 | } else { |
|
195 | $userForm->addError('username'); |
||
196 | 4 | } |
|
197 | } |
||
198 | } |
||
199 | if ($response === null) { |
||
200 | if(in_array('none', $promptValues, true)) { |
||
201 | /** @var \Oauth2\Controller\AuthorizeController $authController */ |
||
202 | 1 | $authController = $oauthServer->getAuthorizeController(); |
|
203 | 4 | $oauthResponse = $oauthServer->getResponse(); |
|
204 | 4 | $oauthResponse->setRedirect(302, $authController->getRedirectUri(), $authController->getState(), |
|
205 | 'login_required', |
||
206 | 4 | 'Authentication Request cannot be completed without user authentication.', |
|
207 | null |
||
208 | 1 | ); |
|
209 | 1 | $this->handleErrorResponse($oauthResponse); |
|
0 ignored issues
–
show
$oauthResponse of type object<OAuth2\ResponseInterface> is not a sub-type of object<OAuth2\Response> . It seems like you assume a concrete implementation of the interface OAuth2\ResponseInterface to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
210 | 1 | } |
|
211 | // force empty password |
||
212 | 1 | $userForm->password = ''; |
|
213 | 1 | $response = $this->render('login', [ |
|
0 ignored issues
–
show
|
|||
214 | 1 | 'user' => $userForm, |
|
215 | 1 | ]); |
|
216 | } |
||
217 | return $response; |
||
218 | } |
||
219 | 1 | ||
220 | /** |
||
221 | * Display authorize page |
||
222 | * |
||
223 | 4 | * @return Response | string |
|
224 | 4 | * @throws \yii\base\UnknownClassException |
|
225 | 4 | * @since 1.0.0 |
|
226 | */ |
||
227 | public function actionAuthorize() |
||
228 | { |
||
229 | Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
||
230 | |||
231 | /* @var \Oauth2\Server $oauthServer */ |
||
232 | $oauthServer = Yii::$app->session->get('oauthServer'); |
||
233 | |||
234 | if ($oauthServer === NULL) { |
||
235 | $response = new OAuth2Response(); |
||
236 | $response->setError(400, 'invalid_request', 'The request was not performed as expected.'); |
||
237 | $this->handleErrorResponse($response); |
||
238 | } |
||
239 | |||
240 | 4 | /** @var \OAuth2\Controller\AuthorizeController $authController */ |
|
241 | 4 | $authController = $oauthServer->getAuthorizeController(); |
|
242 | 4 | $client = Client::findOne($authController->getClientId()); |
|
243 | 4 | $oauthRequest = Yii::$app->session->get('oauthRequest'); |
|
244 | $promptValues = $oauthRequest && key_exists('prompt', $oauthRequest->query) ? explode(" ", $oauthRequest->query['prompt']) : []; |
||
245 | |||
246 | 4 | // user has already granted permission |
|
247 | 2 | if ($client->hasUser(Yii::$app->user->id) === true && !in_array('consent', $promptValues, true)) { |
|
248 | 2 | //TODO: check if all consents should be removed |
|
249 | /** @var \OAuth2\Response $oauthResponse */ |
||
250 | 2 | $oauthResponse = new OAuth2Response(); |
|
251 | 2 | $oauthResponse = $oauthServer->handleAuthorizeRequest($oauthRequest, $oauthResponse, true, Yii::$app->user->id); |
|
252 | 2 | ||
253 | if ($oauthResponse->getParameter('error') === NULL) { |
||
254 | Yii::$app->session->remove('oauthServer'); |
||
255 | Yii::$app->session->remove('oauthRequest'); |
||
256 | 4 | ||
257 | 4 | return $this->redirect($oauthResponse->getHttpHeader('Location')); |
|
258 | 4 | } else { |
|
259 | 4 | $this->handleErrorResponse($oauthResponse); |
|
0 ignored issues
–
show
$oauthResponse of type object<OAuth2\ResponseInterface> is not a sub-type of object<OAuth2\Response> . It seems like you assume a concrete implementation of the interface OAuth2\ResponseInterface to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
260 | 4 | } |
|
261 | } else { |
||
262 | // perform regular authorization |
||
263 | if (in_array('none', $promptValues, true)) { |
||
264 | 4 | $oauthResponse = $oauthServer->getResponse(); |
|
265 | $oauthResponse->setRedirect(302, $authController->getRedirectUri(), $authController->getState(), |
||
266 | 'consent_required', |
||
267 | 'Authentication Request cannot be completed without End-User consent.', |
||
268 | NULL |
||
269 | 4 | ); |
|
270 | 4 | $this->handleErrorResponse($oauthResponse); |
|
0 ignored issues
–
show
$oauthResponse of type object<OAuth2\ResponseInterface> is not a sub-type of object<OAuth2\Response> . It seems like you assume a concrete implementation of the interface OAuth2\ResponseInterface to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
271 | 4 | } |
|
272 | 4 | ||
273 | $additionalScopes = $authController->getScope(); |
||
274 | $requestedScopes = []; |
||
275 | if (empty($additionalScopes) === false) { |
||
276 | $additionalScopes = explode(' ', $additionalScopes); |
||
277 | foreach ($additionalScopes as $scope) { |
||
278 | $dbScope = Scope::findOne($scope); |
||
279 | if ($dbScope !== NULL) { |
||
280 | 6 | $requestedScopes[] = $dbScope; |
|
281 | } else { |
||
282 | 6 | $response = new OAuth2Response(); |
|
283 | 6 | $response->setError(400, 'invalid_scope', 'Scope ' . $scope . ' does not exist.'); |
|
284 | 6 | $this->handleErrorResponse($response); |
|
285 | 6 | } |
|
286 | 6 | } |
|
287 | 6 | } |
|
288 | if (Yii::$app->request->isPost === true) { |
||
289 | $accept = Yii::$app->request->getBodyParam('accept'); |
||
290 | /** @var \Oauth2\Request $oauthRequest */ |
||
291 | $oauthRequest = Yii::$app->session->get('oauthRequest'); |
||
292 | /** @var \Oauth2\Response $oauthResponse */ |
||
293 | $oauthResponse = new OAuth2Response(); |
||
294 | |||
295 | if ($accept !== NULL) { |
||
296 | // authorize |
||
297 | $oauthResponse = $oauthServer->handleAuthorizeRequest($oauthRequest, $oauthResponse, true, Yii::$app->user->id); |
||
298 | // check if user has not already granted the client |
||
299 | 4 | if ($client->hasUser(Yii::$app->user->id) === false) { |
|
300 | $client->addUser(Yii::$app->user->id); |
||
301 | 4 | } |
|
302 | 4 | } else { |
|
303 | 4 | // decline |
|
304 | 4 | $oauthResponse = $oauthServer->handleAuthorizeRequest($oauthRequest, $oauthResponse, false, Yii::$app->user->id); |
|
305 | 4 | $client->removeUser(Yii::$app->user->id); |
|
306 | } |
||
307 | |||
308 | Yii::$app->session->remove('oauthServer'); |
||
309 | Yii::$app->session->remove('oauthRequest'); |
||
310 | $error = $oauthResponse->getParameters(); |
||
0 ignored issues
–
show
The method
getParameters() does not exist on OAuth2\ResponseInterface . Did you maybe mean getParameter() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
311 | $redirect = $oauthResponse->getHttpHeader('Location'); |
||
312 | if ((empty($error) === false) && ($redirect === NULL)) { |
||
313 | Yii::$app->session->setFlash('error', $error, false); |
||
314 | return $this->redirect(['error']); |
||
315 | } else { |
||
316 | return $this->redirect($redirect); |
||
317 | } |
||
318 | } |
||
319 | } |
||
320 | return $this->render('authorize', [ |
||
0 ignored issues
–
show
The return type of
return $this->render('au... => $requestedScopes)); (string ) is incompatible with the return type documented by sweelix\oauth2\server\co...roller::actionAuthorize of type yii\web\Response .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
321 | 'client' => $client, |
||
322 | 'requestedScopes' => $requestedScopes, |
||
0 ignored issues
–
show
The variable
$requestedScopes does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
323 | ]); |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Display an error page |
||
328 | * |
||
329 | * @return Response | string |
||
330 | * @since 1.0.0 |
||
331 | */ |
||
332 | public function actionError() |
||
333 | { |
||
334 | Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
||
335 | |||
336 | $errorData = Yii::$app->session->getFlash('error'); |
||
337 | $code = isset($errorData['code']) && is_numeric($errorData['code']) ? $errorData['code'] : 400; |
||
338 | Yii::$app->response->setStatusCode($code); |
||
339 | |||
340 | return $this->render('error', [ |
||
341 | 'type' => (isset($errorData['error']) ? $errorData['error'] : null), |
||
342 | 'description' => (isset($errorData['error_description']) ? $errorData['error_description'] : null), |
||
343 | ]); |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Handles OAuth errors by either displaying an error page or redirecting to the callback |
||
348 | * |
||
349 | * @param \Oauth2\Response $response |
||
350 | * @return Response | null |
||
351 | */ |
||
352 | public function handleErrorResponse($response) |
||
353 | { |
||
354 | if ($response->getParameter('error') !== null) { |
||
355 | Yii::$app->session->remove('oauthServer'); |
||
356 | Yii::$app->session->remove('oauthRequest'); |
||
357 | |||
358 | if ($response->isRedirection()) { |
||
359 | return $this->redirect($response->getHttpHeader('Location')); |
||
360 | } else { |
||
361 | $code = $response->getStatusCode(); |
||
362 | $error = $response->getParameter('error', 'Unkown error'); |
||
363 | $description = $response->getParameter('error_description', 'Please check your request.'); |
||
364 | Yii::$app->session->setFlash('error', [ |
||
365 | 'code' => $code, |
||
366 | 'error' => $error, |
||
367 | 'error_description' => $description |
||
368 | ], false |
||
369 | ); |
||
370 | return $this->redirect(['error']); |
||
371 | } |
||
372 | } |
||
373 | |||
374 | return null; |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * @return string classname for selected interface |
||
379 | * @throws \yii\base\InvalidConfigException |
||
380 | * @since 1.0.0 |
||
381 | */ |
||
382 | public function getUserClass() |
||
383 | { |
||
384 | if ($this->userClass === null) { |
||
385 | $scope = Yii::createObject('sweelix\oauth2\server\interfaces\UserModelInterface'); |
||
386 | $this->userClass = get_class($scope); |
||
387 | } |
||
388 | return $this->userClass; |
||
389 | } |
||
390 | } |
||
391 |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.