Passed
Push — master ( 52b7e1...c026a7 )
by Vince
06:12
created

jwtValidate   F

Complexity

Total Complexity 62

Size/Duplication

Total Lines 314
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 113
c 3
b 0
f 0
dl 0
loc 314
rs 3.44
wmc 62

15 Methods

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