Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
chromed
/
wp-content
/
plugins
/
advanced-access-manager
/
application
/
Service
:
Jwt.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * ====================================================================== * LICENSE: This file is subject to the terms and conditions defined in * * file 'license.txt', which is part of this source code package. * * ====================================================================== */ /** * JWT Token service * * @package AAM * @version 7.0.0 */ class AAM_Service_Jwt { use AAM_Service_BaseTrait; /** * JWT Registry DB option * * @version 7.0.0 */ const DB_OPTION = 'aam_jwt_registry'; /** * Default configurations * * @version 7.0.0 */ const DEFAULT_CONFIG = [ 'service.jwt.bearer' => 'header,query_param,post_param,cookie', 'service.jwt.header_name' => 'HTTP_AUTHENTICATION', 'service.jwt.cookie_name' => 'aam_jwt_token', 'service.jwt.post_param_name' => 'aam-jwt', 'service.jwt.query_param_name' => 'aam-jwt' ]; /** * Constructor * * @return void * @access protected * * @version 7.0.4 */ protected function __construct() { add_filter('aam_get_config_filter', function($result, $key) { if (empty($result) && array_key_exists($key, self::DEFAULT_CONFIG)) { $result = self::DEFAULT_CONFIG[$key]; } return $result; }, 10, 2); // WP Core current user definition add_filter('determine_current_user', function($user_id){ return $this->_determine_current_user($user_id); }, PHP_INT_MAX); // Register RESTful API AAM_Restful_Jwt::bootstrap(); add_action('init', function() { $this->initialize_hooks(); }, PHP_INT_MAX); } /** * Initialize service hooks * * @return void * @access protected * * @version 7.0.4 */ protected function initialize_hooks() { if (is_admin()) { // Hook that initialize the AAM UI part of the service add_action('aam_initialize_ui_action', function () { AAM_Backend_Feature_Main_Jwt::register(); }); add_action('aam_post_edit_user_modal_action', function () { if (current_user_can('aam_manage_jwt')) { echo AAM_Backend_View::get_instance()->loadPartial( 'jwt-login-url' ); } }); } add_action('aam_reset_action', function() { global $wpdb; // Run the query, will return true if deleted, false otherwise $wpdb->delete($wpdb->usermeta, [ 'meta_key' => $wpdb->prefix . AAM_Framework_Service_Jwts::DB_OPTION ]); }); add_filter( 'aam_rest_authenticated_user_data_filter', function($result, $request, $user) { return $this->_prepare_login_response($result, $request, $user); }, 10, 3 ); // Allow other implementations to work with JWT token add_filter('aam_current_jwt_filter', function($result) { if (empty($result)) { $token = $this->_extract_token(); $result = !empty($token) ? $token->jwt : null; } return $result; }); } /** * Extern authentication request with JWT token * * @param array $response * @param WP_REST_Request $request * @param WP_User $user * * @return array * @access public * * @version 7.0.0 */ private function _prepare_login_response($response, $request, $user) { $issue_jwt = $this->_get_backward_compatible_request_param( 'issue_jwt', 'issueJWT', $request ); $issue_refreshable_jwt = $this->_get_backward_compatible_request_param( 'issue_refreshable_jwt', 'refreshableJWT', $request ); if (is_array($response) && ($issue_jwt || $issue_refreshable_jwt)) { if ($issue_refreshable_jwt) { if (current_user_can('aam_issue_refreshable_jwt')) { throw new DomainException( 'You are not allowed to issue refreshable JWT token' ); } } $result = AAM::api()->jwts('user:' . $user->ID)->issue([], [ 'refreshable' => $issue_refreshable_jwt ]); $response['jwt'] = [ 'token' => $result['token'], 'token_expires' => $result['claims']['exp'] ]; } return $response; } /** * Get backward compatible param from request * * @param string $new_param * @param string $legacy_param * @param WP_REST_Request $request * @param bool $default * * @return string|null * @access private * * @version 7.0.1 */ private function _get_backward_compatible_request_param( $new_param, $legacy_param, $request, $default = false ) { $result = $request->get_param($new_param); if (empty($result)) { $result = $request->get_param($legacy_param); if (!empty($result)) { _deprecated_argument('/authenticate', AAM_VERSION, sprintf( 'The REST %s parameter is deprecated. Replace it with %s', $legacy_param, $new_param )); } } return is_null($result) ? $default : $result; } /** * Determine current user by JWT * * @param int $user_id * * @return int * @access private * * @version 7.0.4 */ private function _determine_current_user($user_id) { if (empty($user_id)) { $token = $this->_extract_token(); if (!empty($token)) { $claims = AAM::api()->jwt->decode($token->jwt); if (!is_wp_error($claims)) { // Backward compatibility if (array_key_exists('userId', $claims)) { $cuid = $claims['userId']; } else { $cuid = $claims['user_id']; } // Get JWT service and verify that token is valid $service = AAM::api()->jwts( 'user:' . $cuid, [ 'error_handling' => 'wp_error' ] ); if (!is_wp_error($service)) { $is_valid = $service->validate($token->jwt); if ($is_valid === true) { if ($this->_is_user_active($cuid)) { $this->_maybe_authenticate($cuid, $token, $claims); $user_id = $cuid; } } } } } } return $user_id; } /** * Determine if JWT token is used in password-less URL and if so - authenticate * * @param int $user_id * @param object $token * @param array $claims * * @return void * @access private * * @version 7.0.4 */ private function _maybe_authenticate($user_id, $token, $claims) { if (in_array($token->method, [ 'get', 'query', 'query_param' ], true)) { $this->_authenticate_user($user_id, $claims); } } /** * Authenticate user with JWT * * @return void * @access private * * @version 7.0.0 */ private function _authenticate_user($user_id, $token_claims) { wp_set_current_user($user_id); wp_set_auth_cookie($user_id); // If we are authenticating with passwordless, that manually set user's // expiration attributes $data = [ 'expiration' => [ 'expires_at' => $token_claims['exp'] ] ]; if (array_key_exists('trigger', $token_claims)) { $data['expiration']['trigger'] = $token_claims['trigger']; } $user = AAM::api()->user($user_id); $user->update($data); do_action('wp_login', $user->user_login, $user->get_core_instance()); // Determine where to redirect user and safely redirect & finally just // redirect user to the homepage $redirect_to = AAM::api()->misc->get($_GET, 'redirect_to'); wp_safe_redirect( apply_filters( 'login_redirect', (!empty($redirect_to) ? $redirect_to : admin_url()), '', $user->get_core_instance() ) ); // Halt the execution. Redirect should carry user away if this is not // a CLI execution (e.g. Unit Test) if (php_sapi_name() !== 'cli') { exit; } } /** * Extract JWT token from the request * * Based on the `authentication.jwt.container` setting, parse HTTP request and * try to extract the JWT token * * @return object|null * @access protected * * @version 7.0.4 */ private function _extract_token() { $configs = AAM::api()->config; $container = wp_parse_list($configs->get('service.jwt.bearer', '')); foreach ($container as $method) { switch (strtolower(trim($method))) { case 'header': // Fallback for Authorization header $possibles = array( 'HTTP_AUTHORIZATION', 'REDIRECT_HTTP_AUTHORIZATION', $configs->get('service.jwt.header_name') ); foreach($possibles as $h) { $jwt = AAM::api()->misc->get($_SERVER, $h); if (!empty($jwt)) { break; } } break; case 'cookie': $jwt = AAM::api()->misc->get( $_COOKIE, $configs->get('service.jwt.cookie_name') ); break; case 'post': case 'post_param': $jwt = AAM::api()->misc->get( $_POST, $configs->get('service.jwt.post_param_name') ); break; case 'get': case 'query': case 'query_param': $jwt = AAM::api()->misc->get( $_GET, $configs->get('service.jwt.query_param_name') ); break; default: $jwt = apply_filters('aam_extract_jwt_filter', null, $method); break; } if (!empty($jwt)) { break; } } if (!empty($jwt)) { $response = (object) array( 'jwt' => preg_replace('/^Bearer /', '', $jwt), 'method' => $method ); } else { $response = null; } return $response; } /** * Verify user's status * * @param int $user_id * * @return bool * @access private * * @version 7.0.4 */ private function _is_user_active($user_id) { $user = AAM::api()->user($user_id); // Verify that user is active and is not expired return $user->is_user_active() && !$user->is_user_access_expired(); } }