Completed
Pull Request — develop (#816)
by Kristijan
07:28
created

Mongo::collection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
namespace OAuth2\Storage;
4
5
use OAuth2\OpenID\Storage\AuthorizationCodeInterface as OpenIDAuthorizationCodeInterface;
6
7
/**
8
 * Simple MongoDB storage for all storage types
9
 *
10
 * NOTE: This class is meant to get users started
11
 * quickly. If your application requires further
12
 * customization, extend this class or create your own.
13
 *
14
 * NOTE: Passwords are stored in plaintext, which is never
15
 * a good idea.  Be sure to override this for your application
16
 *
17
 * @author Julien Chaumond <[email protected]>
18
 */
19
class Mongo implements AuthorizationCodeInterface,
20
    AccessTokenInterface,
21
    ClientCredentialsInterface,
22
    UserCredentialsInterface,
23
    RefreshTokenInterface,
24
    JwtBearerInterface,
25
    OpenIDAuthorizationCodeInterface
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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_null($result) ? false : $result also could return the type false which is incompatible with the return type mandated by OAuth2\Storage\ClientInterface::getClientDetails() of array.
Loading history...
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
}
334