-
-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathValidatesJWT.php
133 lines (114 loc) · 3.75 KB
/
ValidatesJWT.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
declare(strict_types=1);
/*
* This file is part of the PHP-JWT package.
*
* (c) Jitendra Adhikari <[email protected]>
* <https://github.com/adhocore>
*
* Licensed under MIT license.
*/
namespace Ahc\Jwt;
/**
* JSON Web Token (JWT) implementation in PHP7.
*
* @author Jitendra Adhikari <[email protected]>
* @license MIT
*
* @link https://github.com/adhocore/jwt
*/
trait ValidatesJWT
{
/**
* Throw up if input parameters invalid.
*
* @codeCoverageIgnore
*/
protected function validateConfig($key, string $algo, int $maxAge, int $leeway)
{
if (empty($key)) {
throw new JWTException('Signing key cannot be empty', static::ERROR_KEY_EMPTY);
}
if (!isset($this->algos[$algo])) {
throw new JWTException('Unsupported algo ' . $algo, static::ERROR_ALGO_UNSUPPORTED);
}
if ($maxAge < 1) {
throw new JWTException('Invalid maxAge: Should be greater than 0', static::ERROR_INVALID_MAXAGE);
}
if ($leeway < 0 || $leeway > 120) {
throw new JWTException('Invalid leeway: Should be between 0-120', static::ERROR_INVALID_LEEWAY);
}
}
/**
* Throw up if header invalid.
*/
protected function validateHeader(array $header)
{
if (empty($header['alg'])) {
throw new JWTException('Invalid token: Missing header algo', static::ERROR_ALGO_MISSING);
}
if (empty($this->algos[$header['alg']])) {
throw new JWTException('Invalid token: Unsupported header algo', static::ERROR_ALGO_UNSUPPORTED);
}
$this->validateKid($header);
}
/**
* Throw up if kid exists and invalid.
*/
protected function validateKid(array $header)
{
if (!isset($header['kid'])) {
return;
}
if (empty($this->keys[$header['kid']])) {
throw new JWTException('Invalid token: Unknown key ID', static::ERROR_KID_UNKNOWN);
}
$this->key = $this->keys[$header['kid']];
}
/**
* Throw up if timestamp claims like iat, exp, nbf are invalid.
*/
protected function validateTimestamps(array $payload)
{
$timestamp = $this->timestamp ?: \time();
$checks = [
['exp', $this->leeway /* */ , static::ERROR_TOKEN_EXPIRED, 'Expired'],
['iat', $this->maxAge - $this->leeway, static::ERROR_TOKEN_EXPIRED, 'Expired'],
['nbf', -$this->leeway, static::ERROR_TOKEN_NOT_NOW, 'Not now'],
];
foreach ($checks as list($key, $offset, $code, $error)) {
if (isset($payload[$key])) {
$offset += $payload[$key];
$fail = $key === 'nbf' ? $timestamp <= $offset : $timestamp >= $offset;
if ($fail) {
throw new JWTException('Invalid token: ' . $error, $code);
}
}
}
}
/**
* Throw up if key is not resource or file path to private key.
*/
protected function validateKey()
{
if (\is_string($key = $this->key)) {
if (\substr($key, 0, 7) !== 'file://') {
$key = 'file://' . $key;
}
$this->key = \openssl_get_privatekey($key, $this->passphrase ?: '');
}
if (!\is_resource($this->key)) {
throw new JWTException('Invalid key: Should be resource of private key', static::ERROR_KEY_INVALID);
}
}
/**
* Throw up if last json_encode/decode was a failure.
*/
protected function validateLastJson()
{
if (\JSON_ERROR_NONE === \json_last_error()) {
return;
}
throw new JWTException('JSON failed: ' . \json_last_error_msg(), static::ERROR_JSON_FAILED);
}
}