* Authenticates and logs a user in with 'remember' capability.
* The credentials is an array that has 'user_login', 'user_password', and
* 'remember' indices. If the credentials is not given, then the log in form
* will be assumed and used if set.
* The various authentication cookies will be set by this function and will be
* set for a longer period depending on if the 'remember' credential is set to
* Note: wp_signon() doesn't handle setting the current user. This means that if the
* function is called before the {@see 'init'} hook is fired, is_user_logged_in() will
* evaluate as false until that point. If is_user_logged_in() is needed in conjunction
* with wp_signon(), wp_set_current_user() should be called explicitly.
* @global string $auth_secure_cookie
* @param array $credentials Optional. User info in order to sign on.
* @param string|bool $secure_cookie Optional. Whether to use secure cookie.
* @return WP_User|WP_Error WP_User on success, WP_Error on failure.
function wp_signon( $credentials = array(), $secure_cookie = '' ) {
if ( empty( $credentials ) ) {
$credentials = array(); // Back-compat for plugins passing an empty string.
if ( ! empty( $_POST['log'] ) ) {
$credentials['user_login'] = wp_unslash( $_POST['log'] );
if ( ! empty( $_POST['pwd'] ) ) {
$credentials['user_password'] = $_POST['pwd'];
if ( ! empty( $_POST['rememberme'] ) ) {
$credentials['remember'] = $_POST['rememberme'];
if ( ! empty( $credentials['remember'] ) ) {
$credentials['remember'] = true;
$credentials['remember'] = false;
* Fires before the user is authenticated.
* The variables passed to the callbacks are passed by reference,
* and can be modified by callback functions.
* @todo Decide whether to deprecate the wp_authenticate action.
* @param string $user_login Username (passed by reference).
* @param string $user_password User password (passed by reference).
do_action_ref_array( 'wp_authenticate', array( &$credentials['user_login'], &$credentials['user_password'] ) );
if ( '' === $secure_cookie ) {
$secure_cookie = is_ssl();
* Filters whether to use a secure sign-on cookie.
* @param bool $secure_cookie Whether to use a secure sign-on cookie.
* @param array $credentials {
* Array of entered sign-on data.
* @type string $user_login Username.
* @type string $user_password Password entered.
* @type bool $remember Whether to 'remember' the user. Increases the time
* that the cookie will be kept. Default false.
$secure_cookie = apply_filters( 'secure_signon_cookie', $secure_cookie, $credentials );
global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie().
$auth_secure_cookie = $secure_cookie;
add_filter( 'authenticate', 'wp_authenticate_cookie', 30, 3 );
$user = wp_authenticate( $credentials['user_login'], $credentials['user_password'] );
if ( is_wp_error( $user ) ) {
wp_set_auth_cookie( $user->ID, $credentials['remember'], $secure_cookie );
* Fires after the user has successfully logged in.
* @param string $user_login Username.
* @param WP_User $user WP_User object of the logged-in user.
do_action( 'wp_login', $user->user_login, $user );
* Authenticate a user, confirming the username and password are valid.
* @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.
* @param string $username Username for authentication.
* @param string $password Password for authentication.
* @return WP_User|WP_Error WP_User on success, WP_Error on failure.
function wp_authenticate_username_password( $user, $username, $password ) {
if ( $user instanceof WP_User ) {
if ( empty( $username ) || empty( $password ) ) {
if ( is_wp_error( $user ) ) {
if ( empty( $username ) ) {
$error->add( 'empty_username', __( '<strong>Error</strong>: The username field is empty.' ) );
if ( empty( $password ) ) {
$error->add( 'empty_password', __( '<strong>Error</strong>: The password field is empty.' ) );
$user = get_user_by( 'login', $username );
__( 'Unknown username. Check again or try your email address.' )
* Filters whether the given user can be authenticated with the provided $password.
* @param WP_User|WP_Error $user WP_User or WP_Error object if a previous
* callback failed authentication.
* @param string $password Password to check against the user.
$user = apply_filters( 'wp_authenticate_user', $user, $password );
if ( is_wp_error( $user ) ) {
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
/* translators: %s: User name. */
__( '<strong>Error</strong>: The password you entered for the username %s is incorrect.' ),
'<strong>' . $username . '</strong>'
' <a href="' . wp_lostpassword_url() . '">' .
__( 'Lost your password?' ) .
* Authenticates a user using the email and password.
* @param WP_User|WP_Error|null $user WP_User or WP_Error object if a previous
* callback failed authentication.
* @param string $email Email address for authentication.
* @param string $password Password for authentication.
* @return WP_User|WP_Error WP_User on success, WP_Error on failure.
function wp_authenticate_email_password( $user, $email, $password ) {
if ( $user instanceof WP_User ) {
if ( empty( $email ) || empty( $password ) ) {
if ( is_wp_error( $user ) ) {
// Uses 'empty_username' for back-compat with wp_signon().
$error->add( 'empty_username', __( '<strong>Error</strong>: The email field is empty.' ) );
if ( empty( $password ) ) {
$error->add( 'empty_password', __( '<strong>Error</strong>: The password field is empty.' ) );
if ( ! is_email( $email ) ) {
$user = get_user_by( 'email', $email );
__( 'Unknown email address. Check again or try your username.' )
/** This filter is documented in wp-includes/user.php */
$user = apply_filters( 'wp_authenticate_user', $user, $password );
if ( is_wp_error( $user ) ) {
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
/* translators: %s: Email address. */
__( '<strong>Error</strong>: The password you entered for the email address %s is incorrect.' ),
'<strong>' . $email . '</strong>'
' <a href="' . wp_lostpassword_url() . '">' .
__( 'Lost your password?' ) .
* Authenticate the user using the WordPress auth cookie.
* @global string $auth_secure_cookie
* @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.
* @param string $username Username. If not empty, cancels the cookie authentication.
* @param string $password Password. If not empty, cancels the cookie authentication.
* @return WP_User|WP_Error WP_User on success, WP_Error on failure.
function wp_authenticate_cookie( $user, $username, $password ) {
if ( $user instanceof WP_User ) {
if ( empty( $username ) && empty( $password ) ) {
$user_id = wp_validate_auth_cookie();
return new WP_User( $user_id );
global $auth_secure_cookie;
if ( $auth_secure_cookie ) {
$auth_cookie = SECURE_AUTH_COOKIE;
$auth_cookie = AUTH_COOKIE;
if ( ! empty( $_COOKIE[ $auth_cookie ] ) ) {
return new WP_Error( 'expired_session', __( 'Please log in again.' ) );
// If the cookie is not set, be silent.
* Authenticates the user using an application password.
* @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 ) {
if ( ! WP_Application_Passwords::is_in_use() ) {
$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.
* @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 ) {
$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 ( is_email( $username ) ) {
__( 'Unknown email address. Check again or try your username.' )
__( 'Unknown username. Check again or try your email address.' )
} elseif ( ! wp_is_application_passwords_available() ) {
'application_passwords_disabled',
__( 'Application passwords are not available.' )
} elseif ( ! wp_is_application_passwords_available_for_user( $user ) ) {
'application_passwords_disabled_for_user',
__( 'Application passwords are not available for your account. Please contact the site administrator for assistance.' )
* Fires when an application password failed to authenticate the user.
* @param WP_Error $error The authentication error.
do_action( 'application_password_failed_authentication', $error );
* Strip 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 ) ) {
* 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.
* @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 );
WP_Application_Passwords::record_application_password_usage( $user->ID, $item['uuid'] );
* Fires after an application password was used for authentication.
* @param WP_User $user The user who was authenticated.
* @param array $item The application password used.
do_action( 'application_password_did_authenticate', $user, $item );
__( 'The provided password is an invalid application password.' )
/** This action is documented in wp-includes/user.php */
do_action( 'application_password_failed_authentication', $error );
* Validates the application password credentials passed via Basic Authentication.
* @param int|false $input_user User ID if one has been determined, false otherwise.
* @return int|false The authenticated user ID if successful, false otherwise.
function wp_validate_application_password( $input_user ) {
// Don't authenticate twice.
if ( ! empty( $input_user ) ) {
if ( ! wp_is_application_passwords_available() ) {
// Both $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] must be set in order to attempt authentication.
if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
$authenticated = wp_authenticate_application_password( null, $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] );
if ( $authenticated instanceof WP_User ) {
return $authenticated->ID;
// If it wasn't a user what got returned, just pass on what we had received originally.
* For Multisite blogs, check if the authenticated user has been marked as a
* spammer, or if the user's primary blog has been marked as spam.
* @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.
* @return WP_User|WP_Error WP_User on success, WP_Error if the user is considered a spammer.
function wp_authenticate_spam_check( $user ) {
if ( $user instanceof WP_User && is_multisite() ) {
* Filters whether the user has been marked as a spammer.
* @param bool $spammed Whether the user is considered a spammer.
* @param WP_User $user User to check against.
$spammed = apply_filters( 'check_is_user_spammed', is_user_spammy( $user ), $user );