WordPress «Cookies están bloqueadas»: qué significa realmente y cómo solucionarlo

¿Te fue útil?

Nada eleva más tu tensión que un directivo que te escribe: «No puedo iniciar sesión en WordPress. Dice que las cookies están bloqueadas». Lo pruebas tú mismo. Mismo error. Abres DevTools y… el navegador parece funcionar. Las cookies funcionan en otros sitios. Entonces, ¿por qué WordPress se comporta como si fuera 2004?

Este mensaje no es un diagnóstico. Es WordPress encogiéndose de hombros con gabardina. El problema real casi siempre es uno de estos: cabeceras que no llegan al navegador, detección incorrecta de HTTPS, una caché sirviendo la respuesta equivocada, o un proxy/CDN reescribiendo todo en tonterías. Lo abordaremos como un incidente: reproducir, capturar evidencia, aislar la capa, corregir la causa y añadir salvaguardas para que no vuelva a ocurrir a las 2 a. m.

Qué significa realmente el mensaje (y qué no significa)

Cuando WordPress muestra «Cookies están bloqueadas o no son compatibles con tu navegador», rara vez es culpa del navegador. WordPress muestra esto cuando el flujo de inicio de sesión no puede confirmar el viaje de ida y vuelta de una cookie de sesión.

En términos sencillos, WordPress espera esta secuencia:

  1. Tu navegador solicita /wp-login.php.
  2. El servidor responde con una cabecera Set-Cookie (cookie de prueba o cookie de autenticación según el paso).
  3. Tu navegador devuelve esa cookie en la siguiente petición.
  4. WordPress ve la cookie y continúa. Si no la ve, obtendrás el mensaje «cookies están bloqueadas» o un bucle de redirección.

Si la cookie no vuelve, WordPress no puede saber si estás autenticado, si puedes almacenar cookies en absoluto, o si la petición de inicio de sesión está siendo reproducida desde caché. Entonces WordPress te lanza ese mensaje genérico.

Lo que por lo general no es

  • No es una configuración del navegador, a menos que estés en un entorno muy restringido o probando en un modo de privacidad inusual.
  • No significa «WordPress está caído». La mayoría de los sitios siguen sirviendo páginas bien; solo el inicio de sesión está roto.
  • No es una solución permanente «borrar cookies y volver a intentarlo». Si borrar cookies ayuda, es una pista, no la solución.

Lo que suele ser

  • Cabeceras cambiadas o eliminadas (proxy/CDN/WAF, PHP-FPM mal configurado, reglas de caché incorrectas).
  • Confusión HTTP/HTTPS (WordPress piensa que está en HTTP, establece cookies sin Secure, o genera redirecciones incorrectas).
  • Desajuste de alcance de la cookie (dominio/ruta incorrectos, siteurl y home mal, nombres de host mezclados).
  • Interferencia de caché (caché de página, caché inverso, caché de objetos o CDN que cachea /wp-login.php o respuestas de redirección).
  • Plugins/capas de seguridad que sobrepasan (reescriben cabeceras, inyectan redirecciones, cambian mal las políticas SameSite).

Idea parafraseada atribuida a Werner Vogels (CTO de Amazon): Todo falla a veces; construye sistemas y hábitos que asuman fallos y se recuperen rápido. Esto aplica aquí. Trata el inicio de sesión como una ruta crítica. Obsérvalo, protégelo y no permitas que «borrar cookies» se convierta en tu plan operativo.

Las cookies son sorprendentemente pequeñas para la cantidad de caos que generan. Algunos hechos concretos te darán mejores instintos durante el troubleshooting.

  • Hecho 1: HTTP es sin estado por diseño. Las cookies fueron un parche pragmático para mantener estado entre peticiones sin rediseñar la web.
  • Hecho 2: Las cookies surgieron en la era de Netscape (mediados de los 90). Fueron útiles mucho antes de ser polémicas.
  • Hecho 3: Una cookie es solo una cabecera. Específicamente, el servidor envía Set-Cookie y el cliente devuelve Cookie. Si un proxy manipula las cabeceras, tu “problema de navegador” es en realidad infraestructura.
  • Hecho 4: Los navegadores modernos aplican reglas de cookies mucho más estrictas que antes—especialmente para SameSite, peticiones cross-site y contextos de terceros.
  • Hecho 5: El atributo Secure bloquea cookies sobre HTTP. Excelente para seguridad. Terrible para terminaciones TLS mal configuradas donde la aplicación cree que está en HTTP.
  • Hecho 6: Muchos errores de inicio de sesión se presentan como bucles de redirección, no como errores explícitos de cookies, porque la app sigue intentando establecer una sesión.
  • Hecho 7: WordPress históricamente toleró muchas configuraciones de hosting extrañas (hosting compartido, puertos raros, proxies peculiares). Ese legado significa múltiples maneras de configurar lo mismo—y múltiples maneras de configurarlo mal.
  • Hecho 8: Algunos CDNs y plugins de “optimización” cachean HTML y redirecciones agresivamente. Si cachean las respuestas de wp-login.php, estás sirviendo efectivamente un flujo de inicio de sesión previamente generado a todo el mundo. Eso no es “optimización”; es ruleta.

Broma #1: Las cookies son archivos diminutos que pueden arruinar tu fin de semana. El segundo peor tipo de cookie que puedes encontrar en producción es la que no configuraste.

Guía rápida de diagnóstico (primero/segundo/tercero)

Si haces trabajo de SRE el tiempo suficiente, aprendes a querer un buen playbook. Aquí tienes uno que encuentra al culpable rápido sin deambular por ajustes de plugins como si fuera una casa encantada.

Primero: Prueba si se envía y se devuelve Set-Cookie

  • Captura las cabeceras de respuesta de /wp-login.php y del POST a /wp-login.php.
  • Confirma que el navegador (o curl) envía la cookie de vuelta en la siguiente petición.
  • Si falta Set-Cookie o cambia inesperadamente entre saltos, deja de culpar al navegador.

Segundo: Identifica el “edge” que posee las cabeceras

  • ¿Hay un CDN? ¿Un WAF? ¿Un reverse proxy? ¿Un controlador de ingreso? ¿Una capa de caché Nginx?
  • Evítalo temporalmente (IP/puerto de origen directo, override de hosts, red interna) y compara cabeceras.
  • Si el origen funciona pero el edge falla, ya tienes al sospechoso.

Tercero: Valida las suposiciones de HTTPS y host canónico

  • WordPress debe coincidir con la realidad en: esquema (https), host (www vs apex) y ruta.
  • Revisa siteurl y home en la base de datos.
  • Revisa cabeceras de proxy: X-Forwarded-Proto, X-Forwarded-Host, y los valores de $_SERVER en WordPress.

Cuándo escalar de inmediato

  • Ves respuestas cacheadas para /wp-login.php o /wp-admin/.
  • Las cabeceras Set-Cookie están siendo eliminadas o reescritas por el edge.
  • El sitio está detrás de SSO, proxy corporativo o reglas CSP estrictas que cambiaron recientemente.

Causas raíz que realmente puedes arreglar

1) Esquema o host incorrecto: WordPress establece cookies para el lugar equivocado

Si WordPress piensa que se ejecuta en http:// pero los usuarios se conectan vía https://, las cookies pueden emitirse sin los atributos correctos, las redirecciones pueden rebotar y la cookie de autenticación puede no ser aceptada nunca.

Escenarios comunes:

  • TLS terminado en un balanceador, pero el origen no recibe X-Forwarded-Proto: https.
  • Forzas HTTPS en el edge, pero WordPress aún genera URLs HTTP internamente.
  • Nombres de host canónicos mezclados: el formulario de login hace POST a example.com, pero la cookie es para www.example.com (o viceversa).

2) Capas de caché: el inicio de sesión no debería «optimizarse»

Cualquier caché que almacene o reproduzca respuestas de inicio de sesión puede romper cookies. Esto incluye:

  • Reglas de CDN que accidentalmente incluyen /wp-login.php.
  • fastcgi_cache de Nginx aplicado demasiado ampliamente.
  • Plugins de caché de WordPress que cachean páginas de administración o login.
  • Reglas de edge que cachean respuestas 301/302 con demasiada agresividad.

El inicio de sesión es dinámico. La autenticación es por usuario. Si lo cacheas, no estás acelerando el sitio; estás rompiendo la realidad básica.

3) Atributos SameSite y Secure: los navegadores modernos son más estrictos

Las reglas modernas de cookies son más estrictas con contextos cross-site. La mayoría de los inicios de sesión de WordPress son de primera parte, así que normalmente evitas problemas de SameSite. Pero en el momento en que introduces:

  • formularios de login embebidos,
  • flujos SSO,
  • plugins OAuth con callbacks cross-domain,
  • o configuraciones de «login desde otro dominio»,

…puedes encontrarte con cookies rechazadas a menos que los atributos estén configurados correctamente.

4) Desajuste de dominio/ruta de la cookie causado por deriva de configuración

WordPress tiene múltiples formas de decidir dominio y ruta para las cookies. Si tus WP_HOME, WP_SITEURL, valores en la base de datos y la URL de acceso real no se alinean, puedes establecer cookies para el dominio o ruta incorrectos con facilidad.

5) Plugins de seguridad, WAFs y «endurecimientos» que rompen cabeceras

Los productos de seguridad adoran reescribir cabeceras. A veces lo hacen correctamente. Otras veces eliminan Set-Cookie por «privacidad». O inyectan redirecciones que descartan cookies. O bloquean POSTs a /wp-login.php con reglas demasiado amplias.

6) Salida de PHP antes de las cabeceras (sí, aún ocurre)

Si algo imprime salida antes de que WordPress establezca cookies, PHP puede emitir el comportamiento de “headers already sent”, lo que significa que tu Set-Cookie nunca sale del servidor. Esto suele ocurrir con temas rotos, ediciones personalizadas en wp-config.php o plugins que imprimen espacios en blanco/BOM al inicio de un archivo.

7) Desincronización de relojes y comportamiento raro de TTL

La expiración de cookies depende del tiempo. Si los servidores tienen desincronización de reloj, las cookies pueden parecer inmediatamente expiradas, especialmente en configuraciones multinodo donde un nodo emite y otro valida. Es más raro, pero ocurre.

Broma #2: La sincronización de tiempo es el asesino silencioso—porque nada dice «inicio de sesión seguro» como un servidor que vive en el futuro.

Tareas prácticas: comandos, salidas y decisiones

A continuación están las tareas prácticas que puedes ejecutar desde un host con acceso de red al sitio (o desde el propio servidor web). Cada una incluye una salida de ejemplo realista y la decisión que tomas según ella. Ejecútalas en orden si quieres una traza de evidencia limpia.

Task 1: Fetch /wp-login.php headers and confirm Set-Cookie exists

cr0x@server:~$ curl -skI https://www.example.com/wp-login.php | sed -n '1,20p'
HTTP/2 200
date: Sat, 27 Dec 2025 11:05:12 GMT
content-type: text/html; charset=UTF-8
cache-control: no-store, no-cache, must-revalidate, max-age=0
set-cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly; SameSite=Lax
x-powered-by: PHP/8.2
server: nginx

Qué significa: WordPress está emitiendo una cookie de prueba; eso es bueno. Si no ves set-cookie en absoluto, o bien las cabeceras se están eliminando en upstream o PHP no las está enviando.

Decisión: Si falta, evita el CDN/proxy a continuación (Task 3). Si está presente, verifica que se devuelva (Task 2).

Task 2: Confirm the cookie round-trip works with curl

cr0x@server:~$ curl -sk -c /tmp/cj.txt https://www.example.com/wp-login.php >/dev/null
cr0x@server:~$ cat /tmp/cj.txt
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
www.example.com	FALSE	/	TRUE	0	wordpress_test_cookie	WP%20Cookie%20check
cr0x@server:~$ curl -sk -b /tmp/cj.txt -I https://www.example.com/wp-login.php | grep -i set-cookie
set-cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly; SameSite=Lax

Qué significa: curl almacenó y reenvió la cookie con éxito. Si el servidor aún se queja en el navegador, el problema puede ser caché, redirecciones o desalineación de host/esquema en la ruta del navegador.

Decisión: Si el viaje de ida y vuelta con curl funciona pero los navegadores fallan, inspecciona redirecciones y canonización de dominio (Tasks 4–6).

Task 3: Bypass the CDN/reverse proxy by hitting the origin (or internal LB) directly

cr0x@server:~$ curl -sI http://10.20.30.40/wp-login.php | sed -n '1,15p'
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=UTF-8
Set-Cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; HttpOnly; SameSite=Lax

Qué significa: El origen establece la cookie, pero nota que falta Secure sobre HTTP. Si los usuarios acceden vía HTTPS en el edge, WordPress puede necesitar que se le indique que está en HTTPS para que establezca atributos y URLs correctos.

Decisión: Corrige la detección de HTTPS detrás del proxy (ver Tasks 10–11) y asegura que el edge reenvíe X-Forwarded-Proto.

Task 4: Check redirect chain for login and admin

cr0x@server:~$ curl -skIL https://example.com/wp-admin/ | sed -n '1,40p'
HTTP/2 301
location: https://www.example.com/wp-admin/
cache-control: max-age=3600
date: Sat, 27 Dec 2025 11:06:11 GMT

HTTP/2 302
location: https://www.example.com/wp-login.php?redirect_to=https%3A%2F%2Fwww.example.com%2Fwp-admin%2F&reauth=1
set-cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly; SameSite=Lax

HTTP/2 200
content-type: text/html; charset=UTF-8

Qué significa: Las redirecciones son esperadas, pero nota cache-control: max-age=3600 en una redirección canónica. Si tu CDN cachea ese 301/302 con agresividad para rutas de inicio de sesión, puedes quedar atrapado en un bucle o servir respuestas obsoletas.

Decisión: Agrega reglas de “no cache” para /wp-login.php, /wp-admin/ y redirecciones relacionadas con auth en el CDN/proxy.

Task 5: Verify siteurl and home in the database

cr0x@server:~$ mysql -u wpuser -p -D wordpress -e "SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');"
+-------------+------------------------+
| option_name | option_value           |
+-------------+------------------------+
| home        | https://example.com    |
| siteurl     | https://www.example.com|
+-------------+------------------------+

Qué significa: Nombres de host mezclados. Esto es un generador clásico de desajustes de alcance de cookie y puede producir bucles de login.

Decisión: Haz que coincidan con tu host canónico (usualmente ambos https://www.example.com o ambos apex). Actualiza con cuidado (Task 6) y asegura redirecciones consistentes.

Task 6: Fix home and siteurl (carefully)

cr0x@server:~$ mysql -u wpuser -p -D wordpress -e "UPDATE wp_options SET option_value='https://www.example.com' WHERE option_name IN ('home','siteurl');"
cr0x@server:~$ mysql -u wpuser -p -D wordpress -e "SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');"
+-------------+-----------------------+
| option_name | option_value          |
+-------------+-----------------------+
| home        | https://www.example.com |
| siteurl     | https://www.example.com |
+-------------+-----------------------+

Qué significa: Host canónico alineado. Esto a menudo resuelve rarezas de dominio/ruta de cookie y bucles de redirección.

Decisión: Vuelve a probar el inicio de sesión. Si sigue roto, pasa a la inspección de cabeceras en el edge (Task 7) y comprobaciones de caché (Task 8).

Task 7: Compare edge vs origin Set-Cookie and cache headers

cr0x@server:~$ curl -skI https://www.example.com/wp-login.php | egrep -i 'set-cookie|cache-control|server|via|cf-cache-status|x-cache'
server: cloudflare
cf-cache-status: HIT
cache-control: public, max-age=14400

Qué significa: Un CDN cacheó /wp-login.php. Eso no es una pista; es un cráter humeante.

Decisión: Evita inmediatamente la caché para rutas de login/admin en el CDN y purga los objetos cacheados. Luego vuelve a probar.

Task 8: Inspect Nginx config for caching of login/admin paths

cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '/fastcgi_cache/,+25p'
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=PHP:100m inactive=60m;
map $request_uri $skip_cache {
    default 0;
    ~*/wp-admin/ 1;
    ~*/wp-login.php 1;
}
server {
    location ~ \.php$ {
        fastcgi_cache PHP;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        add_header X-Cache $upstream_cache_status;
    }
}

Qué significa: Esta configuración está haciendo lo correcto: evita caché para login/admin. Si tu configuración carece de estas exclusiones, puedes romper la autenticación.

Decisión: Si falta, añade exclusiones y recarga Nginx. Si están presentes, verifica si el map realmente coincide con tus rutas (algunas configuraciones usan prefijos distintos o reescrituras).

Task 9: Test whether login/admin responses are being cached anyway

cr0x@server:~$ curl -skI https://www.example.com/wp-login.php | egrep -i 'x-cache|cache-control|set-cookie'
cache-control: no-store, no-cache, must-revalidate, max-age=0
set-cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly; SameSite=Lax
x-cache: MISS

Qué significa: No-store y un miss de caché es saludable. Si ves HIT o cabeceras de cache público, arregla las reglas de caché primero.

Decisión: Si la caché está limpia, céntrate en esquema/cabeceras reenviadas y atributos de la cookie.

Task 10: Verify the reverse proxy forwards HTTPS indication

cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '/proxy_set_header X-Forwarded-Proto/,+10p'
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

Qué significa: El proxy reenvía el esquema que ve. Si TLS termina antes de este proxy, $scheme podría ser http incluso para usuarios HTTPS, lo cual es incorrecto.

Decisión: Si TLS termina en un balanceador upstream, establece X-Forwarded-Proto https allí, o pasa la cabecera original y confía en ella cuidadosamente.

Task 11: Confirm WordPress sees HTTPS on the origin

cr0x@server:~$ php -r 'var_export([ "HTTPS"=>($_SERVER["HTTPS"]??null), "HTTP_X_FORWARDED_PROTO"=>($_SERVER["HTTP_X_FORWARDED_PROTO"]??null) ]);'
array (
  'HTTPS' => NULL,
  'HTTP_X_FORWARDED_PROTO' => NULL,
)

Qué significa: En este contexto de shell no tienes cabeceras de la petición, pero resalta lo que buscas en un contexto de petición real: WordPress depende de variables de servidor. Si las peticiones no las llenan, WordPress puede comportarse mal detrás de proxies.

Decisión: Añade un endpoint diagnóstico temporal pequeño o registra cabeceras reenviadas en el servidor web; luego ajusta la configuración del proxy o la conciencia de proxy de WordPress (comúnmente vía wp-config.php y patrones de proxies confiables).

Task 12: Check for “headers already sent” in PHP/WordPress logs

cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log | egrep -i 'headers already sent|warning|notice' | tail
WARNING: [pool www] child 18124 said into stderr: "PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/bad-plugin/bad.php:1) in /var/www/html/wp-includes/pluggable.php on line 1427"

Qué significa: Un plugin imprimió salida temprano, así que WordPress no puede establecer cookies/cabeceras de forma fiable.

Decisión: Desactiva el plugin problemático (Task 13) y corrígelo/reemplázalo. No «soluciones parche» esto; es código roto.

Task 13: Disable plugins quickly without wp-admin

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ sudo mv wp-content/plugins wp-content/plugins.disabled
cr0x@server:~$ sudo mkdir wp-content/plugins
cr0x@server:~$ sudo chown -R www-data:www-data wp-content/plugins

Qué significa: WordPress cargará sin plugins, lo cual a menudo basta para restaurar el inicio de sesión. Es una medida contundente. Funciona.

Decisión: Si ahora el login funciona, reintroduce plugins por lotes para encontrar al culpable. Si sigue fallando, el problema está en capas inferiores (proxy/caché/config).

Task 14: Check system time sync (for multi-node and expiry weirdness)

cr0x@server:~$ timedatectl status | sed -n '1,12p'
Local time: Sat 2025-12-27 11:08:42 UTC
Universal time: Sat 2025-12-27 11:08:42 UTC
RTC time: Sat 2025-12-27 11:08:42
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active

Qué significa: La sincronización de tiempo es saludable. Si no está sincronizada (o difiere entre nodos), la expiración de cookies y las comprobaciones de nonce pueden fallar.

Decisión: Arregla NTP/chrony antes de profundizar más. La deriva de tiempo crea problemas de autenticación “aleatorios” que te hacen perder días.

Task 15: Verify the response isn’t compressing/transforming in a way that breaks headers (proxy sanity)

cr0x@server:~$ curl -skI https://www.example.com/wp-login.php | egrep -i 'content-encoding|set-cookie|vary'
set-cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly; SameSite=Lax
vary: Accept-Encoding

Qué significa: Normal. Si ves manipulación exótica de cabeceras o cookies faltantes solo cuando cierta función de “optimización” está activada, esa función es culpable hasta que se demuestre lo contrario.

Decisión: Apaga la función transformadora de cabeceras en el edge y vuelve a probar. Luego reactívala con exclusiones correctas.

Task 16: Inspect browser-visible cookie attributes via a server-side reproduction (optional but decisive)

cr0x@server:~$ curl -skD - https://www.example.com/wp-login.php -o /dev/null | sed -n '/^Set-Cookie/Ip'
Set-Cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly; SameSite=Lax

Qué significa: Confirma los atributos exactos de la cookie que salen del servidor. Si los navegadores aún la rechazan, suele ser desajuste de dominio, contexto de terceros o política empresarial.

Decisión: Compara el host solicitado vs Domain/Path de la cookie; verifica embebidos cross-site; prueba desde un perfil limpio y desde otra red.

Tres microhistorias corporativas desde el frente

Microhistoria 1: El incidente causado por una suposición errónea

La empresa tenía una instancia de WordPress para notas de prensa y actualizaciones para inversores. No era “crítica” hasta que lo fue—el día de resultados, el equipo de comunicaciones no pudo iniciar sesión. El sitio se mostraba bien al público, lo que hizo que la dirección asumiera que era “error de usuario”. Clásico.

El ingeniero de guardia comprobó lo obvio: cookies del navegador habilitadas, modo incógnito, otro portátil. Mismo error. Cogieron cabeceras con curl y notaron algo sutil: la respuesta de la página de login no tenía Set-Cookie en la URL pública, pero sí cuando se accedía al origen directamente.

La suposición errónea fue creer que el CDN “solo cacheaba assets estáticos”. No era así. Alguien había activado una regla para cachear «todo el HTML por rendimiento», con una excepción para /wp-admin pero no para /wp-login.php. El CDN cacheó una respuesta de login que nunca estableció un viaje de cookie válido, y la sirvió fielmente a todos.

La solución fue sencilla: evitar la caché para endpoints de login y admin, purgar la caché y añadir una comprobación de regresión en su monitorización sintética para afirmar la presencia de Set-Cookie en el login. La lección: las suposiciones sobre capas que no tocas con regularidad son caras cuando fallan.

Microhistoria 2: La optimización que salió mal

Otra organización quería reducir el Time To First Byte en páginas PHP. Alguien desplegó fastcgi_cache de Nginx en el clúster de WordPress. Funcionó de maravilla en staging. En producción parecía más rápido. Las métricas mejoraron. Todo el mundo se felicitó y se fue a comer.

Dos días después, los editores comenzaron a informar bucles de login intermitentes. No constantes. No reproducibles a demanda. El peor tipo de bug: el que hace que la gente discuta si es real.

Finalmente, un ingeniero añadió una cabecera X-Cache y descubrió que ciertas respuestas 302 alrededor de la autenticación se estaban cacheando bajo condiciones imprevistas. La clave de caché no incluía suficiente variación, y la lógica de «saltar caché» no detectó un endpoint de login reescrito por un plugin de seguridad.

La corrección requirió endurecer las reglas de bypass de caché, excluir explícitamente wp-login.php, wp-admin y cualquier alias de login, y asegurar que las cookies en la petición forzaran el bypass. El rendimiento se mantuvo mayormente mejorado, pero el equipo aprendió una regla valiosa: cachear flujos de auth dinámicos es como poner un turbo a una bicicleta—técnicamente posible, socialmente irresponsable.

Microhistoria 3: La práctica aburrida pero correcta que salvó el día

Una empresa ejecutaba WordPress detrás de un balanceador y dos reverse proxies, por “cumplimiento”. También tenían un hábito que sonaba aburrido: cada cambio en reglas de edge requería pasar un pequeño script de verificación antes del despliegue.

El script hacía tres comprobaciones: obtener /wp-login.php y afirmar que existe Set-Cookie; obtener /wp-admin/ y asegurar que no devuelve cabeceras cacheables; y confirmar que las redirecciones terminan en un host canónico y HTTPS.

Un equipo de seguridad empujó una actualización a su plantilla WAF. Involuntariamente, eliminó Set-Cookie de respuestas que coincidían con una firma genérica de “cookie de seguimiento”. Eso habría dejado inservible el login de administración en una docena de sitios.

Pero la canalización de despliegue bloqueó el cambio porque la verificación falló en preproducción. La solución fue una excepción WAF para cookies de autenticación de WordPress y una firma más precisa. No ocurrió nada dramático en producción, que es el mejor tipo de incidente. Su puerta aburrida salvó el día previniendo una caída que nadie hubiera entendido en una llamada de dirección.

Errores comunes: síntoma → causa raíz → solución

Esta sección es la lista de “deja de adivinar”. Si ves el síntoma, salta a la causa probable y aplica la solución. Evita pasos de culto cargo.

1) Síntoma: «Cookies están bloqueadas» aparece inmediatamente después de enviar credenciales

  • Causa raíz: Set-Cookie nunca llega al navegador (eliminado por CDN/WAF/proxy) o cabeceras ya enviadas en PHP.
  • Solución: Compara cabeceras edge vs origen; desactiva caché del CDN para login; revisa logs de PHP-FPM por “Cannot modify header information”.

2) Síntoma: Bucle infinito entre /wp-admin y /wp-login.php

  • Causa raíz: Desajuste de esquema/host (siteurl/home desalineados), o proxy que reporta mal HTTPS.
  • Solución: Alinea home y siteurl; asegura que X-Forwarded-Proto sea correcto; aplica un único nombre de host canónico.

3) Síntoma: Funciona en el origen, falla en el dominio público

  • Causa raíz: Capa edge reescribiendo/eliminando Set-Cookie, cacheando respuestas de login, o aplicando protección de bots agresiva.
  • Solución: Evita caché para /wp-login.php y /wp-admin; desactiva caché HTML; añade una excepción WAF para estas rutas.

4) Síntoma: Funciona en un navegador/perfil pero no en otro

  • Causa raíz: Cookies antiguas con Domain/Path desajustados, o una extensión del navegador que altera peticiones, o políticas empresariales estrictas.
  • Solución: Inspecciona almacenamiento de cookies para el dominio; elimina solo cookies de WordPress; prueba en un perfil limpio; revisa si el login está embebido/cross-site.

5) Síntoma: Solo algunos usuarios pueden iniciar sesión, a menudo detrás de redes corporativas

  • Causa raíz: Proxy corporativo que elimina cabeceras, interceptación TLS o políticas que bloquean cookies en ciertos contextos.
  • Solución: Captura cabeceras desde las redes afectadas; proporciona un login no embebido; asegura que las cookies sean de primera parte y usa HTTPS de forma consistente.

6) Síntoma: Rompe después de habilitar «forzar HTTPS» en el edge

  • Causa raíz: WordPress aún piensa que está en HTTP, establece redirecciones/cookies incorrectas o genera URLs mixtas.
  • Solución: Reenvía cabeceras HTTPS correctamente y configura WordPress para reconocer HTTPS detrás de proxies; alinea URLs en la BD.

7) Síntoma: Fallos de login en Multisite en varios subdominios

  • Causa raíz: Escopado de dominio de cookie que no coincide con la configuración de la red, además de canonización inconsistente entre sitios.
  • Solución: Asegura mapeo de dominios consistente; evita mezclar modos subdominio y subdirectorio por accidente; verifica settings de la red y comportamiento de domain cookie.

8) Síntoma: Comportamiento aleatorio de “desconexión” después de iniciar sesión correctamente

  • Causa raíz: Caché mezclando estados autenticados y no autenticados, o deriva de tiempo entre nodos, o colisiones en el caché de objetos.
  • Solución: Asegura que las cachés hagan bypass con cookies de auth; verifica NTP; valida la configuración del caché de objetos y las salts.

Listas de verificación / plan paso a paso

Checklist A: Triages en una pasada (15 minutos)

  1. Reproducir en un perfil de navegador limpio. Registra la URL exacta y si usas www o apex.
  2. Comprobar cabeceras en /wp-login.php en la URL pública: confirma que existe Set-Cookie y que cache-control no es público.
  3. Comprobar cadena de redirecciones para /wp-admin/. Confirma que termina en un host https:// canónico.
  4. Evitar el edge (acceder al origen/LB directamente) y comparar el comportamiento de Set-Cookie.
  5. Desactivar plugins si los logs muestran “headers already sent” o si el comportamiento cambia por petición.

Checklist B: Hacer la fijación duradera (el plan «no me despertará otra vez»)

  1. Canonizar host y esquema: elige uno (normalmente https://www o https:// apex) y usa lo mismo en todas partes.
  2. Asegurar reglas de caché:
    • Nunca cachear /wp-login.php, /wp-admin/ o respuestas que establezcan cookies de auth.
    • Hacer bypass de caché cuando la petición tenga cookies de auth de WordPress.
    • No cachear 302/301 desde endpoints de auth a menos que comprendas profundamente el alcance.
  3. Hacer correctas las cabeceras de proxy: asegurar que HTTPS se señalice correctamente al origen y que solo proxies confiables puedan establecer cabeceras reenviadas.
  4. Añadir comprobaciones sintéticas que afirmen:
    • Set-Cookie existe en /wp-login.php
    • no hay cabeceras públicas de caché en login/admin
    • la cadena de redirecciones termina en host canónico
  5. Minimizar plugins de «ajustes de login». Muchos están bien, pero cualquier cosa que toque cabeceras, redirecciones o cookies debe tratarse como middleware de producción.
  6. Mantener relojes sincronizados entre nodos, siempre.

Checklist C: Si debes cambiar algo durante un incidente

  1. Purgar la caché del CDN para /wp-login.php y /wp-admin/ (y cualquier alias de login).
  2. Desactivar temporalmente cache HTML/funciones de optimización de edge para esas rutas.
  3. Desactivar plugins renombrando el directorio de plugins (rollback rápido).
  4. Revertir el último cambio de edge/WAF/plantilla si esto empezó «justo después» de un despliegue.

Preguntas frecuentes

1) ¿WordPress miente cuando dice que las cookies están bloqueadas?

No miente; es impreciso. WordPress no puede confirmar el viaje de ida y vuelta de la cookie, así que achaca la culpa a las “cookies” incluso si el verdadero problema es tu proxy o caché.

2) ¿Por qué funciona para páginas públicas pero no para wp-admin?

Las páginas públicas pueden cachearse y no requieren sesión autenticada. El login sí. Cualquier cosa que rompa Set-Cookie, redirecciones o detección de HTTPS se manifestará primero en wp-admin.

3) ¿Un CDN puede realmente romper el login de WordPress?

Sí. Si cachea /wp-login.php, cachea redirecciones en la cadena de login, elimina Set-Cookie o aplica protección de bots que bloquea POSTs, verás fallos de cookie/login.

4) ¿Cuál es la causa más común en entornos modernos?

La caché o «optimización» aplicada a endpoints de login/admin. En segundo lugar: terminación HTTPS/proxy que no transmite cabeceras correctamente a WordPress.

5) ¿Necesito cambiar ajustes de SameSite?

No suele ser necesario para inicios de sesión estándar de WordPress. Considera SameSite cuando tengas SSO cross-domain, login embebido o callbacks externos. Si lo cambias, prueba en varios navegadores y no adivines.

6) ¿Por qué arreglar home y siteurl lo soluciona?

Porque WordPress usa esos valores para generar URLs y a veces para inferir el alcance de las cookies. Si uno dice example.com y otro www.example.com, invitas a desajustes de cookies y bucles de redirección.

7) Desactivé todos los plugins y sigue fallando. ¿Ahora qué?

Entonces probablemente sea infraestructura: caché de edge, reescritura de cabeceras, detección de HTTPS o desajuste de URLs en la base de datos. Compara cabeceras edge vs origen y revisa cadenas de redirección.

8) ¿La deriva de tiempo realmente puede causar problemas de login?

Sí, especialmente en entornos multinodo. Cookies, nonces y validación de sesión pueden comportarse como si la cookie fuera “ignorada” cuando las marcas de tiempo no coinciden.

9) ¿Debo simplemente decir a los usuarios que borren cookies?

Sólo como solución temporal y solo después de haber recogido evidencia. Si borrar cookies “arregla” el problema, aún tienes un desajuste sistémico o de caché que volverá a ocurrir.

10) ¿Y si el error solo aparece en móvil o dentro de un webview embebido?

Entonces podrías estar tratando con restricciones de cookies de terceros, políticas de navegadores in-app o flujos cross-site. Evita login embebido, mantenlo de primera parte y verifica los atributos de la cookie para ese contexto.

Conclusión: siguientes pasos que perduran

«Cookies están bloqueadas» es la forma en que WordPress te dice que falló un handshake de sesión. Tu trabajo es descubrir qué capa mintió: la app, el proxy, la caché o la configuración. El camino más rápido es la evidencia, no las corazonadas: captura cabeceras, compara edge vs origen, inspecciona redirecciones y confirma esquema/host canónicos.

Haz esto a continuación, en orden:

  1. Ejecuta una comprobación de cabeceras en /wp-login.php y confirma Set-Cookie y ausencia de cache público.
  2. Sigue la cadena de redirecciones para /wp-admin/ y elimina host/esquema mixtos.
  3. Evita tu edge y compara. Si el origen funciona, arregla reglas del edge (caché y manejo de cabeceras).
  4. Si ves “headers already sent”, desactiva el plugin problemático y trátalo como defecto de código, no como rareza de configuración.
  5. Añade una comprobación sintética pequeña para que nunca te entere de este problema por un ejecutivo frustrado otra vez.
← Anterior
Passthrough PCIe en Proxmox vs ESXi: GPUs, HBAs, NICs — qué es más fácil y qué es más rápido
Siguiente →
Debian 13: los core dumps llenan tu disco — conserva valor para depurar, elimina el bulto

Deja un comentario