In my setup, I am rewriting the mountpoints of clients from the ones set up by the listeners to individual mountpoints depending on client group.

The idea behind this is perfect isolation of multi-tenancy on the server. Individual clients from different groups thus are not able to see each other, even when subscribing to “#” (everything).

In my auth_on_register webhook I am checking whether the client trying to register is coming from the web (as part of the picockpit user interface) or from the Raspberry Pi client. At this point the mountpoint is still determined by the listener, as it has not yet been rewritten.

In the webhook (in Crystal) I set the new mountpoint, like this:

res = %({„result“: „ok“, „modifiers“: {„mountpoint“: „#{mountpoint}“, „client_id“: „#{clientid}“}})

Today I was debugging why the JS client could not publish any messages. It was disconnecting with the error:

MQTT connection lost (8): AMQJS0008I Socket closed.

Here is what I see as VerneMQ debug output:

“12:13:33.630 [error] can’t auth publish [<<„…“>>,{„…“,<<„…“>>},0,[<<„test“>>],<<„Hello world!“>>,false] due to not_authorized”

This had me initially baffled. I was checking for the “correct” (javascript client) mountpoint, I thought?

And, my webhook for auth_on_publish was never called?

It turns out, that I forgot to consider that the new mountpoint was already set! And this new mountpoint is not some virtual construct, but the actual new mountpoint – any requests from this client are going to carry that new mountpoint!

Therefore: make sure that in your Lua function auth_on_publish(pub) you are checking for the new mountpoint, before passing to the next handler (webhook).