Passed
Push — master ( 89971b...1a5c63 )
by Vince
01:47
created

jwtValidate   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 331
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 124
c 5
b 0
f 0
dl 0
loc 331
rs 5.04
wmc 57

15 Methods

Rating   Name   Duplication   Size   Complexity  
A payload() 0 17 3
A header() 0 11 4
A signature() 0 28 6
A nbf() 0 17 5
A exp() 0 17 5
A leeway() 0 3 1
A typ() 0 8 4
B sub() 0 33 8
A isAnonymousScope() 0 3 2
A alg() 0 12 5
A algorithm() 0 6 2
A iss() 0 17 5
A iat() 0 17 5
A timestamp() 0 3 1
A getTimestamp() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like jwtValidate often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use jwtValidate, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * ==================================
4
 * Responsible PHP API
5
 * ==================================
6
 *
7
 * @link Git https://github.com/vince-scarpa/responsibleAPI.git
8
 *
9
 * @api Responible API
10
 * @package responsible\core\oauth
11
 *
12
 * @author Vince scarpa <[email protected]>
13
 *
14
 */
15
namespace responsible\core\auth;
16
17
use responsible\core\server;
18
use responsible\core\encoder;
19
use responsible\core\exception;
20
use responsible\core\route;
21
use responsible\core\user;
22
23
class jwtValidate extends jwt
24
{
25
    /**
26
     * [$TIMESTAMP]
27
     * @var int
28
     */
29
    protected static $TIMESTAMP;
30
31
    /**
32
     * [$LEEWAY]
33
     * @var int
34
     */
35
    protected static $LEEWAY = 0;
36
37
    /**
38
     * [$ALGORITHM]
39
     * @var string
40
     */
41
    private static $ALGORITHM;
42
43
    /**
44
     * [$isPayloadValid Validation placeholders]
45
     * @var array
46
     */
47
    protected static $isPayloadValid = [
48
        "iss" => false,
49
        "sub" => false,
50
        "iat" => false,
51
        "nbf" => false,
52
        "exp" => false,
53
    ];
54
55
    /**
56
     * [header Validate the header object]
57
     * First segment of the token
58
     * @return bool
59
     */
60
    public static function header(array $headObject = [])
61
    {
62
        if (
63
            empty($headObject) ||
64
            !self::typ($headObject) ||
65
            !self::alg($headObject)
66
        ) {
67
            (new exception\errorException)
68
                ->setOptions(parent::$options)
69
                ->message(self::messages('denied_token'))
70
                ->error('UNAUTHORIZED');
71
        }
72
    }
73
74
    /**
75
     * [payload Validate the payload object]
76
     * Second segment of the token
77
     * @return bool
78
     */
79
    public static function payload(array $payloadObject = [])
80
    {
81
        if( self::isAnonymousScope($payloadObject) ) {
82
            return true;
83
        }
84
85
        self::iss($payloadObject);
86
        self::sub($payloadObject);
87
        self::iat($payloadObject);
88
        self::nbf($payloadObject);
89
        self::exp($payloadObject);
90
91
        if ((true === in_array(false, self::$isPayloadValid))) {
92
            (new exception\errorException)
93
                ->setOptions(parent::$options)
94
                ->message(self::messages('denied_token'))
95
                ->error('UNAUTHORIZED');
96
        }
97
    }
98
99
    /**
100
     * Check if the scope is anonymous
101
     * @return boolean
102
     */
103
    private static function isAnonymousScope($payloadObject)
104
    {
105
        return (isset($payloadObject['scope']) && $payloadObject['scope'] == 'anonymous');
106
    }
107
108
    /**
109
     * [signature - Validate the signature object]
110
     * Third segment of the token
111
     * @return bool
112
     */
113
    public static function signature($jwtHead, $jwtPayload, $signature, $key)
114
    {
115
        if (empty($jwtHead) ||
116
            empty($jwtPayload) ||
117
            empty($signature) ||
118
            empty($key)
119
        ) {
120
            (new exception\errorException)
121
                ->setOptions(parent::$options)
122
                ->message(self::messages('denied_token'))
123
                ->error('UNAUTHORIZED');
124
        }
125
126
        $cipher = new encoder\cipher;
127
128
        $hashed = $cipher->encode(
129
            $cipher->hash(
130
                self::$ALGORITHM,
131
                $jwtHead . '.' . $jwtPayload,
132
                $key
133
            )
134
        );
135
136
        if (!$cipher->hashCompare($signature, $hashed)) {
137
            (new exception\errorException)
138
                ->setOptions(parent::$options)
139
                ->message(self::messages('denied_token'))
140
                ->error('UNAUTHORIZED');
141
        }
142
    }
143
144
    /**
145
     * [typ Issuer claim]
146
     *
147
     * @return bool
148
     */
149
    public static function typ($headObject)
150
    {
151
        if (!isset($headObject['typ']) ||
152
            (isset($headObject['typ']) && empty($headObject))
153
        ) {
154
            return;
155
        }
156
        return true;
157
    }
158
159
    /**
160
     * [alg Issuer claim]
161
     *
162
     * @return bool
163
     */
164
    public static function alg($headObject)
165
    {
166
        if (!isset($headObject['alg']) ||
167
            (isset($headObject['alg']) && empty($headObject)) &&
168
            self::getAlgorithm($headObject['alg'])
169
        ) {
170
            return;
171
        }
172
173
        self::algorithm($headObject['alg']);
174
175
        return true;
176
    }
177
178
    /**
179
     * [iss Issuer claim]
180
     *
181
     * @return bool
182
     */
183
    public static function iss($payloadObject)
184
    {
185
        if (!isset($payloadObject['iss']) ||
186
            (isset($payloadObject['iss']) && empty($payloadObject))
187
        ) {
188
            return;
189
        }
190
191
        $router = new route\router;
192
        $router->route();
193
194
        if ($payloadObject['iss'] !== $router->getIssuer(true)) {
195
            return;
196
        }
197
198
        self::$isPayloadValid['iss'] = true;
199
        return true;
200
    }
201
202
    /**
203
     * [sub Subject claim]
204
     * The Responsible API uses the "Subject" claim as a placeholder for account Ids
205
     *
206
     * @return bool
207
     */
208
    public static function sub($payloadObject)
209
    {
210
        $server = new server([], parent::$options);
211
        if ($server->isMockTest()) {
212
            self::$isPayloadValid['sub'] = true;
213
            return true;
214
        }
215
216
        if (!isset($payloadObject['sub']) ||
217
            (isset($payloadObject['sub']) && empty($payloadObject))
218
        ) {
219
            return;
220
        }
221
222
        $account = (object) (new user\user)
223
            ->setOptions(parent::$options)
224
            ->load($payloadObject['sub'], ['refreshToken' => false])
225
        ;
226
227
        if (empty($account)) {
228
            return;
229
        } else {
230
            if (!isset($account->account_id)) {
231
                return;
232
            }
233
234
            if ((int) $account->account_id !== (int) $payloadObject['sub']) {
235
                return;
236
            }
237
        }
238
239
        self::$isPayloadValid['sub'] = true;
240
        return true;
241
    }
242
243
    /**
244
     * [iat Issued at claim]
245
     *
246
     * @return bool
247
     */
248
    public static function iat($payloadObject)
249
    {
250
        if (!isset($payloadObject['iat']) ||
251
            (isset($payloadObject['iat']) && empty($payloadObject))
252
        ) {
253
            return;
254
        }
255
256
        if ($payloadObject['iat'] > self::getTimestamp()) {
257
            (new exception\errorException)
258
                ->setOptions(parent::$options)
259
                ->message(self::messages('not_ready'))
260
                ->error('NO_CONTENT');
261
        }
262
263
        self::$isPayloadValid['iat'] = true;
264
        return true;
265
    }
266
267
    /**
268
     * [nbf Not before claim]
269
     *
270
     * @return bool
271
     */
272
    public static function nbf($payloadObject)
273
    {
274
        if (!isset($payloadObject['nbf']) ||
275
            (isset($payloadObject['nbf']) && empty($payloadObject))
276
        ) {
277
            return;
278
        }
279
280
        if ($payloadObject['nbf'] > self::getTimestamp()) {
281
            (new exception\errorException)
282
                ->setOptions(parent::$options)
283
                ->message(self::messages('not_ready'))
284
                ->error('NO_CONTENT');
285
        }
286
287
        self::$isPayloadValid['nbf'] = true;
288
        return true;
289
    }
290
291
    /**
292
     * [exp Expiration claim this optional so if its not set return true]
293
     *
294
     * @return bool
295
     */
296
    public static function exp($payloadObject)
297
    {
298
        if (!isset($payloadObject['exp']) ||
299
            (isset($payloadObject['exp']) && empty($payloadObject))
300
        ) {
301
            return;
302
        }
303
304
        if ($payloadObject['exp'] <= (int) (self::$TIMESTAMP - self::$LEEWAY)) {
305
            (new exception\errorException)
306
                ->setOptions(parent::$options)
307
                ->message(self::messages('expired'))
308
                ->error('UNAUTHORIZED');
309
        }
310
311
        self::$isPayloadValid['exp'] = true;
312
        return true;
313
    }
314
315
    /**
316
     * [leeway Inherit the leeway offset]
317
     * @param  int $leeway [integer in seconds]
318
     * @return void
319
     */
320
    public static function leeway($leeway)
321
    {
322
        self::$LEEWAY = $leeway;
323
    }
324
325
    /**
326
     * [timestamp Inherit the current timestamp (now)]
327
     * @param  int $timestamp [integer in seconds]
328
     * @return void
329
     */
330
    public static function timestamp($timestamp)
331
    {
332
        self::$TIMESTAMP = $timestamp;
333
    }
334
335
    /**
336
     * [getTimestamp Add both the timestamp (now) and the leeway]
337
     * @return int
338
     */
339
    private static function getTimestamp()
340
    {
341
        return (int) (self::$TIMESTAMP + self::$LEEWAY);
342
    }
343
344
    /**
345
     * [algorithm Set the requested hash algorithm]
346
     * @return string
347
     */
348
    public static function algorithm($algo = 'SHA256')
349
    {
350
        if ($algo == 'HS256') {
351
            $algo = 'sha256';
352
        }
353
        self::$ALGORITHM = $algo;
354
    }
355
}
356