Contents
Introducción — objetivo y alcance
Este artículo explica, con todo lujo de detalles, cómo detectar desde JavaScript si un visitante de un sitio WordPress está autenticado y cómo exponer esa información de forma segura (sin filtrar datos sensibles). Se muestran tres enfoques prácticos, sus ventajas/desventajas y recomendaciones de seguridad para evitar fugas de información y ataques CSRF/XSS/CORS.
Aclaración sobre seguridad y modelo de amenazas
- Qué se quiere conseguir: que código cliente (JS) conozca si el usuario está logueado y, opcionalmente, reciba sólo datos no sensibles (por ejemplo: id público, display_name o roles de forma muy limitada).
- Qué NO se debe hacer: incrustar en el frontend datos sensibles (passwords, tokens privados, emails no públicos, meta sensibles), exponer endpoints REST sin control de permisos o CORS, y generar variables globales con información privada.
- Requisitos seguros: siempre HTTPS, validación en servidor de permisos, uso de nonces para llamadas que mutan o recuperan datos sensibles, y mínimo privilegio en los datos devueltos.
Resumen de métodos
- Pasar un booleano seguro al script encolado (wp_localize_script / wp_add_inline_script). Opción simple, buena para UI condicional.
- Consultar una ruta REST personalizada que valida autenticación y devuelve solo campos permitidos. Opción RESTful y flexible.
- Usar admin-ajax con acciones protegidas por check_ajax_referer y comprobaciones de capacidad. Opción retrocompatible.
1) Método simple: booleano seguro inyectado en el script
Este enfoque consiste en encolar tu script y pasarle una estructura mínima con un booleano que indique si el usuario está logueado. Nunca incluyas más que lo estrictamente necesario.
Ejemplo: functions.php (enqueue datos seguros)
// functions.php
function miplugin_enqueue_scripts() {
wp_enqueue_script(
miplugin-frontend,
plugin_dir_url(__FILE__) . assets/js/miplugin-frontend.js,
array(),
1.0,
true
)
// Solo pasamos un booleano (evitar datos sensibles)
data = array(
isLoggedIn => is_user_logged_in()
)
// wp_localize_script convierte a objeto JS de forma segura
wp_localize_script(miplugin-frontend, MiPluginData, data)
}
add_action(wp_enqueue_scripts, miplugin_enqueue_scripts)
Ejemplo: JavaScript que consume la variable
// assets/js/miplugin-frontend.js
if (typeof MiPluginData !== undefined MiPluginData.isLoggedIn) {
// Cambiar comportamiento visual sin exponer datos del usuario
document.documentElement.classList.add(user-logged-in)
} else {
document.documentElement.classList.remove(user-logged-in)
}
Pros/Contras
- Pros: sencillo, sin llamadas adicionales, buena para ajustar interfaz.
- Contras: solo informa si hay sesión no sirve para obtener datos adicionales sobre el usuario sin crear endpoints adicionales seguros.
2) Método REST seguro: ruta personalizada con comprobaciones
Para obtener información adicional no sensible (por ejemplo display_name o ID público) pero manteniendo control, registre una ruta REST que valide permisos y devuelva solo campos permitidos. Use nonces o la cabecera X-WP-Nonce que WordPress espera para peticiones autenticadas desde el frontend.
Registrar la ruta REST (PHP)
// functions.php o plugin principal
add_action(rest_api_init, function () {
register_rest_route(miplugin/v1, /me, array(
methods => GET,
callback => miplugin_rest_get_me,
permission_callback => function () {
// Solo usuarios autenticados pueden acceder a esta ruta
return is_user_logged_in()
},
))
})
function miplugin_rest_get_me( request ) {
user = wp_get_current_user()
// Devolver solo campos no sensibles
return array(
id => user->ID,
display_name => user->display_name,
// No devolver email ni meta sensibles a menos que sea imprescindible
)
}
Pasar nonce al frontend (opcional pero recomendado)
// functions.php: encolar script y pasar nonce para peticiones REST autenticadas
function miplugin_enqueue_with_nonce() {
wp_enqueue_script(miplugin-frontend, plugin_dir_url(__FILE__) . assets/js/miplugin-frontend.js, array(), 1.0, true)
data = array(
restUrl => esc_url_raw( rest_url(miplugin/v1/me) ),
nonce => wp_create_nonce(wp_rest)
)
wp_localize_script(miplugin-frontend, MiPluginData, data)
}
add_action(wp_enqueue_scripts, miplugin_enqueue_with_nonce)
Consumir la ruta REST desde JS
// assets/js/miplugin-frontend.js
if (typeof MiPluginData !== undefined) {
fetch(MiPluginData.restUrl, {
method: GET,
credentials: same-origin,
headers: {
X-WP-Nonce: MiPluginData.nonce,
Accept: application/json
}
})
.then(response => {
if (!response.ok) throw new Error(No autorizado o error en la petición)
return response.json()
})
.then(data => {
// data: { id, display_name }
console.log(Usuario autenticado:, data)
})
.catch(err => {
// Usuario no autenticado o error
console.log(Estado no autenticado o error, err)
})
}
Buenas prácticas al usar REST
- Configurar permission_callback que valide is_user_logged_in() y/o capacidades concretas (current_user_can).
- Devolver únicamente los campos que realmente necesitas.
- Proteger con nonces y usar X-WP-Nonce para peticiones desde el frontend.
- No permitir CORS públicos para endpoints que devuelvan datos de usuario.
3) admin-ajax.php y acciones AJAX seguras
Común en desarrollos legacy. Use check_ajax_referer para CSRF y current_user_can/is_user_logged_in para permisos.
Registrar la acción y comprobar nonce
// functions.php
add_action(wp_ajax_miplugin_get_me, miplugin_ajax_get_me) // sólo usuarios autenticados
function miplugin_ajax_get_me() {
check_ajax_referer(miplugin-nonce, security)
if (!is_user_logged_in()) {
wp_send_json_error(No autenticado, 401)
}
user = wp_get_current_user()
wp_send_json_success(array(
id => user->ID,
display_name => user->display_name
))
}
JS que llama a admin-ajax
// Encolar y pasar nonce similar con wp_localize_script
fetch(ajaxurl, {
method: POST,
credentials: same-origin,
headers: { Content-Type: application/x-www-form-urlencoded charset=UTF-8 },
body: new URLSearchParams({
action: miplugin_get_me,
security: MiPluginData.nonce
})
})
.then(r => r.json())
.then(resp => {
if (resp.success) {
console.log(Usuario:, resp.data)
} else {
console.log(No autenticado o error)
}
})
Recomendaciones de seguridad detalladas
- Minimizar datos: siempre enviar lo mínimo imprescindible. Un booleano muchas veces es suficiente.
- Validación en servidor: nunca confíes en el estado informado por JS. Todas las decisiones sensibles se deben validar en servidor.
- Nonces y CSRF: para acciones que cambien estado o devuelvan datos con riesgo, use check_ajax_referer o X-WP-Nonce en peticiones REST.
- HTTPS: obligatorio para proteger cookies de sesión y evitar MITM.
- Cookies seguras: marque cookies de autenticación como HttpOnly (lo hace WP para algunas cookies) y SameSite según necesidad.
- Escapar y sanitizar: use esc_html, esc_attr y wp_json_encode cuando inyecte datos en JS evite concatenación insegura.
- CORS: no permita orígenes no confiables para endpoints que devuelvan datos de usuario.
- Audit logs y límites: para endpoints sensibles, registre y limite peticiones (rate limit) y revise logs de auditoría si es necesario.
Errores comunes y cómo evitarlos
- Inyectar email/password/token en window.: nunca lo haga. Use sólo banderas o datos públicos mínimos.
- REST sin permission_callback: Evítelo eso permitirá que cualquier visitante acceda a la ruta.
- Depender solo de JS para control de acceso: el frontend es manipulable todas las comprobaciones aplicativas deben ocurrir en servidor.
Checklist rápido antes de publicar
- ¿Solo paso un booleano o datos no sensibles? Sí/No
- ¿Las rutas que devuelven información tienen permission_callback adecuada? Sí/No
- ¿Uso HTTPS y nonces para llamadas autenticadas? Sí/No
- ¿He revisado que no expondré metadata sensible en JSON? Sí/No
Conclusión
Detectar si un usuario está logueado desde JavaScript en WordPress es sencillo si se hace con prudencia. Para cambios visuales basta con pasar un booleano seguro vía wp_localize_script para información adicional use rutas REST o admin-ajax protegidas con nonces y permission callbacks. La clave es exponer lo mínimo, validar todo en el servidor y blindar las llamadas con HTTPS y controles de acceso.
|
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |
