Passed
Branch master (e80214)
by Vince
01:23
created

jwtValidate::alg()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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