Como detectar en JS si el usuario está logueado exponiendo datos seguros en WordPress

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

  1. Pasar un booleano seguro al script encolado (wp_localize_script / wp_add_inline_script). Opción simple, buena para UI condicional.
  2. Consultar una ruta REST personalizada que valida autenticación y devuelve solo campos permitidos. Opción RESTful y flexible.
  3. 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 🙂



Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *