1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* DefaultController.php |
4
|
|
|
* |
5
|
|
|
* PHP version 5.6+ |
6
|
|
|
* |
7
|
|
|
* @author pgaultier |
8
|
|
|
* @copyright 2010-2016 Ibitux |
9
|
|
|
* @license http://www.ibitux.com/license license |
10
|
|
|
* @version XXX |
11
|
|
|
* @link http://www.ibitux.com |
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-2016 Ibitux |
32
|
|
|
* @license http://www.ibitux.com/license license |
33
|
|
|
* @version XXX |
34
|
|
|
* @link http://www.ibitux.com |
35
|
|
|
* @package sweelix\oauth2\server\controllers |
36
|
|
|
* @since XXX |
37
|
|
|
*/ |
38
|
|
|
class AuthorizeController extends Controller |
39
|
|
|
{ |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @inheritdoc |
43
|
|
|
*/ |
44
|
9 |
|
public function behaviors() |
45
|
|
|
{ |
46
|
9 |
|
$behaviors = parent::behaviors(); |
47
|
9 |
|
$behaviors['access'] = [ |
48
|
9 |
|
'class' => AccessControl::className(), |
49
|
9 |
|
'only' => ['authorize'], |
50
|
|
|
'rules' => [ |
51
|
|
|
[ |
52
|
9 |
|
'allow' => true, |
53
|
9 |
|
'actions' => ['authorize'], |
54
|
9 |
|
'roles' => ['@'], |
55
|
9 |
|
], |
56
|
9 |
|
], |
57
|
|
|
]; |
58
|
9 |
|
return $behaviors; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Send back an oauth token |
63
|
|
|
* @return Response |
64
|
|
|
* @since XXX |
65
|
|
|
*/ |
66
|
8 |
|
public function actionIndex() |
67
|
|
|
{ |
68
|
8 |
|
Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
69
|
8 |
|
$oauthServer = Yii::createObject('OAuth2\Server'); |
70
|
|
|
/* @var \Oauth2\Server $oauthServer */ |
71
|
8 |
|
$status = false; |
72
|
8 |
|
$oauthRequest = OAuth2Request::createFromGlobals(); |
73
|
8 |
|
$oauthResponse = new OAuth2Response(); |
74
|
8 |
|
$grantType = Yii::$app->request->getQueryParam('response_type'); |
75
|
|
|
switch ($grantType) { |
76
|
|
|
// Authorization Code |
77
|
8 |
|
case 'code': |
78
|
4 |
|
if (Module::getInstance()->allowAuthorizationCode === true) { |
79
|
3 |
|
$oauthGrantType = Yii::createObject('OAuth2\GrantType\AuthorizationCode'); |
80
|
|
|
/* @var \OAuth2\GrantType\AuthorizationCode $oauthGrantType */ |
81
|
3 |
|
$oauthServer->addGrantType($oauthGrantType); |
82
|
3 |
|
$status = $oauthServer->validateAuthorizeRequest($oauthRequest, $oauthResponse); |
83
|
3 |
|
$error = $oauthResponse->getParameters(); |
84
|
3 |
|
if (($status === false) && (empty($error) === false)) { |
85
|
1 |
|
Yii::$app->session->setFlash('error', $error, false); |
86
|
|
|
// return $this->redirect(['error']); |
|
|
|
|
87
|
1 |
|
} |
88
|
3 |
|
} else { |
89
|
1 |
|
$status = false; |
90
|
1 |
|
Yii::$app->session->setFlash('error', ['error' => 'invalid_grant', 'error_description' => 'authorization code grant is not supported'], false); |
91
|
|
|
} |
92
|
4 |
|
break; |
93
|
|
|
// Implicit |
94
|
4 |
|
case 'token': |
95
|
4 |
|
$status = $oauthServer->validateAuthorizeRequest($oauthRequest, $oauthResponse); |
96
|
4 |
|
$error = $oauthResponse->getParameters(); |
97
|
4 |
|
if (($status === false) && (empty($error) === false)) { |
98
|
2 |
|
Yii::$app->session->setFlash('error', $error, false); |
99
|
|
|
// return $this->redirect(['error']); |
|
|
|
|
100
|
2 |
|
} |
101
|
4 |
|
break; |
102
|
|
|
} |
103
|
|
|
|
104
|
8 |
|
if ($status === true) { |
105
|
4 |
|
Yii::$app->session->set('oauthServer', $oauthServer); |
106
|
4 |
|
if (isset($oauthRequest) === true) { |
107
|
4 |
|
Yii::$app->session->set('oauthRequest', $oauthRequest); |
108
|
4 |
|
} |
109
|
4 |
|
if (Yii::$app->user->isGuest === true) { |
110
|
4 |
|
$response = $this->redirect(['login']); |
111
|
4 |
|
} else { |
112
|
1 |
|
$response = $this->redirect(['authorize']); |
113
|
|
|
} |
114
|
4 |
|
} else { |
115
|
|
|
//TODO: check if we should redirect to specific url with an error |
116
|
4 |
|
$response = $this->redirect(['error']); |
117
|
|
|
} |
118
|
8 |
|
return $response; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Display login page |
123
|
|
|
* @return Response|string |
124
|
|
|
* @since XXX |
125
|
|
|
*/ |
126
|
5 |
|
public function actionLogin() |
127
|
|
|
{ |
128
|
5 |
|
Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
129
|
|
|
|
130
|
5 |
|
$oauthServer = Yii::$app->session->get('oauthServer'); |
131
|
|
|
/* @var \Oauth2\Server $oauthServer */ |
132
|
5 |
|
if ($oauthServer === null) { |
133
|
1 |
|
Yii::$app->session->setFlash('error', [ |
134
|
1 |
|
'error' => 'request_invalid', |
135
|
1 |
|
'error_description' => 'The request was not performed as expected.', |
136
|
1 |
|
], false); |
137
|
1 |
|
return $this->redirect(['error']); |
138
|
|
|
} |
139
|
|
|
|
140
|
4 |
|
$userForm = Yii::createObject('sweelix\oauth2\server\forms\User'); |
141
|
4 |
|
$response = null; |
142
|
|
|
/* @var \sweelix\oauth2\server\forms\User $userForm */ |
143
|
4 |
|
if (Yii::$app->request->isPost === true) { |
144
|
|
|
//TODO: handle case when user decline the grants |
145
|
4 |
|
$userForm->load(Yii::$app->request->bodyParams); |
146
|
5 |
|
if ($userForm->validate() === true) { |
147
|
4 |
|
$userClass = $this->getUserClass(); |
148
|
4 |
|
$realUser = $userClass::findByUsernameAndPassword($userForm->username, $userForm->password); |
149
|
|
|
/* @var \sweelix\oauth2\server\interfaces\UserModelInterface $realUser */ |
150
|
4 |
|
if ($realUser !== null) { |
151
|
4 |
|
Yii::$app->user->login($realUser, Module::getInstance()->loginDuration); |
152
|
4 |
|
$response = $this->redirect(['authorize']); |
153
|
4 |
|
} else { |
154
|
2 |
|
$userForm->addError('username'); |
155
|
|
|
} |
156
|
4 |
|
} |
157
|
4 |
|
} |
158
|
4 |
|
if ($response === null) { |
159
|
|
|
// force empty password |
160
|
4 |
|
$userForm->password = ''; |
161
|
4 |
|
$response = $this->render('login', [ |
162
|
4 |
|
'user' => $userForm, |
163
|
4 |
|
]); |
164
|
4 |
|
} |
165
|
4 |
|
return $response; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Display authorize page |
170
|
|
|
* @return string|Response |
171
|
|
|
* @since XXX |
172
|
|
|
*/ |
173
|
4 |
|
public function actionAuthorize() |
174
|
|
|
{ |
175
|
4 |
|
Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
176
|
4 |
|
$oauthServer = Yii::$app->session->get('oauthServer'); |
177
|
|
|
/* @var \Oauth2\Server $oauthServer */ |
178
|
4 |
|
if ($oauthServer === null) { |
179
|
|
|
Yii::$app->session->setFlash('error', [ |
180
|
|
|
'error' => 'request_invalid', |
181
|
|
|
'error_description' => 'The request was not performed as expected.', |
182
|
|
|
], false); |
183
|
|
|
return $this->redirect(['error']); |
184
|
|
|
} |
185
|
4 |
|
$oauthController = $oauthServer->getAuthorizeController(); |
186
|
4 |
|
$client = Client::findOne($oauthController->getClientId()); |
187
|
|
|
|
188
|
4 |
|
if ($client->hasUser(Yii::$app->user->id) === true) { |
189
|
|
|
// already logged |
190
|
1 |
|
$oauthRequest = Yii::$app->session->get('oauthRequest'); |
191
|
1 |
|
$oauthResponse = new OAuth2Response(); |
192
|
1 |
|
$oauthResponse = $oauthServer->handleAuthorizeRequest($oauthRequest, $oauthResponse, true, Yii::$app->user->id); |
193
|
|
|
/* @var OAuth2Response $oauthResponse */ |
194
|
1 |
|
Yii::$app->session->remove('oauthServer'); |
195
|
1 |
|
Yii::$app->session->remove('oauthRequest'); |
196
|
1 |
|
$error = $oauthResponse->getParameters(); |
197
|
1 |
|
if (empty($error) === false) { |
198
|
|
|
Yii::$app->session->setFlash('error', $error, false); |
199
|
|
|
return $this->redirect(['error']); |
200
|
|
|
} else { |
201
|
1 |
|
return $this->redirect($oauthResponse->getHttpHeader('Location')); |
202
|
|
|
} |
203
|
|
|
} else { |
204
|
|
|
// perform regular authorization |
205
|
4 |
|
$additionalScopes = $oauthController->getScope(); |
206
|
4 |
|
$requestedScopes = []; |
207
|
4 |
|
if (empty($additionalScopes) === false) { |
208
|
|
|
$additionalScopes = explode(' ', $additionalScopes); |
209
|
|
|
foreach($additionalScopes as $scope) { |
210
|
|
|
$dbScope = Scope::findOne($scope); |
211
|
|
|
if ($dbScope !== null) { |
212
|
|
|
$requestedScopes[] = [ |
213
|
|
|
'id' => $dbScope->id, |
|
|
|
|
214
|
|
|
'description' => $dbScope->definition, |
|
|
|
|
215
|
|
|
]; |
216
|
|
|
} else { |
217
|
|
|
$requestedScopes[] = [ |
218
|
|
|
'id' => $scope, |
219
|
|
|
'description' => null, |
220
|
|
|
]; |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
} |
224
|
4 |
|
if (Yii::$app->request->isPost === true) { |
225
|
4 |
|
$accept = Yii::$app->request->getBodyParam('accept', null); |
226
|
4 |
|
$oauthRequest = Yii::$app->session->get('oauthRequest'); |
227
|
4 |
|
$oauthResponse = new OAuth2Response(); |
228
|
|
|
/* @var OAuth2Response $oauthResponse */ |
229
|
|
|
|
230
|
4 |
|
if ($accept !== null) { |
231
|
2 |
|
$oauthResponse = $oauthServer->handleAuthorizeRequest($oauthRequest, $oauthResponse, true, Yii::$app->user->id); |
232
|
2 |
|
$client->addUser(Yii::$app->user->id); |
233
|
|
|
// authorize |
234
|
2 |
|
} else { |
235
|
2 |
|
$oauthResponse = $oauthServer->handleAuthorizeRequest($oauthRequest, $oauthResponse, false, Yii::$app->user->id); |
236
|
2 |
|
$client->removeUser(Yii::$app->user->id); |
237
|
|
|
// decline |
238
|
|
|
} |
239
|
|
|
|
240
|
4 |
|
Yii::$app->session->remove('oauthServer'); |
241
|
4 |
|
Yii::$app->session->remove('oauthRequest'); |
242
|
4 |
|
$error = $oauthResponse->getParameters(); |
|
|
|
|
243
|
4 |
|
$redirect = $oauthResponse->getHttpHeader('Location'); |
244
|
4 |
|
if ((empty($error) === false) && ($redirect === null)) { |
245
|
|
|
Yii::$app->session->setFlash('error', $error, false); |
246
|
|
|
return $this->redirect(['error']); |
247
|
|
|
} else { |
248
|
4 |
|
return $this->redirect($redirect); |
249
|
|
|
} |
250
|
|
|
} |
251
|
|
|
} |
252
|
|
|
|
253
|
4 |
|
return $this->render('authorize', [ |
254
|
4 |
|
'client' => $client, |
255
|
4 |
|
'requestedScopes' => $requestedScopes, |
256
|
4 |
|
]); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* Display an error page |
261
|
|
|
* @return Response|string |
262
|
|
|
* @since XXX |
263
|
|
|
*/ |
264
|
5 |
|
public function actionError() |
265
|
|
|
{ |
266
|
5 |
|
Yii::$app->response->headers->add('Content-Security-Policy', 'frame-ancestors \'none\';'); |
267
|
5 |
|
$errorData = Yii::$app->session->getFlash('error'); |
268
|
5 |
|
return $this->render('error', [ |
269
|
5 |
|
'type' => (isset($errorData['error']) ? $errorData['error'] : null), |
270
|
5 |
|
'description' => (isset($errorData['error_description']) ? $errorData['error_description'] : null), |
271
|
5 |
|
]); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* @var string |
276
|
|
|
*/ |
277
|
|
|
private $userClass; |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* @return string classname for selected interface |
281
|
|
|
* @since XXX |
282
|
|
|
*/ |
283
|
4 |
|
public function getUserClass() |
284
|
|
|
{ |
285
|
4 |
|
if ($this->userClass === null) { |
286
|
4 |
|
$scope = Yii::createObject('sweelix\oauth2\server\interfaces\UserModelInterface'); |
287
|
4 |
|
$this->userClass = get_class($scope); |
288
|
4 |
|
} |
289
|
4 |
|
return $this->userClass; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
|
293
|
|
|
|
294
|
|
|
} |
295
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.