Parsed: 128995

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;
  }

  $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;
}