|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
/** |
|
6
|
|
|
* balloon |
|
7
|
|
|
* |
|
8
|
|
|
* @copyright Copryright (c) 2012-2019 gyselroth GmbH (https://gyselroth.com) |
|
9
|
|
|
* @license GPL-3.0 https://opensource.org/licenses/GPL-3.0 |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
namespace Balloon\App\Idp\Storage; |
|
13
|
|
|
|
|
14
|
|
|
use Balloon\App\Idp\Exception\MultiFactorAuthenticationRequired; |
|
15
|
|
|
use Balloon\Hook; |
|
16
|
|
|
use Balloon\Server; |
|
17
|
|
|
use Balloon\Server\User; |
|
18
|
|
|
use Micro\Auth\Adapter\Basic\BasicInterface; |
|
19
|
|
|
use Micro\Auth\Auth; |
|
20
|
|
|
use MongoDB\BSON\UTCDateTime; |
|
21
|
|
|
use MongoDB\Database; |
|
22
|
|
|
use OAuth2\Storage\MongoDB as OAuthMongoDB; |
|
23
|
|
|
use Psr\Log\LoggerInterface; |
|
24
|
|
|
|
|
25
|
|
|
class Db extends OAuthMongoDB |
|
26
|
|
|
{ |
|
27
|
|
|
/** |
|
28
|
|
|
* Auth. |
|
29
|
|
|
* |
|
30
|
|
|
* @var Auth |
|
31
|
|
|
*/ |
|
32
|
|
|
protected $auth; |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Hook. |
|
36
|
|
|
* |
|
37
|
|
|
* @var Hook |
|
38
|
|
|
*/ |
|
39
|
|
|
protected $hook; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* Logger. |
|
43
|
|
|
* |
|
44
|
|
|
* @var LoggerInterface |
|
45
|
|
|
*/ |
|
46
|
|
|
protected $logger; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* Server. |
|
50
|
|
|
* |
|
51
|
|
|
* @var Server |
|
52
|
|
|
*/ |
|
53
|
|
|
protected $server; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* Last adapter. |
|
57
|
|
|
* |
|
58
|
|
|
* @var string |
|
59
|
|
|
*/ |
|
60
|
|
|
protected $adapter; |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* {@inheritdoc} |
|
64
|
|
|
*/ |
|
65
|
|
|
public function __construct(Database $db, Auth $auth, Hook $hook, Server $server, LoggerInterface $logger, array $config = []) |
|
66
|
|
|
{ |
|
67
|
|
|
$this->server = $server; |
|
68
|
|
|
$this->auth = $auth; |
|
69
|
|
|
$this->hook = $hook; |
|
70
|
|
|
$this->logger = $logger; |
|
71
|
|
|
|
|
72
|
|
|
parent::__construct($db, $config); |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* {@inheritdoc} |
|
77
|
|
|
*/ |
|
78
|
|
|
public function checkUserCredentials($username, $password) |
|
79
|
|
|
{ |
|
80
|
|
|
foreach ($this->auth->getAdapters() as $name => $adapter) { |
|
81
|
|
|
if ($adapter instanceof BasicInterface) { |
|
|
|
|
|
|
82
|
|
|
try { |
|
83
|
|
|
if ($adapter->plainAuth($username, $password) === true) { |
|
84
|
|
|
$user = null; |
|
85
|
|
|
$identity = $this->auth->createIdentity($adapter); |
|
86
|
|
|
|
|
87
|
|
|
try { |
|
88
|
|
|
$user = $this->server->getUserByName($username); |
|
89
|
|
|
} catch (User\Exception\NotFound $e) { |
|
90
|
|
|
$this->logger->warning('failed connect authenticated user, user account does not exists', [ |
|
91
|
|
|
'category' => get_class($this), |
|
92
|
|
|
]); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
$this->hook->run('preServerIdentity', [$identity, &$user]); |
|
96
|
|
|
|
|
97
|
|
|
if (!($user instanceof User)) { |
|
98
|
|
|
throw new User\Exception\NotAuthenticated('user does not exists', User\Exception\NotAuthenticated::USER_NOT_FOUND); |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
|
|
if ($user->isDeleted()) { |
|
102
|
|
|
throw new User\Exception\NotAuthenticated( |
|
103
|
|
|
'user is disabled and can not be used', |
|
104
|
|
|
User\Exception\NotAuthenticated::USER_DELETED |
|
105
|
|
|
); |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
$this->adapter = $name; |
|
|
|
|
|
|
109
|
|
|
|
|
110
|
|
|
return true; |
|
111
|
|
|
} |
|
112
|
|
|
} catch (MultiFactorAuthenticationRequired $e) { |
|
113
|
|
|
throw $e; |
|
114
|
|
|
} catch (\Exception $e) { |
|
115
|
|
|
$this->logger->error('failed authenticate user, unexcepted exception was thrown', [ |
|
116
|
|
|
'category' => get_class($this), |
|
117
|
|
|
'exception' => $e, |
|
118
|
|
|
]); |
|
119
|
|
|
} |
|
120
|
|
|
} |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
return false; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* {@inheritdoc} |
|
128
|
|
|
*/ |
|
129
|
|
|
public function getUser($username) |
|
130
|
|
|
{ |
|
131
|
|
|
try { |
|
132
|
|
|
return $this->server->getUserByName($username) |
|
133
|
|
|
->getAttributes(); |
|
134
|
|
|
} catch (User\Exception\NotFound $e) { |
|
135
|
|
|
$this->logger->warning('failed connect authenticated user, user account does not exists', [ |
|
136
|
|
|
'category' => get_class($this), |
|
137
|
|
|
]); |
|
138
|
|
|
|
|
139
|
|
|
return false; |
|
140
|
|
|
} |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
/** |
|
144
|
|
|
* {@inheritdoc} |
|
145
|
|
|
*/ |
|
146
|
|
|
public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null) |
|
147
|
|
|
{ |
|
148
|
|
|
if ($expires === 0) { |
|
149
|
|
|
$expires = null; |
|
150
|
|
|
} else { |
|
151
|
|
|
$expires = new UTCDateTime($expires * 1000); |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
$token = [ |
|
155
|
|
|
'access_token' => $access_token, |
|
156
|
|
|
'client_id' => $client_id, |
|
157
|
|
|
'expires' => $expires, |
|
158
|
|
|
'user_id' => $user_id, |
|
159
|
|
|
'scope' => $scope, |
|
160
|
|
|
'adapter' => $this->adapter, |
|
161
|
|
|
]; |
|
162
|
|
|
|
|
163
|
|
|
if ($this->getAccessToken($access_token)) { |
|
164
|
|
|
$result = $this->collection('access_token_table')->updateOne( |
|
165
|
|
|
['access_token' => $access_token], |
|
166
|
|
|
['$set' => $token] |
|
167
|
|
|
); |
|
168
|
|
|
|
|
169
|
|
|
return $result->getMatchedCount() > 0; |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
$result = $this->collection('access_token_table')->insertOne($token); |
|
173
|
|
|
|
|
174
|
|
|
return $result->getInsertedCount() > 0; |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
/** |
|
178
|
|
|
* {@inheritdoc} |
|
179
|
|
|
*/ |
|
180
|
|
View Code Duplication |
public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null) |
|
|
|
|
|
|
181
|
|
|
{ |
|
182
|
|
|
if ($expires === 0) { |
|
183
|
|
|
$expires = null; |
|
184
|
|
|
} else { |
|
185
|
|
|
$expires = new UTCDateTime($expires * 1000); |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
return parent::setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope, $id_token); |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* {@inheritdoc} |
|
193
|
|
|
*/ |
|
194
|
|
View Code Duplication |
public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null) |
|
|
|
|
|
|
195
|
|
|
{ |
|
196
|
|
|
if ($expires === 0) { |
|
197
|
|
|
$expires = null; |
|
198
|
|
|
} else { |
|
199
|
|
|
$expires = new UTCDateTime($expires * 1000); |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
return parent::setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope); |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
/** |
|
206
|
|
|
* {@inheritdoc} |
|
207
|
|
|
*/ |
|
208
|
|
View Code Duplication |
public function getAccessToken($access_token) |
|
|
|
|
|
|
209
|
|
|
{ |
|
210
|
|
|
$token = $this->collection('access_token_table')->findOne(['access_token' => $access_token]); |
|
211
|
|
|
|
|
212
|
|
|
if ($token === null) { |
|
213
|
|
|
return false; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
if ($token['expires'] !== null) { |
|
217
|
|
|
$token['expires'] = $token['expires']->toDateTime()->format('U'); |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
return $token; |
|
221
|
|
|
} |
|
222
|
|
|
|
|
223
|
|
|
/** |
|
224
|
|
|
* {@inheritdoc} |
|
225
|
|
|
*/ |
|
226
|
|
View Code Duplication |
public function getAuthorizationCode($code) |
|
|
|
|
|
|
227
|
|
|
{ |
|
228
|
|
|
$code = $this->collection('code_table')->findOne([ |
|
229
|
|
|
'authorization_code' => $code, |
|
230
|
|
|
]); |
|
231
|
|
|
|
|
232
|
|
|
if ($code === null) { |
|
233
|
|
|
return false; |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
|
|
if ($code['expires'] !== null) { |
|
237
|
|
|
$code['expires'] = $code['expires']->toDateTime()->format('U'); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
return $code; |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
/** |
|
244
|
|
|
* {@inheritdoc} |
|
245
|
|
|
*/ |
|
246
|
|
View Code Duplication |
public function getRefreshToken($refresh_token) |
|
|
|
|
|
|
247
|
|
|
{ |
|
248
|
|
|
$token = $this->collection('refresh_token_table')->findOne(['refresh_token' => $refresh_token]); |
|
249
|
|
|
|
|
250
|
|
|
if ($token === null) { |
|
251
|
|
|
return false; |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
if ($token['expires'] !== null) { |
|
255
|
|
|
$token['expires'] = $token['expires']->toDateTime()->format('U'); |
|
256
|
|
|
} |
|
257
|
|
|
|
|
258
|
|
|
return $token; |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.jsonfile (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.jsonto be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
requireorrequire-devsection?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceofchecks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.