La autenticación MQTT con usuario y contraseña es la forma más utilizada para que un cliente demuestre su identidad ante un broker, y también la que con más frecuencia se configura mal. En esta guía verás exactamente cómo viajan las credenciales en el paquete CONNECT, por qué solo están a salvo dentro de TLS, qué códigos de motivo recibes cuando son incorrectas y cómo gestionar un conjunto de credenciales por dispositivo.
Cómo viajan las credenciales en el paquete CONNECT
Toda sesión MQTT comienza con un paquete CONNECT enviado por el cliente. Su cabecera variable contiene los connect flags, dos de los cuales son el User Name Flag y el Password Flag. Cuando están activados, el payload transporta el nombre de usuario como cadena UTF-8 y la contraseña como datos binarios, justo después del client ID y del mensaje Will opcional.
CONNECT
Protocol name: MQTT
Protocol level: 5 (MQTT 5.0) or 4 (MQTT 3.1.1)
Connect flags: username=1, password=1, clean start=1
Keep alive: 60
Payload:
Client ID: sensor-0042
Username: YOUR_USERNAME
Password: YOUR_PASSWORD <- bytes en bruto, sin hash
En la capa MQTT no hay hash, desafío ni cifrado. La contraseña se envía tal cual. Cualquiera que pueda leer el flujo TCP en el puerto 1883 puede leer la contraseña con una herramienta de captura de paquetes en cuestión de segundos.
Conviene conocer algunos detalles del protocolo:
- En MQTT 3.1.1 solo se puede enviar una contraseña si también se envía un nombre de usuario. MQTT 5.0 relajó esta regla para que la contraseña pueda enviarse sola, pero la mayoría de los brokers siguen esperando ambos.
- El campo de contraseña es binario, así que puede contener bytes arbitrarios, incluidos tokens. Así es como los esquemas basados en tokens, como la autenticación JWT en MQTT, reutilizan el mismo campo.
- MQTT 5.0 también define la autenticación mejorada mediante una propiedad Authentication Method y paquetes AUTH, para mecanismos de desafío-respuesta. El usuario y la contraseña siguen siendo la base habitual.
Por qué TLS es obligatorio con contraseñas
Como la contraseña cruza la red en texto claro, la autenticación MQTT con usuario y contraseña sin TLS es poco mejor que no tener autenticación en cualquier red no confiable. TLS cifra toda la sesión, incluido el paquete CONNECT, y permite al cliente verificar que está hablando con el broker real y no con un impostor que recopila credenciales.
| Puerto | Transporte | ¿Seguro para credenciales? |
|---|---|---|
| 1883 | MQTT sobre TCP plano | No, la contraseña es visible en la red |
| 8883 | MQTT sobre TLS | Sí, con verificación de certificado |
| 8083 | MQTT sobre WebSocket | No |
| 8084 | MQTT sobre WebSocket seguro (/mqtt) |
Sí |
En ConnectMQ, usa el puerto 8883 para dispositivos y servicios y el 8084 para navegadores siempre que envíes credenciales. El broker presenta un certificado de Let's Encrypt, en el que confían los paquetes de CA estándar de los sistemas operativos de escritorio y servidor. Los clientes embebidos necesitan incluir la CA raíz en el firmware; la guía de configuración de TLS en MQTT cubre ese paso.
Verifica también el certificado. Desactivar la verificación (insecure, setInsecure(), rejectUnauthorized: false) te da cifrado frente a la escucha pasiva, pero ninguna protección frente a un atacante que intercepte la conexión y presente su propio certificado.
Conectarse con usuario y contraseña
Los ejemplos usan los marcadores YOUR_USERNAME, YOUR_PASSWORD y YOUR_CLIENT_ID, que obtienes al crear un broker en el portal. Si todavía no tienes uno, la guía del broker MQTT en la nube repasa las opciones de alojamiento.
Python (paho-mqtt 2.x)
import os
import ssl
import paho.mqtt.client as mqtt
HOST = os.environ.get("MQTT_HOST", "YOUR_BROKER_HOST")
USERNAME = os.environ["MQTT_USERNAME"] # nunca lo incluyas en el control de versiones
PASSWORD = os.environ["MQTT_PASSWORD"]
CLIENT_ID = os.environ["MQTT_CLIENT_ID"]
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print("Rejected:", reason_code) # p. ej. Bad user name or password
client.disconnect()
return
print("Authenticated")
client.publish(f"devices/{CLIENT_ID}/status", "online", qos=1, retain=True)
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, 8883, keepalive=60)
client.loop_forever()
Línea de comandos
mosquitto_pub -h YOUR_BROKER_HOST -p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-i YOUR_CLIENT_ID -u YOUR_USERNAME -P "$MQTT_PASSWORD" \
-t 'devices/YOUR_CLIENT_ID/status' -m online -V mqttv5
Lee la contraseña desde una variable de entorno en lugar de escribirla en la línea de comandos, donde acaba en el historial del shell y en los listados de procesos.
Qué ocurre cuando las credenciales son incorrectas
El broker responde a CONNECT con un CONNACK. El código te indica si el problema está en las credenciales o en la autorización:
| Situación | CONNACK en MQTT 3.1.1 | Código de motivo en MQTT 5.0 |
|---|---|---|
| Aceptado | 0x00 | 0x00 Success |
| Client ID rechazado | 0x02 Identifier rejected | 0x85 Client Identifier not valid |
| Usuario o contraseña incorrectos | 0x04 Bad user name or password | 0x86 Bad User Name or Password |
| Credenciales válidas, sin permiso | 0x05 Not authorized | 0x87 Not authorized |
Los pasos completos de diagnóstico están en MQTT connection refused: not authorized. Hay dos reglas prácticas que se aplican a todos los clientes:
- No reintentes inmediatamente en un bucle cerrado. Las credenciales incorrectas no se arreglan solas, y muchos brokers tratan los fallos rápidos como un ataque. ConnectMQ bloquea las direcciones IP tras varios inicios de sesión fallidos, así que una flota mal configurada que bombardee el broker puede acabar bloqueándose a sí misma.
- Usa backoff exponencial con jitter y muestra los fallos de autenticación en los logs o en el estado del dispositivo, separados de los errores de red.
Credenciales por dispositivo: por qué y cómo
El atajo con el que empiezan la mayoría de los proyectos es un único usuario y contraseña compartidos y grabados en todos los dispositivos. Funciona el primer día y da problemas a partir de entonces:
- Un solo dispositivo filtrado expone a toda la flota.
- No puedes revocar un único dispositivo sin volver a flashearlos todos.
- Los logs no pueden decirte qué dispositivo se comportó mal.
Las credenciales por dispositivo resuelven los tres problemas. En un broker Mosquitto autoalojado tendrías que mantener un archivo de contraseñas:
# Crea el archivo con el primer usuario y añade los demás sin -c
mosquitto_passwd -c /etc/mosquitto/passwd sensor-0001
mosquitto_passwd /etc/mosquitto/passwd sensor-0002
# mosquitto.conf
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
allow_anonymous false
password_file /etc/mosquitto/passwd
El archivo almacena hashes con sal, no las contraseñas en sí, y el broker debe recargarse tras cada cambio. Operarlo por tu cuenta también implica mantener renovado el certificado TLS y el archivo sincronizado entre instancias.
Credenciales por dispositivo en ConnectMQ
Con ConnectMQ el broker genera las credenciales por ti. Al crear un broker en el portal recibes un nombre de usuario, una contraseña y un client ID, y el client ID queda vinculado a las credenciales emitidas. Esa vinculación importa: una contraseña robada no puede usarse con un client ID arbitrario, y dos dispositivos no pueden compartir en silencio un mismo conjunto de credenciales, porque competirían por la misma identidad vinculada.
Prácticas recomendadas en un broker MQTT gestionado:
- Emite un conjunto de credenciales independiente para cada dispositivo o servicio y registra qué dispositivo físico tiene cada client ID.
- Guarda la contraseña en un almacenamiento protegido del dispositivo, no en el código fuente. Consulta cómo proteger las credenciales MQTT en los dispositivos.
- Conéctate solo en 8883 u 8084 con verificación de certificado.
- Planifica los cambios: la guía de rotación de credenciales muestra cómo sustituir credenciales en toda una flota sin tiempo de inactividad.
Los tenants están aislados entre sí, de modo que las credenciales emitidas para tu broker solo dan acceso al tráfico de tu broker. Las cuotas y la protección contra inundaciones se aplican según el plan, lo que limita el daño que puede causar un único cliente comprometido.
Usuario y contraseña frente a otros métodos
| Método | Ventaja | Inconveniente |
|---|---|---|
| Usuario y contraseña sobre TLS | Sencillo, compatible con todas las bibliotecas cliente | Secreto estático; hay que almacenarlo y rotarlo |
| Certificados de cliente (mTLS) | Identidad sólida, sin secreto compartido en la red | Ciclo de vida de certificados y PKI que operar |
| JWT en el campo de contraseña | De corta duración, transporta claims | Necesita un emisor de tokens y reloj sincronizado en los dispositivos |
Para la mayoría de las flotas, contraseñas únicas por dispositivo sobre TLS verificado son una base sólida. La guía de buenas prácticas de seguridad MQTT cubre las capas que se sitúan por encima.
Empieza con ConnectMQ
Olvídate de archivos de contraseñas y renovaciones de certificados. Un broker MQTT gestionado de ConnectMQ te ofrece TLS en 8883 y 8084, credenciales generadas vinculadas a client IDs y bloqueo de IP ante inicios de sesión fallidos repetidos. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito.
Preguntas frecuentes
¿Es segura la autenticación MQTT con usuario y contraseña?
Es lo bastante segura para la mayoría de los despliegues cuando se usa sobre TLS con verificación de certificado y contraseñas únicas por dispositivo. Sobre TCP plano en el puerto 1883, la contraseña es visible para cualquiera que pueda capturar el tráfico.
¿MQTT cifra la contraseña?
No. MQTT envía la contraseña como bytes en bruto dentro de CONNECT. El cifrado procede únicamente de la capa TLS que envuelve la conexión.
¿Puedo conectarme al broker público con usuario y contraseña?
El servidor MQTT público gratuito en broker.connectmq.com acepta conexiones anónimas con cualquier client ID único no vacío y está pensado solo para pruebas y prototipos. Para tráfico privado y autenticado, crea tu propio broker y usa las credenciales generadas.
¿Cuál es la diferencia entre 0x86 y 0x87?
0x86 significa que el usuario o la contraseña eran incorrectos. 0x87 significa que las credenciales se entendieron, pero el cliente no tiene permiso para conectarse o realizar la acción.



