MQTT brokers often seem like they’re open for business to anyone with a network connection, but thankfully, you can lock them down tight with username and password authentication.

Let’s see what that looks like in practice. Imagine a Mosquitto broker running on 192.168.1.100.

# On a client machine, attempt to connect without credentials (will fail if auth is enforced)
mosquitto_sub -h 192.168.1.100 -t "sensors/temperature" -C 1

# On a client machine, connect successfully with credentials
mosquitto_sub -h 192.168.1.100 -t "sensors/temperature" -u "alice" -P "s3cr3tP@ssw0rd" -C 1

The core of this security lies in how the broker is configured to validate incoming connections. It’s not just a simple on/off switch; it involves defining users, their passwords, and how the broker checks them.

Here’s the mental model for how username/password authentication works in MQTT, specifically with Mosquitto, a popular broker:

  1. Client Connection Attempt: A client (publisher or subscriber) initiates a connection to the MQTT broker. This attempt includes the client ID, potentially a username, and a password.

  2. Broker Interception: The broker receives the connection request. If authentication is enabled, it intercepts the request before allowing the client to subscribe to any topics or publish any messages.

  3. Authentication Mechanism: The broker consults its configured authentication mechanism. For username/password, this typically means checking against a local password file or an external authentication backend (like LDAP or a custom plugin).

  4. Credential Verification:

    • Local Password File: The broker looks up the provided username in its password file. If found, it hashes the provided password and compares it to the stored hash.
    • External Backend: The broker forwards the username and password to the configured external system for verification.
  5. Authentication Success/Failure:

    • Success: If the credentials match, the broker allows the connection to proceed. The client is now authenticated and can perform operations based on its authorization rules (which is a separate but related topic).
    • Failure: If the credentials don’t match, or the username isn’t found, the broker rejects the connection immediately. The client will receive a connection refused error, typically code 5 (Not authorized).
  6. Authorization (Post-Authentication): Once authenticated, the client’s ability to publish or subscribe to specific topics is determined by the broker’s authorization rules. This is where you define what an authenticated user can do.

The primary lever you control here is the password_file directive in your mosquitto.conf. This file is a simple text file where each line defines a username and their hashed password.

Here’s a snippet of what that mosquitto.conf might look like:

# Enable username/password authentication
allow_anonymous false

# Path to the password file
password_file /etc/mosquitto/passwd

And the corresponding /etc/mosquitto/passwd file:

alice:$6$rounds=50000$usesomesalt$abcdefghijklmnopqrstuvwxyz0123456789
bob:$6$rounds=50000$usesomesalt$ABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210

To create and manage this password file, you’d use the mosquitto_passwd utility:

# Add a new user 'alice' and set her password
# This will prompt you for the password
mosquitto_passwd -b /etc/mosquitto/passwd alice mysecretpassword

# Add another user 'bob'
mosquitto_passwd -b /etc/mosquitto/passwd bob anothersecurepassword

# Delete user 'charlie'
mosquitto_passwd -d /etc/mosquitto/passwd charlie

When allow_anonymous false is set, the broker will require a username and password for all connections. If allow_anonymous true (or if it’s omitted, as true is often the default) and password_file is specified, the broker will allow anonymous connections and authenticated connections. You then use authorization rules to control what anonymous users can do, and what authenticated users can do.

The mosquitto_passwd command uses SHA-512 hashing with a salt by default. The rounds parameter in the hash string indicates how many iterations of the hashing function were performed; a higher number means more computational effort to crack a password but also takes longer to authenticate. The usesomesalt is a placeholder for the actual random salt generated for each password.

The most surprising thing about username/password authentication is how often it’s conflated with authorization. You can have a user successfully authenticate (prove they are who they say they are), but then still be blocked from publishing to certain topics because authorization rules haven’t granted them permission. Authentication is about identity; authorization is about permissions.

Once you’ve got username/password authentication working, the next logical step is to start thinking about what those authenticated users can actually do on your broker, which leads you into MQTT authorization.

Want structured learning?

Take the full Mqtt course →