¿Puedo iniciar sesión de un usuario programáticamente sin contraseña?
Estoy creando usuarios manualmente de forma programática y quiero iniciar sesión con el usuario recién creado. WordPress facilita el acceso a la contraseña hasheada, pero no a la versión en texto plano. ¿Hay alguna manera de usar wp_signon() sin la contraseña en texto plano?
Encontré a una persona que dice haberlo logrado aquí, pero no funcionó para mí.
¡GRACIAS!

El siguiente código realiza el inicio de sesión automático, ¡sin necesidad de contraseña!
// Inicio de sesión automático //
$username = "Admin";
$user = get_user_by('login', $username );
// URL de redirección //
if ( !is_wp_error( $user ) )
{
wp_clear_auth_cookie();
wp_set_current_user ( $user->ID );
wp_set_auth_cookie ( $user->ID );
$redirect_to = user_admin_url();
wp_safe_redirect( $redirect_to );
exit();
}

Funciona muy bien. Con solo el nombre de usuario es suficiente, que no distingue entre mayúsculas y minúsculas.

get_user_by()
devuelve false en caso de fallo, por lo que deberías comprobar si es false en lugar del objeto WP_Error

@Sjoerd Linders, ¿dónde puedo enganchar tu script para forzar a que un usuario esté conectado?

wp_set_auth_cookie()
iniciará sesión a un usuario sin necesidad de conocer su contraseña.

Esto funcionó muy bien. Sin embargo, cuando lo uso, el condicional is_user_logged_in()
no parece funcionar. ¿Sabes si está verificando algo diferente a las cookies?

@Emerson - ¿en qué hook estás iniciando su sesión? Tiene que ser antes de que se envíen las cabeceras. También intenta usar wp_set_current_user
antes de iniciar su sesión.

En realidad no lo estaba llamando desde un hook. Solo agregué wp_set_auth_cookie()
en mi función de inicio de sesión. Supongo que necesito reconsiderar eso. También investigaré sobre wp_set_current_user y reportaré los resultados. ¡Muchas gracias por tu ayuda con esto!

He encontrado otra solución aquí que utiliza un enfoque mejor (al menos en mi opinión...). No es necesario configurar ninguna cookie, utiliza la API de Wordpress:
/**
* Inicia sesión de un usuario de forma programática
*
* @param string $username
* @return bool True si el inicio de sesión fue exitoso; false si no lo fue
*/
function programmatic_login( $username ) {
if ( is_user_logged_in() ) {
wp_logout();
}
add_filter( 'authenticate', 'allow_programmatic_login', 10, 3 ); // Se engancha antes que otros callbacks para interrumpirlos
$user = wp_signon( array( 'user_login' => $username ) );
remove_filter( 'authenticate', 'allow_programmatic_login', 10, 3 );
if ( is_a( $user, 'WP_User' ) ) {
wp_set_current_user( $user->ID, $user->user_login );
if ( is_user_logged_in() ) {
return true;
}
}
return false;
}
/**
* Un callback del filtro 'authenticate' que autentica al usuario usando solo el nombre de usuario.
*
* Para evitar posibles vulnerabilidades de seguridad, esto solo debe usarse en el contexto de un inicio de sesión programático,
* y debe desengancharse inmediatamente después de ejecutarse.
*
* @param WP_User $user
* @param string $username
* @param string $password
* @return bool|WP_User Un objeto WP_User si el nombre de usuario coincide con un usuario existente, o false si no
*/
function allow_programmatic_login( $user, $username, $password ) {
return get_user_by( 'login', $username );
}
Creo que el código se explica por sí mismo:
El filtro busca el objeto WP_User para el nombre de usuario dado y lo devuelve.
Una llamada a la función wp_set_current_user
con el objeto WP_User devuelto por wp_signon
, una verificación con la función is_user_logged_in
para asegurarse de que estás conectado, ¡y eso es todo!
¡Un código limpio y elegante en mi opinión!

@Shebo Tu comentario no parece ser correcto. La primera línea de la función verifica si el array $credentials
está vacío o no. Si el array no está vacío (que es el caso en mi respuesta), los valores del array se utilizan para autenticar al usuario.

@Mike wow, cómo pude perdérmelo... Mi error, disculpas por la confusión. Eliminaré mi primer comentario para evitar confusiones. Aunque es una gran solución :)

Este excelente artículo explica por qué esto es necesario: https://tommcfarlin.com/wordpress-user-caches/

Además de Mike, Paul y Sjoerd:
Para manejar mejor las redirecciones de login.php
:
//---------------------Inicio de sesión automático--------------------
if(!is_user_logged_in()){
$username = "user1";
if($user=get_user_by('login',$username)){
clean_user_cache($user->ID);
wp_clear_auth_cookie();
wp_set_current_user( $user->ID );
wp_set_auth_cookie( $user->ID , true, false);
update_user_caches($user);
if(is_user_logged_in()){
$redirect_to = user_admin_url();
wp_safe_redirect( $redirect_to );
exit;
}
}
}
elseif('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] == wp_login_url()){
$redirect_to = user_admin_url();
wp_safe_redirect( $redirect_to );
exit;
}
Se debe colocar en wp-config.php
justo después de
require_once(ABSPATH . 'wp-settings.php');
Para tu información
Basado en la solución anterior, he lanzado un plugin para mantener al usuario conectado de un WordPress a otro sincronizando los datos del usuario y la sesión de cookies:

Curiosamente, la única forma en que funciona para mí es si redirecciono y uso die() después:
clean_user_cache($user->ID);
wp_clear_auth_cookie();
wp_set_current_user( $user_id, $user->user_login );
wp_set_auth_cookie( $user_id, true, true );
update_user_caches( $user );
if ( is_user_logged_in() ) {
$redirect_to = $_SERVER['REQUEST_URI'];
header("location:".$redirect_to );
die();
}

Creo que este es el camino correcto. Deberíamos limpiar la caché y las cookies del usuario. Después de iniciar sesión, necesitamos activar el hook wp_login
para que otros plugins y funciones del núcleo funcionen en conjunto.
$user = get_user_by( 'ID', $user_id ); // Obtener WP_User desde el ID de usuario.
// $user = get_user_by( 'email', $email ); // O obtener desde el email.
// $user = get_user_by( 'login', $username ); // O obtener desde el nombre de usuario.
if ( false !== $user ) {
clean_user_cache( $user->ID );
wp_clear_auth_cookie();
wp_set_current_user( $user->ID, $user->user_login );
wp_set_auth_cookie( $user->ID );
update_user_caches( $user );
do_action( 'wp_login', $user->user_login, $user );
}
