PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / 5.9
Advanced Access Manager – Access Governance for WordPress v5.9
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 / JwtAuth.php
advanced-access-manager / Application / Core Last commit date
Api 7 years ago ConfigPress 7 years ago Object 7 years ago Policy 7 years ago Subject 7 years ago API.php 7 years ago Cache.php 7 years ago Compatibility.php 7 years ago Config.php 7 years ago ConfigPress.php 7 years ago Console.php 7 years ago Exporter.php 7 years ago Gateway.php 7 years ago Importer.php 7 years ago JwtAuth.php 7 years ago Login.php 7 years ago Media.php 7 years ago Object.php 7 years ago Request.php 7 years ago Server.php 7 years ago Subject.php 7 years ago
JwtAuth.php
347 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 Authentication
12 *
13 * @package AAM
14 * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15 */
16 class AAM_Core_JwtAuth {
17
18 /**
19 * Single instance of itself
20 *
21 * @var AAM_Core_JwtAuth
22 *
23 * @access protected
24 * @static
25 */
26 protected static $instance = null;
27
28 /**
29 * Constructor
30 *
31 * @return void
32 *
33 * @access protected
34 */
35 protected function __construct() {
36 //register API endpoint
37 add_action('rest_api_init', array($this, 'registerAPI'));
38
39 //register authentication hook
40 add_filter('determine_current_user', array($this, 'determineCurrentUser'), 999);
41 }
42
43 /**
44 * Register APIs
45 *
46 * @return void
47 *
48 * @access public
49 */
50 public function registerAPI() {
51 // Authenticate user
52 register_rest_route('aam/v1', '/authenticate', array(
53 'methods' => 'POST',
54 'callback' => array($this, 'authenticate'),
55 'args' => array(
56 'username' => array(
57 'description' => __('Valid username.', AAM_KEY),
58 'type' => 'string',
59 ),
60 'password' => array(
61 'description' => __('Valid password.', AAM_KEY),
62 'type' => 'string',
63 )
64 ),
65 ));
66
67 // Validate JWT token
68 register_rest_route('aam/v1', '/validate-jwt', array(
69 'methods' => 'POST',
70 'callback' => array($this, 'validateJWT'),
71 'args' => array(
72 'jwt' => array(
73 'description' => __('JWT token.', AAM_KEY),
74 'type' => 'string',
75 )
76 ),
77 ));
78 }
79
80 /**
81 * Authenticate user
82 *
83 * @param WP_REST_Request $request
84 *
85 * @return WP_REST_Response
86 *
87 * @access public
88 */
89 public function authenticate(WP_REST_Request $request) {
90 $username = $request->get_param('username');
91 $password = $request->get_param('password');
92
93 // try to authenticate user
94 $result = AAM_Core_Login::getInstance()->execute(array(
95 'user_login' => $username,
96 'user_password' => $password
97 ), false);
98
99 $response = new WP_REST_Response();
100
101 if ($result['status'] === 'success') { // generate token
102 try {
103 $token = $this->issueJWT($result['user']->ID);
104
105 $response->status = 200;
106 $response->data = array(
107 'token' => $token->token,
108 'token_expires' => $token->claims['exp'],
109 'user' => $result['user']
110 );
111 } catch (Exception $ex) {
112 $response->status = 400;
113 $response->data = new WP_Error(
114 'rest_jwt_empty_secret_key',
115 $ex->getMessage()
116 );
117 }
118 } else {
119 $response->data = $result['reason'];
120 $response->status = 403;
121 }
122
123 return apply_filters('aam-jwt-response-filter', $response);
124 }
125
126 /**
127 *
128 * @param WP_REST_Request $request
129 */
130 public function validateJWT(WP_REST_Request $request) {
131 $jwt = $request->get_param('jwt');
132 $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
133
134 $response = new WP_REST_Response(array(
135 'status' => 'invalid'
136 ), 400);
137
138 if (!empty($jwt)) {
139 try {
140 $claims = Firebase\JWT\JWT::decode(
141 $jwt, $key, array_keys(Firebase\JWT\JWT::$supported_algs)
142 );
143
144 $response->status = 200;
145 $response->data = array(
146 'status' => 'valid',
147 'token_expires' => $claims->exp
148 );
149 } catch (Exception $ex) {
150 $response->data['reason'] = $ex->getMessage();
151 }
152 }
153
154 return $response;
155 }
156
157 /**
158 * Generate JWT token
159 *
160 * @param int $userId
161 *
162 * @return stdClass
163 *
164 * @access public
165 * @throws Exception
166 */
167 public function issueJWT($userId, $container = 'header') {
168 $container = explode(
169 ',', AAM_Core_Config::get('authentication.jwt.container', $container)
170 );
171
172 $token = $this->generateJWT($userId);
173
174 if (in_array('cookie', $container, true)) {
175 setcookie(
176 'aam-jwt',
177 $token->token,
178 $token->claims['exp'],
179 '/',
180 parse_url(get_bloginfo('url'), PHP_URL_HOST),
181 is_ssl(),
182 AAM_Core_Config::get('authentication.jwt.cookie.httpOnly', false)
183 );
184 }
185
186 return $token;
187 }
188
189 /**
190 * Generate the token
191 *
192 * @param int $userId
193 * @param int $expires
194 *
195 * @return stdObject
196 *
197 * @access public
198 * @throws Exception
199 */
200 public static function generateJWT($userId, $expires = null) {
201 $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
202 $expire = AAM_Core_Config::get('authentication.jwt.expires', $expires);
203 $alg = AAM_Core_Config::get('authentication.jwt.algorithm', 'HS256');
204
205 if (!empty($expire)) {
206 $time = DateTime::createFromFormat('m/d/Y, H:i O', $expires);
207 } else {
208 $time = new DateTime('+24 hours');
209 }
210
211 if ($key) {
212 $claims = apply_filters('aam-jwt-claims-filter', array(
213 "iat" => time(),
214 'exp' => $time->format('U'),
215 'userId' => $userId
216 ));
217
218 $token = Firebase\JWT\JWT::encode($claims, $key, $alg);
219 } else {
220 Throw new Exception(
221 __('JWT Authentication is enabled but secret key is not defined', AAM_KEY)
222 );
223 }
224
225 return (object) array(
226 'token' => $token,
227 'claims' => $claims
228 );
229 }
230
231 /**
232 *
233 * @param type $result
234 */
235 public function determineCurrentUser($result) {
236 $token = $this->extractJwt();
237 $key = AAM_Core_Config::get('authentication.jwt.secret', SECURE_AUTH_KEY);
238
239 if (!empty($token['jwt'])) {
240 try {
241 $claims = Firebase\JWT\JWT::decode(
242 $token['jwt'], $key, array_keys(Firebase\JWT\JWT::$supported_algs)
243 );
244
245 if (isset($claims->userId)) {
246 $result = $claims->userId;
247
248 // Also login user if REQUEST_METHOD is GET
249 if ($token['method'] === 'query'
250 && AAM_Core_Request::server('REQUEST_METHOD') === 'GET') {
251 wp_set_current_user($claims->userId);
252 wp_set_auth_cookie($claims->userId);
253
254 $exp = get_user_meta($claims->userId, 'aam_user_expiration', true);
255 if (empty($exp)) {
256 update_user_meta(
257 $claims->userId,
258 'aam_user_expiration',
259 date('m/d/Y, H:i O', $claims->exp) . '|logout|'
260 );
261 }
262
263 do_action('wp_login', '', wp_get_current_user());
264 }
265 }
266 } catch (Exception $ex) {
267 // Do nothing
268 }
269 }
270
271 return $result;
272 }
273
274 /**
275 *
276 * @return type
277 */
278 protected function extractJwt() {
279 $container = explode(',', AAM_Core_Config::get(
280 'authentication.jwt.container', 'header,post,query,cookie'
281 ));
282
283 $jwt = null;
284
285 foreach($container as $method) {
286 switch(strtolower(trim($method))) {
287 case 'header':
288 $jwt = AAM_Core_Request::server('HTTP_AUTHENTICATION');
289 break;
290
291 case 'cookie':
292 $jwt = AAM_Core_Request::cookie('aam-jwt');
293 break;
294
295 case 'query':
296 $jwt = AAM_Core_Request::get('aam-jwt');
297 break;
298
299 case 'post':
300 $jwt = AAM_Core_Request::post('aam-jwt');
301 break;
302
303 default:
304 $jwt = apply_filters('aam-get-jwt-filter', null, $method);
305 break;
306 }
307
308 if (!is_null($jwt)) {
309 break;
310 }
311 }
312
313 return array(
314 'jwt' => preg_replace('/^Bearer /', '', $jwt),
315 'method' => $method
316 );
317 }
318
319 /**
320 * Get single instance of itself
321 *
322 * @return AAM_Core_JwtAuth
323 *
324 * @access public
325 * @static
326 */
327 public static function getInstance() {
328 if (is_null(self::$instance)) {
329 self::$instance = new self;
330 }
331
332 return self::$instance;
333 }
334
335 /**
336 * Bootstrap AAM JWT Authentication feature
337 *
338 * @return AAM_Core_JwtAuth
339 *
340 * @access public
341 * @static
342 */
343 public static function bootstrap() {
344 return self::getInstance();
345 }
346
347 }