MQTT username password authentication is the most widely used way for a client to prove its identity to a broker, and it is also the most frequently misconfigured. In this guide you will see exactly how credentials travel in the CONNECT packet, why they are only safe inside TLS, which reason codes you get when they are wrong, and how to manage one credential set per device.
How Credentials Travel in the CONNECT Packet
Every MQTT session starts with a CONNECT packet from the client. Its variable header contains connect flags, two of which are the User Name Flag and the Password Flag. When those flags are set, the payload carries the username as a UTF-8 string and the password as binary data, right after the client ID and the optional Will message.
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 <- raw bytes, not hashed
There is no hashing, challenge or encryption in the MQTT layer. The password is sent as-is. Anyone who can read the TCP stream on port 1883 can read the password with a packet capture tool in seconds.
A few protocol details are worth knowing:
- In MQTT 3.1.1 a password may only be sent if a username is also sent. MQTT 5.0 relaxed this so a password can be sent alone, but most brokers still expect both.
- The password field is binary, so it can hold arbitrary bytes, including tokens. That is how token-based schemes such as MQTT JWT authentication reuse the same field.
- MQTT 5.0 also defines enhanced authentication through an Authentication Method property and AUTH packets, for challenge-response mechanisms. Username and password remain the common baseline.
Why TLS Is Mandatory With Passwords
Because the password crosses the network in clear text, MQTT username password authentication without TLS is little better than no authentication on any untrusted network. TLS encrypts the whole session, including the CONNECT packet, and lets the client verify that it is talking to the real broker rather than an impostor that collects credentials.
| Port | Transport | Safe for credentials? |
|---|---|---|
| 1883 | MQTT over plain TCP | No, password visible on the wire |
| 8883 | MQTT over TLS | Yes, with certificate verification |
| 8083 | MQTT over WebSocket | No |
| 8084 | MQTT over secure WebSocket (/mqtt) |
Yes |
On ConnectMQ, use port 8883 for devices and services and 8084 for browsers whenever you send credentials. The broker presents a Let's Encrypt certificate, which is trusted by standard CA bundles on desktop and server operating systems. Embedded clients need the root CA included in firmware; the MQTT TLS configuration guide covers that step.
Also verify the certificate. Disabling verification (insecure, setInsecure(), rejectUnauthorized: false) gives you encryption against passive sniffing but no protection against an attacker who intercepts the connection and presents their own certificate.
Connecting With a Username and Password
The examples use the placeholders YOUR_USERNAME, YOUR_PASSWORD and YOUR_CLIENT_ID, which you get when you create a broker in the portal. If you have not set one up yet, the cloud MQTT broker guide walks through the hosting options.
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"] # never hard-code in source control
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) # e.g. 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()
Command Line
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
Read the password from an environment variable rather than typing it on the command line, where it ends up in shell history and process listings.
What Happens When Credentials Are Wrong
The broker answers CONNECT with a CONNACK. The code tells you whether the problem is the credentials or the authorization:
| Situation | MQTT 3.1.1 CONNACK | MQTT 5.0 reason code |
|---|---|---|
| Accepted | 0x00 | 0x00 Success |
| Client ID rejected | 0x02 Identifier rejected | 0x85 Client Identifier not valid |
| Wrong username or password | 0x04 Bad user name or password | 0x86 Bad User Name or Password |
| Valid credentials, not allowed | 0x05 Not authorized | 0x87 Not authorized |
Full troubleshooting steps are in MQTT connection refused: not authorized. Two practical rules apply to every client:
- Do not retry immediately in a tight loop. Wrong credentials will not fix themselves, and many brokers treat rapid failures as an attack. ConnectMQ blocks IP addresses after repeated failed logins, so a misconfigured fleet hammering the broker can lock itself out.
- Use exponential backoff with jitter and surface authentication failures in logs or device status, separately from network errors.
Per-Device Credentials: Why and How
The shortcut most projects start with is one shared username and password baked into every device. It works on day one and causes trouble from then on:
- One leaked device exposes the whole fleet.
- You cannot revoke a single device without reflashing all of them.
- Logs cannot tell you which device misbehaved.
Per-device credentials fix all three. On a self-hosted Mosquitto broker you would maintain a password file:
# Create the file with the first user, then add more without -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
The file stores salted hashes, not the passwords themselves, and the broker must be reloaded after changes. Operating this yourself also means keeping the TLS certificate renewed and the file in sync across instances.
Per-Device Credentials on ConnectMQ
With ConnectMQ the broker generates the credentials for you. When you create a broker in the portal you receive a username, password and client ID, and the client ID is bound to the issued credentials. That binding matters: a stolen password cannot be used with an arbitrary client ID, and two devices cannot silently share one credential set, because they would be competing for the same bound identity.
Recommended practice on a managed broker:
- Issue a separate credential set for each device or service, and record which physical device holds which client ID.
- Store the password in protected storage on the device, not in source code. See secure MQTT credentials on devices.
- Connect only on 8883 or 8084 with certificate verification.
- Plan for change: the credential rotation guide shows how to replace credentials across a fleet without downtime.
Tenants are isolated from each other, so credentials issued for your broker give access only to your broker's traffic. Quotas and flood protection apply per plan, which limits the damage a single compromised client can do.
Username and Password Versus Other Methods
| Method | Strength | Weakness |
|---|---|---|
| Username and password over TLS | Simple, supported by every client library | Static secret; must be stored and rotated |
| Client certificates (mTLS) | Strong identity, no shared secret on the wire | Certificate lifecycle and PKI to operate |
| JWT in the password field | Short-lived, carries claims | Needs a token issuer and clock sync on devices |
For most fleets, unique per-device passwords over verified TLS are a solid baseline. The MQTT security best practices guide covers the layers that sit on top.
Get Started with ConnectMQ
Skip the password files and certificate renewals. A hosted MQTT broker from ConnectMQ gives you TLS on 8883 and 8084, generated credentials bound to client IDs and IP blocking for repeated failed logins. Create a free Serverless broker at app.connectmq.com, no credit card required.
Frequently Asked Questions
Is MQTT username password authentication secure?
It is secure enough for most deployments when used over TLS with certificate verification and unique per-device passwords. Over plain TCP on port 1883 the password is visible to anyone who can capture the traffic.
Does MQTT encrypt the password?
No. MQTT sends the password as raw bytes inside CONNECT. Encryption comes only from the TLS layer around the connection.
Can I connect to the public broker with a username and password?
The public test broker at broker.connectmq.com accepts anonymous connections with any non-empty unique client ID. For authenticated, private traffic, create your own broker and use the generated credentials.
What is the difference between 0x86 and 0x87?
0x86 means the username or password was wrong. 0x87 means the credentials were understood but the client is not allowed to connect or perform the action.



