Pregunta:
Estoy trabajando en un complemento que usa WordPress como proveedor de inicio de sesión único para otra aplicación. Necesito asegurarme de que el usuario haya verificado su dirección de correo electrónico respondiendo al correo electrónico enviado por wp_new_user_notification()
.
Hasta ahora, el mejor enfoque que he encontrado es conectarme a la acción after_password_reset
y agregar user_metadata para indicar que el correo electrónico está verificado. Esto funciona, pero todo lo que realmente me dice es que se ha llamado a la función reset_password
.
¿Hay una mejor manera de hacer esto?
Respuesta:
Probé algunos enfoques diferentes para verificar el correo electrónico del usuario. Por ahora, lo que estoy haciendo es esto:
Cuando un usuario se registra por primera vez, establezca los metadatos de usuario del usuario 'email_not_verified' en 1.
add_action( 'user_register', 'sc_user_email_not_verified' );
function sc_user_email_not_verified( $user_id ) {
update_user_meta( $user_id, 'email_not_verified', 1 );
}
Luego, anule la función wp_new_user_notification
para que agregue un 'email_verification_key' a la URL de inicio de sesión. También guarda esa clave como user_metadata.
function wp_new_user_notification( $user_id, $depreciated = null, $notify = '' ) {
...
$email_verification_key = wp_generate_password( 20, false );
update_user_meta( $user_id, 'email_verification_key', $email_verification_key );
$message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
$message .= __('To set your password, visit the following address:') . "\r\n\r\n";
$message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&mail_key=$email_verification_key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n";
$message .= wp_login_url() . "\r\n";
wp_mail($user->user_email, sprintf(__('[%s] Your username and password info'), $blogname), $message);
}
Luego, conéctese a la acción 'validate_password_reset' para verificar que la clave de verificación de correo electrónico de la solicitud de restablecimiento de contraseña coincida con la clave guardada. Si las claves no coinciden, elimine al usuario y rediríjalo al formulario de registro con un error de 'emailnotverified'. Si las claves coinciden, elimine los metadatos 'email_not_verified'.
add_action( 'validate_password_reset', 'sc_verify_user_email', 10, 2 );
function sc_verify_user_email( $errors, $user ) {
if ( isset( $_REQUEST['mail_key'] ) ) {
$email_verification_key = $_REQUEST['mail_key'];
$saved_key = get_user_meta( $user->ID, 'email_verification_key', true );
if ( ! ( $email_verification_key === $saved_key ) ) {
require_once( ABSPATH . 'wp-admin/includes/user.php' );
wp_delete_user( $user->ID );
wp_redirect( network_site_url( "wp-login.php?action=register&error=emailnotverified" ) );
exit;
} else {
delete_user_meta( $user->ID, 'email_not_verified' );
}
}
}
Si el correo electrónico no está verificado, agregue un mensaje que se mostrará en la página de registro cuando haya un error de "correo electrónico no verificado".
add_filter( 'login_message', 'sc_email_not_verified_message' );
function sc_email_not_verified_message() {
$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
$error = isset( $_REQUEST['error'] ) ? $_REQUEST['error'] : '';
if ( 'register' === $action && 'emailnotverified' === $error ) {
$message = '<p class="message">' . __( 'Your email address could not be verified. Please try registering again.' ) . '</p>';
return $message;
}
}
Dentro de la función de inicio de sesión único, si el usuario tiene los metadatos 'email_not_verified', no inicie sesión en la aplicación cliente. (Esto podría suceder si el usuario fue creado a través de un formulario de registro que fue agregado por un complemento).
$current_user = wp_get_current_user();
if ( get_user_meta( $current_user->ID, 'email_not_verified', true ) ) {
echo( 'Invalid request.' ); // This needs to be changed to a redirect.
exit;
}
También agregué una casilla de verificación para mostrar y anular el estado de verificación del correo electrónico del usuario en la página de "edición de usuario".
Editar:
Conectarse a la acción validate_password_reset
probablemente no sea la mejor manera de hacer esto. Se llama antes de que se restablezca la contraseña, por lo que el correo electrónico se verificará incluso si hay errores en el proceso de restablecimiento de la contraseña (por ejemplo, si la clave está vencida o no es válida).
Un mejor enfoque parece ser engancharse a la acción resetpass_form
y agregar un campo oculto al formulario de restablecimiento de contraseña que contiene el valor de 'mail_key':
add_action( 'resetpass_form' 'sc_mail_key_field' );
function sc_mail_key_field() {
if ( isset( $_REQUEST['mail_key'] ) ) {
$mail_key = sanitize_key( wp_unslash( $_REQUEST['mail_key'] ) );
wp_nonce_field( 'verify_email', 'verify_email_nonce' );
echo '<input type="hidden" name="mail_key" value="' . esc_attr( $mail_key ) . '" />';
}
}
Entonces es posible conectarse a la acción after_password_reset
para verificar la clave de correo guardada con el $_POST['mail_key']
.
Puede encontrar un ejemplo de complemento aquí: complemento de verificación de dirección de correo electrónico