"MQTT connection refused: not authorized" significa que el broker recibió tu paquete CONNECT, lo entendió y decidió que este cliente no puede conectarse. En MQTT 3.1.1 es el código de retorno CONNACK 5; en MQTT 5 es el reason code 0x87. Esta guía te ofrece una lista de comprobación paso a paso para encontrar la causa, desde las credenciales y los client ID hasta las confusiones de puertos y las cuentas por broker, y muestra cómo probar cada paso desde la línea de comandos.
Qué te dice realmente "Not Authorized"
El error es más informativo de lo que parece. Para recibirlo, varias cosas tienen que funcionar ya:
- El DNS resolvió el host del broker.
- Se estableció la conexión TCP y, si se usa, TLS.
- El broker interpretó un paquete CONNECT válido.
- Se aceptó la versión del protocolo.
Así que la red está bien. El problema es de identidad o de permisos. Lo verás redactado de distintas formas según la herramienta:
| Herramienta | Mensaje típico |
|---|---|
| mosquitto_pub / mosquitto_sub | Connection error: Connection Refused: not authorised. |
| Paho Python 2.x | reason_code es igual a Not authorized en on_connect |
| MQTT.js | Connection refused: Not authorized (err.code === 5) o reason code 135 con MQTT 5 |
| Nodo MQTT de Node-RED | El estado muestra "connecting" y el registro indica conexión rechazada, no autorizado |
Conviene distinguir pronto un código relacionado. El código de retorno 4 (0x86 en MQTT 5) significa "bad user name or password": las propias credenciales no coincidían. El código 5 (0x87) es más amplio: el broker rechaza a este cliente por un motivo de autorización. Algunos brokers también devuelven 5 ante contraseñas erróneas, así que trata ambos como "revisar la identidad", pero lee el código exacto. La guía de códigos de retorno CONNACK de MQTT explica todos los valores.
Lista de comprobación para el error Not Authorized
Recorre estos pasos en orden. La mayoría de los casos se resuelven antes del paso 4.
- Confirma a qué broker te conectas. Imprime el host y el puerto que tu código usa realmente en tiempo de ejecución, no los que crees haber configurado. Las variables de entorno y los archivos de configuración se sobrescriben entre sí con frecuencia.
- Vuelve a copiar las credenciales. Pega el usuario y la contraseña directamente desde la página de credenciales del broker. Busca espacios al principio o al final, saltos de línea al copiar y usuario y contraseña intercambiados.
- Usa el client ID que pertenece a las credenciales. Muchos brokers MQTT gestionados vinculan un client ID a la cuenta emitida. Si tu código genera un ID aleatorio o reutiliza uno de otro proyecto, el broker puede rechazarlo aunque la contraseña sea correcta.
- Comprueba que la librería envía las credenciales. En Paho, hay que llamar a
username_pw_set()antes deconnect(). En PubSubClient de Arduino, usa la sobrecargaconnect(clientId, user, pass), noconnect(clientId). - Revisa el entrecomillado del shell. Bash altera las contraseñas que contienen
$,!o&. Usa comillas simples:-P 'p@ss$word!'. - Verifica el puerto y el transporte. El puerto 1883 es TCP sin cifrar, el 8883 es TLS, el 8083 es WebSocket y el 8084 es WebSocket seguro con la ruta
/mqtt. Una discrepancia suele producir un timeout o un error de TLS en lugar de "not authorized", pero un cliente mal configurado puede acabar hablando con otro listener u otro entorno distinto del previsto. - Confirma que la cuenta está activa. Puede que las credenciales se hayan regenerado, que un broker se haya eliminado o recreado, o que estés usando credenciales de staging contra producción.
- Comprueba las cuotas de conexión. Si se alcanza el límite de conexiones del plan, los clientes MQTT 5 reciben
0x97 Quota exceeded, pero algunas librerías 3.1.1 muestran cualquier rechazo de forma genérica. Cuenta tus conexiones activas. - Deja de reintentar en bucle. Cada intento fallido es, desde el punto de vista del broker, un inicio de sesión fallido. Espera entre reintentos mientras investigas.
Probar las credenciales desde la línea de comandos
Aísla tu aplicación del problema probando exactamente las mismas credenciales con las herramientas de Mosquitto. Primero, demuestra que la ruta de red funciona con el servidor MQTT público gratuito, que es anónimo:
mosquitto_sub -h broker.connectmq.com -p 1883 -i auth-check-2d9f \
-t "connectmq/demo/2d9f/#" -d -C 1 -W 5
Si ves received CONNACK (0), tu equipo puede llegar al broker y hablar MQTT. A continuación, prueba tus credenciales privadas sobre TLS:
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-u 'YOUR_USERNAME' -P 'YOUR_PASSWORD' -i 'YOUR_CLIENT_ID' \
-t "test/#" -d -V mqttv5
Con -V mqttv5, un rechazo imprime el reason code de MQTT 5, que es más específico que el código de 3.1.1. Si este comando se conecta pero tu aplicación no, el problema está en la configuración de la aplicación, no en la cuenta. Si este comando también falla, el problema son las credenciales, el client ID o la cuenta.
En Windows, --capath no está disponible de la misma forma; usa en su lugar --cafile con un archivo de bundle de CA, o prueba con un cliente MQTT gráfico.
Solucionarlo en el código
Este es un cliente Python que imprime la configuración que realmente está usando y se detiene ante errores de autorización en lugar de reintentar indefinidamente:
import os
import ssl
import paho.mqtt.client as mqtt
HOST = os.getenv("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.getenv("MQTT_PORT", "8883"))
USERNAME = os.getenv("MQTT_USERNAME", "YOUR_USERNAME")
PASSWORD = os.getenv("MQTT_PASSWORD", "YOUR_PASSWORD")
CLIENT_ID = os.getenv("MQTT_CLIENT_ID", "YOUR_CLIENT_ID")
print(f"Connecting to {HOST}:{PORT} as user={USERNAME!r} client_id={CLIENT_ID!r}")
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print(f"Refused: {reason_code} (0x{reason_code.value:02X})")
if reason_code.value in (0x85, 0x86, 0x87):
print("Identity problem: check username, password and client ID")
client.disconnect()
return
print("Connected")
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id=CLIENT_ID,
protocol=mqtt.MQTTv5,
)
client.username_pw_set(USERNAME, PASSWORD)
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.on_connect = on_connect
client.connect(HOST, PORT, keepalive=60)
client.loop_forever()
El formato !r imprime los valores entre comillas, lo que deja a la vista los espacios invisibles. Esa sola línea ha resuelto muchas investigaciones del tipo "mi contraseña es correcta, seguro".
En un ESP32 con PubSubClient, el error habitual está en la sobrecarga:
// Incorrecto: no se envían credenciales
mqtt.connect("YOUR_CLIENT_ID");
// Correcto: client ID, usuario y contraseña
mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD");
Not Authorized después de conectar
A veces la conexión tiene éxito pero las operaciones posteriores fallan con "not authorized". En MQTT 5 verás 0x87 en un SUBACK o PUBACK, o en un DISCONNECT. Eso significa que el cliente puede conectarse pero no tiene permiso para usar un topic concreto, por ejemplo un prefijo reservado. Con MQTT 3.1.1 no hay reason code para una publicación rechazada, así que el mensaje puede simplemente desaparecer. Si los mensajes se esfuman, conéctate temporalmente con MQTT 5 para ver el reason code real. La referencia de reason codes de MQTT recoge todos los códigos por tipo de paquete.
Cómo funciona en ConnectMQ
En ConnectMQ, cada broker que creas en el portal recibe un usuario, una contraseña y un client ID generados, y el client ID está vinculado a esas credenciales. Eso es lo primero que hay que comprobar cuando ves 0x87: ¿estás usando los tres valores del mismo broker? Los brokers están aislados por inquilino, así que las credenciales de un broker no funcionan en otro, ni siquiera dentro de la misma cuenta.
Conviene conocer otros dos comportamientos de la plataforma:
- Los inicios de sesión fallidos están limitados. Tras varios inicios de sesión fallidos, se bloquea la dirección IP de origen. Un dispositivo atascado en un bucle de reconexión rápido con credenciales caducadas puede dejar fuera a otros dispositivos que estén detrás del mismo NAT. Usa backoff exponencial.
- Los límites de conexión dependen del plan. El plan Serverless gratuito permite hasta 25 conexiones simultáneas. Superarlo produce
0x97 Quota exceededen los clientes MQTT 5, no "not authorized", lo que es una razón más para preferir MQTT 5 mientras depuras.
Para reforzar la seguridad más allá de la autenticación, consulta las buenas prácticas de seguridad MQTT, y el tutorial de MQTT para tener una visión más amplia del protocolo.
Conéctate de forma segura con ConnectMQ
Un broker MQTT gestionado que emite credenciales y client ID que encajan entre sí elimina la mayoría de las causas de este error antes de que se produzcan. Regístrate en app.connectmq.com para obtener un broker Serverless gratuito sin tarjeta de crédito y usa el cliente MQTT en el navegador para confirmar que tus credenciales funcionan antes de flashear un solo dispositivo. Descubre más sobre cómo usar un broker MQTT en la nube.
Preguntas frecuentes
¿Qué significa "Connection Refused: not authorised" en las herramientas de Mosquitto?
Es el código de retorno CONNACK 5. El broker recibió un CONNECT válido pero rechazó al cliente, normalmente por credenciales erróneas, un client ID no vinculado a la cuenta o credenciales de otro broker.
¿"Not authorized" es lo mismo que "bad username or password"?
No exactamente. Bad username or password es el código 4 (0x86) y significa que las credenciales no coincidían; not authorized es el código 5 (0x87) y abarca problemas de permisos más amplios. Algunos brokers usan el código 5 para ambos, así que, en cualquier caso, revisa primero las credenciales.
¿Por qué mi cliente se conecta con mosquitto_sub pero no desde mi aplicación?
La aplicación está enviando algo distinto: otro host, un client ID generado, credenciales que faltan o una contraseña alterada. Imprime la configuración efectiva en tiempo de ejecución y compárala con el comando que funciona.
¿Pueden causar problemas los inicios de sesión fallidos repetidos?
Sí. Muchos brokers, incluido ConnectMQ, bloquean direcciones IP tras varios inicios de sesión fallidos. Usa backoff exponencial y deja de reintentar ante errores de autorización.



