Skip to main content

Configure listeners and auth

This guide sets the client ports, TLS, and the NATS permissions of the gateway and its clients. NATS, not the gateway, accepts each credential and enforces its permissions.

Before you start, you need:

  • A config file, with its streams and buckets provisioned.
  • A nats-server.conf that you can edit and reload.

Choose an auth mode for each port​

Clients on the portMode
Each client sends its own NATS username and password, as the MQTT username and password or the SASL PLAIN credentialpassthrough (the default)
Devices that send no credential, or that you do not trust with one. All of them act as one restricted NATS userfixed

1. List the listeners​

mqtt:
listeners:
- { name: public, addr: ":1883" }
- { name: telemetry, addr: ":1884", auth: { mode: fixed, creds: /etc/nats/telemetry.creds } }
- { name: ws, addr: ":8080", ws-path: /mqtt }
amqp:
listeners:
- { name: amqp, addr: ":5672" }
- { name: legacy, addr: ":5673", auth: { mode: fixed, user: legacy, password: env://LEGACY_PASSWORD } }
  • Each list holds every port for its protocol.
  • ws-path serves the protocol over WebSocket at that path.
  • A fixed listener takes one credential: creds, nkey, user and password, jwt and seed, or context. Each value can be an env:// or file:// location.
  • A block with no listeners serves one passthrough port: MQTT on :1883, AMQP on :5672.

2. Generate the permissions​

mq-gateway generate --config gateway.yaml --format nats-server > permissions.conf

permissions.conf defines one variable for each kind of NATS user:

  • $gateway_permissions: the user the gateway acts as in an account.
  • $client_permissions: the users that clients act as.
  • $operator_permissions, commented out: a user that sends admin requests.

Each account under accounts gets its own gateway variable, such as $FLEET_B_gateway_permissions. An account with its own bindings also gets its own client variable.

3. Narrow the client topics​

The config file cannot know which topics each client uses. So each topic list holds all bound subjects, under a NARROW comment.

  1. In $client_permissions, replace each NARROW list with the subjects that the user publishes and subscribes to.
  2. Add the QoS 0 topics that the user uses outside the bindings.
  3. For each subscribe subject that ends in .>, keep its parent subject too. For example, keep orders with orders.>.
  4. For users with different topics, copy the variable under a new name for each user.
  5. In $gateway_permissions, narrow the will topics to the ones your clients set.

An MQTT topic is a subject with / replaced by .. See Mapping to NATS.

4. Give each user its permissions​

Include the file in nats-server.conf and set permissions on each user:

include "permissions.conf"

accounts {
FLEET_A: {
jetstream: enabled
users: [
{ user: gateway-a, password: "gw-a-secret", permissions: $gateway_permissions }
{ user: device, password: "device-secret", permissions: $client_permissions }
]
}
FLEET_B: {
jetstream: enabled
users: [
{ user: gateway-b, password: "gw-b-secret", permissions: $FLEET_B_gateway_permissions }
{ user: sensor, password: "sensor-secret", permissions: $client_permissions }
]
}
}
  • Give each account exactly one gateway user.
  • Delete each variable that no user takes. nats-server refuses to load an unused variable.
  • Keep the system account. The gateway asks it which account each user is in.
  • In operator mode, put the same subjects in the user JWTs.

Reload the server:

nats-server --signal reload

5. Give the gateway its users​

Put the gateway user of the gateway's own account under nats. Put each other gateway user under accounts, with the account name as the key:

nats:
url: nats://nats.example.com:4222
user: gateway-a
password: env://GW_A_PASSWORD
accounts:
FLEET_B: { user: gateway-b, password: env://GW_B_PASSWORD }

In operator mode, the key is the public key of the account. The gateway refuses to start if a user is not in the account that its key names.

Serve TLS​

Add a tls block. TLS then applies to every listener. A WebSocket listener becomes wss:// and an AMQP listener becomes amqps://:

tls:
cert: server.pem
key: server-key.pem
ca: clients-ca.pem # optional: require client certificates

With tls.ca, every client on every listener must present a certificate that the CA signed. The certificate only admits the client. The auth mode of the port still sets the NATS user.

To serve a plain port and a TLS port, run two gateways.

Check it works​

mq-gateway check --config gateway.yaml --verbose
mq-gateway --config gateway.yaml

The gateway logs listener enabled for each port and account ready for each account. Then connect a client on each port:

mqttx pub -h 127.0.0.1 -p 1884 -t 'orders/x' -m 'hello' # fixed: no credential
mqttx sub -h 127.0.0.1 -p 1883 -u device -P device-secret -q 1 -t 'orders/#'

The subscriber gets QoS 1. This shows that its user can create its consumer.

Things to know​

  • A passthrough client with no username connects to NATS with no credential. NATS refuses it, or connects it as the server's no_auth_user. Use a fixed listener to give these clients one restricted NATS user.
  • Clients cannot use the admin subjects. The gateway refuses a client publish or subscription on $MQGW.admin.>, whatever the user's permissions allow.
  • A client without permission gets Not authorized. See Errors for each code and its fix.