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

Memory::isPublicClient()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
namespace OAuth2\Storage;
4
5
use OAuth2\OpenID\Storage\UserClaimsInterface;
6
use OAuth2\OpenID\Storage\AuthorizationCodeInterface as OpenIDAuthorizationCodeInterface;
7
8
/**
9
 * Simple in-memory storage for all storage types
10
 *
11
 * NOTE: This class should never be used in production, and is
12
 * a stub class for example use only
13
 *
14
 * @author Brent Shaffer <bshafs at gmail dot com>
15
 */
16
class Memory implements AuthorizationCodeInterface,
17
    UserCredentialsInterface,
18
    UserClaimsInterface,
19
    AccessTokenInterface,
20
    ClientCredentialsInterface,
21
    RefreshTokenInterface,
22
    JwtBearerInterface,
23
    ScopeInterface,
24
    PublicKeyInterface,
25
    OpenIDAuthorizationCodeInterface
26
{
27
    public $authorizationCodes;
28
    public $userCredentials;
29
    public $clientCredentials;
30
    public $refreshTokens;
31
    public $accessTokens;
32
    public $jwt;
33
    public $jti;
34
    public $supportedScopes;
35
    public $defaultScope;
36
    public $keys;
37
38
    public function __construct($params = array())
39
    {
40
        $params = array_merge(array(
41
            'authorization_codes' => array(),
42
            'user_credentials' => array(),
43
            'client_credentials' => array(),
44
            'refresh_tokens' => array(),
45
            'access_tokens' => array(),
46
            'jwt' => array(),
47
            'jti' => array(),
48
            'default_scope' => null,
49
            'supported_scopes' => array(),
50
            'keys' => array(),
51
        ), $params);
52
53
        $this->authorizationCodes = $params['authorization_codes'];
54
        $this->userCredentials = $params['user_credentials'];
55
        $this->clientCredentials = $params['client_credentials'];
56
        $this->refreshTokens = $params['refresh_tokens'];
57
        $this->accessTokens = $params['access_tokens'];
58
        $this->jwt = $params['jwt'];
59
        $this->jti = $params['jti'];
60
        $this->supportedScopes = $params['supported_scopes'];
61
        $this->defaultScope = $params['default_scope'];
62
        $this->keys = $params['keys'];
63
    }
64
65
    /* AuthorizationCodeInterface */
66
    public function getAuthorizationCode($code)
67
    {
68
        if (!isset($this->authorizationCodes[$code])) {
69
            return false;
70
        }
71
72
        return array_merge(array(
73
            'authorization_code' => $code,
74
        ), $this->authorizationCodes[$code]);
75
    }
76
77
    public function setAuthorizationCode($code, $client_id, $user_id, $redirect_uri, $expires, $scope = null, $id_token = null)
78
    {
79
        $this->authorizationCodes[$code] = compact('code', 'client_id', 'user_id', 'redirect_uri', 'expires', 'scope', 'id_token');
80
81
        return true;
82
    }
83
84
    public function setAuthorizationCodes($authorization_codes)
85
    {
86
        $this->authorizationCodes = $authorization_codes;
87
    }
88
89
    public function expireAuthorizationCode($code)
90
    {
91
        unset($this->authorizationCodes[$code]);
92
    }
93
94
    /* UserCredentialsInterface */
95
    public function checkUserCredentials($username, $password)
96
    {
97
        $userDetails = $this->getUserDetails($username);
98
99
        return $userDetails && $userDetails['password'] && $userDetails['password'] === $password;
100
    }
101
102
    public function setUser($username, $password, $firstName = null, $lastName = null)
103
    {
104
        $this->userCredentials[$username] = array(
105
            'password'   => $password,
106
            'first_name' => $firstName,
107
            'last_name'  => $lastName,
108
        );
109
110
        return true;
111
    }
112
113
    public function getUserDetails($username)
114
    {
115
        if (!isset($this->userCredentials[$username])) {
116
            return false;
117
        }
118
119
        return array_merge(array(
120
            'user_id'    => $username,
121
            'password'   => null,
122
            'first_name' => null,
123
            'last_name'  => null,
124
        ), $this->userCredentials[$username]);
125
    }
126
127
    /* UserClaimsInterface */
128
    public function getUserClaims($user_id, $claims)
129
    {
130
        if (!$userDetails = $this->getUserDetails($user_id)) {
131
            return false;
132
        }
133
134
        $claims = explode(' ', trim($claims));
135
        $userClaims = array();
136
137
        // for each requested claim, if the user has the claim, set it in the response
138
        $validClaims = explode(' ', self::VALID_CLAIMS);
139
        foreach ($validClaims as $validClaim) {
140
            if (in_array($validClaim, $claims)) {
141
                if ($validClaim == 'address') {
142
                    // address is an object with subfields
143
                    $userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails);
144
                } else {
145
                    $userClaims = array_merge($this->getUserClaim($validClaim, $userDetails));
146
                }
147
            }
148
        }
149
150
        return $userClaims;
151
    }
152
153
    protected function getUserClaim($claim, $userDetails)
154
    {
155
        $userClaims = array();
156
        $claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim)));
157
        $claimValues = explode(' ', $claimValuesString);
158
159
        foreach ($claimValues as $value) {
160
            $userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null;
161
        }
162
163
        return $userClaims;
164
    }
165
166
    /* ClientCredentialsInterface */
167
    public function checkClientCredentials($client_id, $client_secret = null)
168
    {
169
        return isset($this->clientCredentials[$client_id]['client_secret']) && $this->clientCredentials[$client_id]['client_secret'] === $client_secret;
170
    }
171
172
    public function isPublicClient($client_id)
173
    {
174
        if (!isset($this->clientCredentials[$client_id])) {
175
            return false;
176
        }
177
178
        return empty($this->clientCredentials[$client_id]['client_secret']);
179
    }
180
181
    /* ClientInterface */
182
    public function getClientDetails($client_id)
183
    {
184
        if (!isset($this->clientCredentials[$client_id])) {
185
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by OAuth2\Storage\ClientInterface::getClientDetails() of array.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
186
        }
187
188
        $clientDetails = array_merge(array(
189
            'client_id'     => $client_id,
190
            'client_secret' => null,
191
            'redirect_uri'  => null,
192
            'scope'         => null,
193
        ), $this->clientCredentials[$client_id]);
194
195
        return $clientDetails;
196
    }
197
198
    public function checkRestrictedGrantType($client_id, $grant_type)
199
    {
200
        if (isset($this->clientCredentials[$client_id]['grant_types'])) {
201
            $grant_types = explode(' ', $this->clientCredentials[$client_id]['grant_types']);
202
203
            return in_array($grant_type, $grant_types);
204
        }
205
206
        // if grant_types are not defined, then none are restricted
207
        return true;
208
    }
209
210
    public function setClientDetails($client_id, $client_secret = null, $redirect_uri = null, $grant_types = null, $scope = null, $user_id = null)
211
    {
212
        $this->clientCredentials[$client_id] = array(
213
            'client_id'     => $client_id,
214
            'client_secret' => $client_secret,
215
            'redirect_uri'  => $redirect_uri,
216
            'grant_types'   => $grant_types,
217
            'scope'         => $scope,
218
            'user_id'       => $user_id,
219
        );
220
221
        return true;
222
    }
223
224
    /* RefreshTokenInterface */
225
    public function getRefreshToken($refresh_token)
226
    {
227
        return isset($this->refreshTokens[$refresh_token]) ? $this->refreshTokens[$refresh_token] : false;
228
    }
229
230
    public function setRefreshToken($refresh_token, $client_id, $user_id, $expires, $scope = null)
231
    {
232
        $this->refreshTokens[$refresh_token] = compact('refresh_token', 'client_id', 'user_id', 'expires', 'scope');
233
234
        return true;
235
    }
236
237
    public function unsetRefreshToken($refresh_token)
238
    {
239
        unset($this->refreshTokens[$refresh_token]);
240
    }
241
242
    public function setRefreshTokens($refresh_tokens)
243
    {
244
        $this->refreshTokens = $refresh_tokens;
245
    }
246
247
    /* AccessTokenInterface */
248
    public function getAccessToken($access_token)
249
    {
250
        return isset($this->accessTokens[$access_token]) ? $this->accessTokens[$access_token] : false;
251
    }
252
253
    public function setAccessToken($access_token, $client_id, $user_id, $expires, $scope = null, $id_token = null)
254
    {
255
        $this->accessTokens[$access_token] = compact('access_token', 'client_id', 'user_id', 'expires', 'scope', 'id_token');
256
257
        return true;
258
    }
259
260
    public function unsetAccessToken($access_token)
261
    {
262
        unset($this->accessTokens[$access_token]);
263
    }
264
265
    public function scopeExists($scope)
266
    {
267
        $scope = explode(' ', trim($scope));
268
269
        return (count(array_diff($scope, $this->supportedScopes)) == 0);
270
    }
271
272
    public function getDefaultScope($client_id = null)
273
    {
274
        return $this->defaultScope;
275
    }
276
277
    /*JWTBearerInterface */
278
    public function getClientKey($client_id, $subject)
279
    {
280
        if (isset($this->jwt[$client_id])) {
281
            $jwt = $this->jwt[$client_id];
282
            if ($jwt) {
283
                if ($jwt["subject"] == $subject) {
284
                    return $jwt["key"];
285
                }
286
            }
287
        }
288
289
        return false;
290
    }
291
292
    public function getClientScope($client_id)
293
    {
294
        if (!$clientDetails = $this->getClientDetails($client_id)) {
295
            return false;
296
        }
297
298
        if (isset($clientDetails['scope'])) {
299
            return $clientDetails['scope'];
300
        }
301
302
        return null;
303
    }
304
305
    public function getJti($client_id, $subject, $audience, $expires, $jti)
306
    {
307
        foreach ($this->jti as $storedJti) {
308
            if ($storedJti['issuer'] == $client_id && $storedJti['subject'] == $subject && $storedJti['audience'] == $audience && $storedJti['expires'] == $expires && $storedJti['jti'] == $jti) {
309
                return array(
310
                    'issuer' => $storedJti['issuer'],
311
                    'subject' => $storedJti['subject'],
312
                    'audience' => $storedJti['audience'],
313
                    'expires' => $storedJti['expires'],
314
                    'jti' => $storedJti['jti']
315
                );
316
            }
317
        }
318
319
        return null;
320
    }
321
322
    public function setJti($client_id, $subject, $audience, $expires, $jti)
323
    {
324
        $this->jti[] = array('issuer' => $client_id, 'subject' => $subject, 'audience' => $audience, 'expires' => $expires, 'jti' => $jti);
325
    }
326
327
    /*PublicKeyInterface */
328
    public function getPublicKey($client_id = null)
329
    {
330
        if (isset($this->keys[$client_id])) {
331
            return $this->keys[$client_id]['public_key'];
332
        }
333
334
        // use a global encryption pair
335
        if (isset($this->keys['public_key'])) {
336
            return $this->keys['public_key'];
337
        }
338
339
        return false;
340
    }
341
342
    public function getPrivateKey($client_id = null)
343
    {
344
        if (isset($this->keys[$client_id])) {
345
            return $this->keys[$client_id]['private_key'];
346
        }
347
348
        // use a global encryption pair
349
        if (isset($this->keys['private_key'])) {
350
            return $this->keys['private_key'];
351
        }
352
353
        return false;
354
    }
355
356
    public function getEncryptionAlgorithm($client_id = null)
357
    {
358
        if (isset($this->keys[$client_id]['encryption_algorithm'])) {
359
            return $this->keys[$client_id]['encryption_algorithm'];
360
        }
361
362
        // use a global encryption algorithm
363
        if (isset($this->keys['encryption_algorithm'])) {
364
            return $this->keys['encryption_algorithm'];
365
        }
366
367
        return 'RS256';
368
    }
369
}
370