eclipse / paho.mqtt.python

paho.mqtt.python
Other
2.19k stars 722 forks source link

Use of broker with JWT Auth (Disconnections rc 5) #761

Closed MacherelR closed 10 months ago

MacherelR commented 10 months ago

Hi,

I'm currently using EMQX as MQTT broker, which is configured for JWT authentication. That allows me to secure the connection and handle claims in terms of users,etc. The Broker is configured such as the JWT token should be used as the password, the username is something else also verified.

Now I previously used paho.mqtt already with a fully-opened (for testing purposes) broker (basic username/password, no auth) and had no problems handling connection/reconnection to the broker with the following callbacks :

def on_disconnect(self,client, userdata, rc):
        manager_logger.info(f"MQTT client disconnected from broker {MQTT_BROKER_URL} with result code : {rc}")
        self.mqtt_connection_on = False
        reconnect_count, reconnect_delay = 0, FIRST_RECONNECT_DELAY
        while reconnect_count < MAX_RECONNECT_COUNT and rc != 0: # rc == 0 means clean disconnect
            manager_logger.info(f"Reconnecting in {reconnect_delay} seconds...")
            time.sleep(reconnect_delay)
            try:
                client.connect(self.mqtt_broker_url, self.mqtt_broker_port)
                manager_logger.info(f"MQTT client reconnected to broker {MQTT_BROKER_URL}")
                self.mqtt_connection_on = True
                return
            except Exception as e:
                manager_logger.error(f"Recinnnection failed: {e}, retrying...")

            reconnect_delay *= RECONNECT_RATE
            reconnect_delay = min(reconnect_delay, MAX_RECONNECT_DELAY)
            reconnect_count += 1
        if rc == 0:
            manager_logger.info(f"App exited cleanly, exiting...")
        else:
            manager_logger.info(f"Reconnection failed after {reconnect_count} attempts, exiting...")
            self.run_flag = False

    def on_connect(self,mqttc, obj, flags, rc):
        # Resubscription needed 
        mqttc.subscribe(COMMAND_TOPIC,qos=1)
        self.mqtt_connection_on = True
        print("rc: " + str(rc))

This worked like charm and reconnection was handled and correctly set.

Now since I've setup jwt auth for the broker, my client keeps disconnecting and then "reconnecting" (it passes the reconnection loop but broker doesn't show up any connection)... I declared and setup my client as follows

self.mqtt_client = mqtt.Client(MQTT_CLIENT_ID, clean_session=False)
self.mqtt_client.username_pw_set(self.mqtt_username, self.mqtt_password)
self.mqtt_client.on_connect = self.on_connect
self.mqtt_client.on_message = self.on_message
self.mqtt_client.on_disconnect = self.on_disconnect
""" FOR Now, unused callbacks"""
self.mqtt_client.on_publish = self.on_publish
self.mqtt_client.on_subscribe = self.on_subscribe
self.mqtt_client.on_log = self.on_log
## Sets last will and testament to indicate if the is offline due to deconnection
self.mqtt_client.will_set(STATUS_TOPIC, payload="offline", qos=2, retain=True)
....
....
if self.mqtt_client is None:
    self._logger.error("MQTT Client has not been defined, missing authentication")
    return 
try:
    self.mqtt_client.connect(self.mqtt_broker_url,
                             port=self.mqtt_broker_port,
                             keepalive=60,
                             session_expiry=60)
    self.mqtt_client.loop_start()
    self._logger.info(f"MQTT client connected to broker {self.mqtt_broker_url}:{self.mqtt_broker_port}")

Where self.mqtt_password is actually the jwt token. Has anyone already implemented this once ? And does anyone know why it keeps disconnect with result code 5 ?