WordPress Version: 6.5
/**
* Authenticates the user using an application password.
*
* @since 5.6.0
*
* @param WP_User|WP_Error|null $input_user WP_User or WP_Error object if a previous
* callback failed authentication.
* @param string $username Username for authentication.
* @param string $password Password for authentication.
* @return WP_User|WP_Error|null WP_User on success, WP_Error on failure, null if
* null is passed in and this isn't an API request.
*/
function wp_authenticate_application_password($input_user, $username, $password)
{
if ($input_user instanceof WP_User) {
return $input_user;
}
if (!WP_Application_Passwords::is_in_use()) {
return $input_user;
}
// The 'REST_REQUEST' check here may happen too early for the constant to be available.
$is_api_request = defined('XMLRPC_REQUEST') && XMLRPC_REQUEST || defined('REST_REQUEST') && REST_REQUEST;
/**
* Filters whether this is an API request that Application Passwords can be used on.
*
* By default, Application Passwords is available for the REST API and XML-RPC.
*
* @since 5.6.0
*
* @param bool $is_api_request If this is an acceptable API request.
*/
$is_api_request = apply_filters('application_password_is_api_request', $is_api_request);
if (!$is_api_request) {
return $input_user;
}
$error = null;
$user = get_user_by('login', $username);
if (!$user && is_email($username)) {
$user = get_user_by('email', $username);
}
// If the login name is invalid, short circuit.
if (!$user) {
if (is_email($username)) {
$error = new WP_Error('invalid_email', __('<strong>Error:</strong> Unknown email address. Check again or try your username.'));
} else {
$error = new WP_Error('invalid_username', __('<strong>Error:</strong> Unknown username. Check again or try your email address.'));
}
} elseif (!wp_is_application_passwords_available()) {
$error = new WP_Error('application_passwords_disabled', __('Application passwords are not available.'));
} elseif (!wp_is_application_passwords_available_for_user($user)) {
$error = new WP_Error('application_passwords_disabled_for_user', __('Application passwords are not available for your account. Please contact the site administrator for assistance.'));
}
if ($error) {
/**
* Fires when an application password failed to authenticate the user.
*
* @since 5.6.0
*
* @param WP_Error $error The authentication error.
*/
do_action('application_password_failed_authentication', $error);
return $error;
}
/*
* Strips out anything non-alphanumeric. This is so passwords can be used with
* or without spaces to indicate the groupings for readability.
*
* Generated application passwords are exclusively alphanumeric.
*/
$password = preg_replace('/[^a-z\d]/i', '', $password);
$hashed_passwords = WP_Application_Passwords::get_user_application_passwords($user->ID);
foreach ($hashed_passwords as $key => $item) {
if (!wp_check_password($password, $item['password'], $user->ID)) {
continue;
}
$error = new WP_Error();
/**
* Fires when an application password has been successfully checked as valid.
*
* This allows for plugins to add additional constraints to prevent an application password from being used.
*
* @since 5.6.0
*
* @param WP_Error $error The error object.
* @param WP_User $user The user authenticating.
* @param array $item The details about the application password.
* @param string $password The raw supplied password.
*/
do_action('wp_authenticate_application_password_errors', $error, $user, $item, $password);
if (is_wp_error($error) && $error->has_errors()) {
/** This action is documented in wp-includes/user.php */
do_action('application_password_failed_authentication', $error);
return $error;
}
WP_Application_Passwords::record_application_password_usage($user->ID, $item['uuid']);
/**
* Fires after an application password was used for authentication.
*
* @since 5.6.0
*
* @param WP_User $user The user who was authenticated.
* @param array $item The application password used.
*/
do_action('application_password_did_authenticate', $user, $item);
return $user;
}
$error = new WP_Error('incorrect_password', __('The provided password is an invalid application password.'));
/** This action is documented in wp-includes/user.php */
do_action('application_password_failed_authentication', $error);
return $error;
}