PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / 5.11
Advanced Access Manager – Access Governance for WordPress v5.11
6.8.4 6.8.5 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13 6.9.14 6.9.15 6.9.16 6.9.17 6.9.18 6.9.19 6.9.2 6.9.20 6.9.21 6.9.22 6.9.23 6.9.24 6.9.25 6.9.26 6.9.27 6.9.28 6.9.29 6.9.3 6.9.30 6.9.31 6.9.32 6.9.33 6.9.34 6.9.35 6.9.36 6.9.37 6.9.38 6.9.39 6.9.4 6.9.41 6.9.42 6.9.43 6.9.44 6.9.45 6.9.46 6.9.47 6.9.48 6.9.49 6.9.5 6.9.51 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.0-alpha.6 7.0.0-alpha.7 7.0.0-beta.1 7.0.0-rc1 7.0.0-rc2 7.0.0-rc3 7.0.1 7.0.10 7.0.11 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7 7.0.8 7.0.9 7.1.0 7.1.1 trunk 3.0 4.0 4.0.1 4.1 4.2 4.3 4.4 4.4.1 4.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.7.5 4.7.6 4.8 4.8.1 4.9 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.5.1 4.9.5.2 5.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1 5.1.1 5.10 5.11 5.2 5.2.1 5.2.5 5.2.6 5.2.7 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.4 5.4.1 5.4.2 5.4.3 5.4.3.1 5.4.3.2 5.5 5.5.1 5.5.2 5.6 5.6.1 5.6.1.1 5.7 5.7.1 5.7.2 5.7.3 5.8 5.8.1 5.8.2 5.8.3 5.9 5.9.1 5.9.1.1 5.9.2 5.9.2.1 5.9.3 5.9.4 5.9.5 5.9.6 5.9.6.1 5.9.6.2 5.9.6.3 5.9.7 5.9.7.1 5.9.7.2 5.9.7.3 5.9.8 5.9.8.1 5.9.9 5.9.9.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.2.0 6.2.1 6.2.2 6.3.0 6.3.1 6.3.2 6.3.3 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.6.0 6.6.1 6.6.2 6.6.3 6.6.4 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3
advanced-access-manager / application / Core / Jwt / Issuer.php
advanced-access-manager / application / Core / Jwt Last commit date
Auth.php 6 years ago Issuer.php 6 years ago Manager.php 6 years ago
Issuer.php
233 lines
1 <?php
2
3 /**
4 * ======================================================================
5 * LICENSE: This file is subject to the terms and conditions defined in *
6 * file 'license.txt', which is part of this source code package. *
7 * ======================================================================
8 */
9
10 /**
11 * AAM JWT Issuer
12 *
13 * @package AAM
14 * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15 * @since v5.9.2
16 */
17 class AAM_Core_Jwt_Issuer {
18
19 /**
20 * Just a local cache
21 *
22 * @var array
23 */
24 protected $cache = array();
25
26 /**
27 * Validate JWT token
28 *
29 * @param string $token
30 *
31 * @return stdClass
32 *
33 * @access public
34 */
35 public function validateToken($token) {
36 try {
37 $headers = $this->extractTokenHeaders($token);
38
39 if (strpos($headers->alg, 'RS') === 0) {
40 $filepath = AAM_Core_Config::get('authentication.jwt.publicKeyPath');
41 $key = (is_readable($filepath) ? file_get_contents($filepath) : null);
42 } else {
43 $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
44 }
45
46 // Step #1. Check if token is actually valid
47 $response = Firebase\JWT\JWT::decode(
48 $token, $key, array_keys(Firebase\JWT\JWT::$supported_algs)
49 );
50
51 // Step #2. If token is "revocable", make sure that claimed user still has
52 // the token in the meta
53 if (!empty($response->revocable)) {
54 $tokens = $this->getUsersTokens($response->userId);
55 if (!in_array($token, $tokens, true)) {
56 throw new Exception(__('Token has been revoked', AAM_KEY));
57 }
58 }
59
60 $response->status = 'valid';
61 } catch (Exception $ex) {
62 $response = array_merge(array(
63 'status' => 'invalid',
64 'reason' => $ex->getMessage()
65 ), (array) $this->extractTokenClaims($token));
66 }
67
68 return (object) $response;
69 }
70
71 /**
72 * Issue JWT token
73 *
74 * @param array $args
75 * @param string|DateTime $expires
76 *
77 * @return stdClass
78 *
79 * @access public
80 * @throws Exception
81 */
82 public function issueToken($args = array(), $expires = null) {
83 if (!empty($expires)) {
84 if (is_a($expires, 'DateTime')) {
85 $time = $expires;
86 } else {
87 $time = DateTime::createFromFormat('m/d/Y, H:i O', $expires);
88 }
89 } else {
90 $time = new DateTime(
91 AAM_Core_Config::get('authentication.jwt.expires', '+24 hours')
92 );
93 }
94
95 $claims = apply_filters(
96 'aam-jwt-claims-filter',
97 array_merge(
98 array(
99 "iat" => time(),
100 'iss' => get_site_url(),
101 'exp' => $time->format('m/d/Y, H:i O'),
102 'jti' => $this->generateUuid()
103 ),
104 $args
105 )
106 );
107
108 // Determine algorithm and key
109 $attr = $this->getJWTSigningAttributes();
110
111 return (object) array(
112 'token' => Firebase\JWT\JWT::encode($claims, $attr->key, $attr->alg),
113 'claims' => $claims
114 );
115 }
116
117 /**
118 * Extract tokens headers
119 *
120 * @param string $token
121 *
122 * @return object
123 *
124 * @access public
125 */
126 public static function extractTokenHeaders($token) {
127 $parts = explode('.', $token);
128
129 try {
130 $headers = Firebase\JWT\JWT::jsonDecode(
131 Firebase\JWT\JWT::urlsafeB64Decode($parts[0])
132 );
133 } catch (Exception $ex) {
134 $headers = new stdClass();
135 }
136
137 return $headers;
138 }
139
140 /**
141 * Extract token claims
142 *
143 * @param string $token
144 *
145 * @return object
146 *
147 * @access public
148 */
149 public static function extractTokenClaims($token) {
150 $parts = explode('.', $token);
151
152 try {
153 $claims = Firebase\JWT\JWT::jsonDecode(
154 Firebase\JWT\JWT::urlsafeB64Decode($parts[1])
155 );
156 } catch (Exception $ex) {
157 $claims = new stdClass();
158 }
159
160 return $claims;
161 }
162
163 /**
164 * Get JWT attributes for signing
165 *
166 * @return object
167 *
168 * @access protected
169 */
170 protected function getJWTSigningAttributes() {
171 $alg = strtoupper(
172 AAM_Core_Config::get('authentication.jwt.algorithm', 'HS256')
173 );
174
175 if (strpos($alg, 'RS') === 0) {
176 $filepath = AAM_Core_Config::get('authentication.jwt.privateKeyPath');
177 $key = (is_readable($filepath) ? file_get_contents($filepath) : null);
178 } else {
179 $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
180 }
181
182 return (object) array(
183 'alg' => $alg,
184 'key' => $key
185 );
186 }
187
188 /**
189 * Get user's tokens
190 *
191 * @param int $userId
192 *
193 * @return array
194 *
195 * @access protected
196 */
197 protected function getUsersTokens($userId) {
198 if (!isset($this->cache[$userId])) {
199 $list = get_user_meta($userId, 'aam-jwt');
200 $this->cache[$userId] = is_array($list) ? $list : array();
201 }
202
203 return $this->cache[$userId];
204 }
205
206 /**
207 * Generate random uuid
208 *
209 * @return string
210 */
211 protected function generateUuid() {
212 return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
213 // 32 bits for "time_low"
214 mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
215
216 // 16 bits for "time_mid"
217 mt_rand( 0, 0xffff ),
218
219 // 16 bits for "time_hi_and_version",
220 // four most significant bits holds version number 4
221 mt_rand( 0, 0x0fff ) | 0x4000,
222
223 // 16 bits, 8 bits for "clk_seq_hi_res",
224 // 8 bits for "clk_seq_low",
225 // two most significant bits holds zero and one for variant DCE1.1
226 mt_rand( 0, 0x3fff ) | 0x8000,
227
228 // 48 bits for "node"
229 mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
230 );
231 }
232
233 }