{"id":10550,"date":"2019-06-04T23:45:26","date_gmt":"2019-06-04T21:45:26","guid":{"rendered":"https:\/\/pi3g.com\/?p=10550"},"modified":"2019-06-04T23:45:26","modified_gmt":"2019-06-04T21:45:26","slug":"debugging-vernemq-connection-authentication-problems-for-dual-authentication-with-webhooks-and-vmq_diversity","status":"publish","type":"post","link":"https:\/\/pi3g.com\/de\/debugging-vernemq-connection-authentication-problems-for-dual-authentication-with-webhooks-and-vmq_diversity\/","title":{"rendered":"Debugging von VerneMQ-Verbindungs-\/Authentifizierungsproblemen bei dualer Authentifizierung mit Webhooks und vmq_diversity"},"content":{"rendered":"<h1>TL;DR<\/h1>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl\">https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl<\/a><\/p>\n<p>includes a statement which will block authentication \/ authorization through any other channels if your Lua script returns \u201cfalse\u201d:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"547\" height=\"70\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb.png\" border=\"0\"><\/a><\/p>\n<p>will lead to:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"552\" height=\"152\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-1.png\" border=\"0\"><\/a><\/p>\n<p>instead of trying other plugins, as you might have assumed!<\/p>\n<p>In order to avoid this problem, simply<strong> do not return anything<\/strong> from your Lua script, if you do not want to handle the message!<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"581\" height=\"403\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-2.png\" border=\"0\"><\/a><\/p>\n<h1>Debugging<\/h1>\n<p>VerneMQ has a built-in trace tool, which will help you to see which problems can occur. First, display the sessions, in order to find out which data your clients are trying to connect with:<\/p>\n<blockquote>\n<p>vmq-admin session show<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"829\" height=\"145\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-3.png\" border=\"0\"><\/a><\/p>\n<p>Then run a trace:<\/p>\n<blockquote>\n<p>vmq-admin trace client client-id=000000007eaefc47 &#8211;mountpoint=5c61a59ba6b76f558d256f42<\/p>\n<\/blockquote>\n<p>Note that the mountpoint defaults to \u201c\u201d (the default mountpoint for Verne) \u2013 if you are not setting a custom mountpoint on the listeners ( as me), then you can omit this.<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1274\" height=\"343\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-4.png\" border=\"0\"><\/a><\/p>\n<p>Initially vmq-admin trace will report that no sessions are found for this client \u2013 if your client is not currently connected.<\/p>\n<p>Connect your client, and there will be more output.<\/p>\n<p>It is also helpful to increase the verbosity level in the logger to debug (for vernemq.conf):<\/p>\n<blockquote>\n<p>log.console.level = debug<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1037\" height=\"172\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-5.png\" border=\"0\"><\/a><\/p>\n<h1>econnrefused<\/h1>\n<p>In my particular case, my webhook endpoint was not running. After starting it up, I now get (multiple attempts with similar output):<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-6.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1439\" height=\"535\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-6.png\" border=\"0\"><\/a><\/p>\n<p>As you can see, the client is now being authenticated, but not being authorized to publish. The client is then disconnected (as per MQTT 3.1.1 spec).<\/p>\n<p>And this is the log output:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-7.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1325\" height=\"125\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-7.png\" border=\"0\"><\/a><\/p>\n<p>what is happening here, is that the client is authenticated using a webhook, and then it tries to become authorized using a Lua script ( MongoDB authorization). <\/p>\n<p>I am not sure why auth_on_publish for the client is not called using a webhook as well. This client in any case is supposed to be authenticated fully using MongoDB.<\/p>\n<p>I also only see requests for auth-on register:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-8.png\"><img loading=\"lazy\" decoding=\"async\" width=\"841\" height=\"91\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-8.png\" border=\"0\"><\/a><\/p>\n<p>To show which webhooks are registered, you can run<\/p>\n<blockquote>\n<p>vmq-admin webhooks show<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-9.png\"><img loading=\"lazy\" decoding=\"async\" width=\"916\" height=\"164\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-9.png\" border=\"0\"><\/a><\/p>\n<p>see: <a href=\"https:\/\/docs.vernemq.com\/plugindevelopment\/webhookplugins\">https:\/\/docs.vernemq.com\/plugindevelopment\/webhookplugins<\/a><\/p>\n<p>All webhooks are called with the method POST, and need to be answered with the HTTP code 200 to be considered successful. <\/p>\n<h2>A request for the webhook server<\/h2>\n<p>Here is how a request will look like for the Webhook server:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-10.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1170\" height=\"116\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-10.png\" border=\"0\"><\/a><\/p>\n<p>headers are passed, with the header vernemq-hook set to <strong>auth_on_register<\/strong> in this case.<\/p>\n<p>The post body will include different information on the client trying to connect.<\/p>\n<p>After using \u201cnext\u201d as a reply from the webhook, the publish works correctly \u2013 the client is authenticated against the MongoDB, and afterwards the publish is authorized, as desired.<\/p>\n<p>Here\u2019s how the answer from the webhook should look like to pass authentication on to the next plugin:<\/p>\n<blockquote>\n<p>{&#8220;result&#8221;: &#8220;next&#8221;}<\/p>\n<\/blockquote>\n<p>And here\u2019s how the trace looks now:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-11.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1001\" height=\"286\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-11.png\" border=\"0\"><\/a><\/p>\n<p>At the bottom you can see the keepalives for the client (PINGREQ, PINGRESP).<\/p>\n<p>So, one client is working now. Onwards to the next client \u2013 which should be authenticated and authorized using webhooks!<\/p>\n<h1>Webhook client<\/h1>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-12.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1017\" height=\"202\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-12.png\" border=\"0\"><\/a><\/p>\n<p>As you can see, by the way, the mountpoint gets rewritten from \u201cpiclient\u201d to a different mountpoint by the MongoDB Lua script.<\/p>\n<p>Basically I am using the mountpoint on the listeners to indicate which authentication method should be used for this client.<\/p>\n<p>In version 2 of VerneMQ, we are promised, there will be a separation of Plugins per Listener \u2013 therefore we can avoid these checks which add overhead to each connection.<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-13.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1041\" height=\"60\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-13.png\" border=\"0\"><\/a><\/p>\n<p>apparently only one trace can be run at a time. Trying again after shutting down the other trace:<\/p>\n<blockquote>\n<p>vmq-admin trace client client-id=my_clientid &#8211;mountpoint=jsclient<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-14.png\"><img loading=\"lazy\" decoding=\"async\" width=\"938\" height=\"171\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-14.png\" border=\"0\"><\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-15.png\"><img loading=\"lazy\" decoding=\"async\" width=\"958\" height=\"207\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-15.png\" border=\"0\"><\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-16.png\"><img loading=\"lazy\" decoding=\"async\" width=\"980\" height=\"73\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-16.png\" border=\"0\"><\/a><\/p>\n<p>Please note that the message auth_on_publish debug is printed by an additional statement I inserted in the Lua script:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-17.png\"><img loading=\"lazy\" decoding=\"async\" width=\"503\" height=\"102\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-17.png\" border=\"0\"><\/a><\/p>\n<p>in auth_commons.lua<\/p>\n<h2>Understanding what to return from the Lua script<\/h2>\n<p>What we want is probably to return from the Lua script that the next hook should be called.<\/p>\n<p>\u201cIn case the plugin can&#8217;t validate the publish message it is best to return <code>next<\/code> as this would allow subsequent plugins in the chain to validate the request.\u201d<\/p>\n<p>(see <a href=\"https:\/\/docs.vernemq.com\/plugindevelopment\/publishflow\">https:\/\/docs.vernemq.com\/plugindevelopment\/publishflow<\/a> )<\/p>\n<p>I assumed that returning <strong>false<\/strong> would imply that, but apparently not?<\/p>\n<p>Let\u2019s look in the Erlang source of vernemq<\/p>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\">https:\/\/github.com\/vernemq\/vernemq<\/a><\/p>\n<p>This is a test suite for the auth_cache for vmq_diversity (where the Lua scripts live):<\/p>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\/blob\/c8b92f398e76d6ce4b8cca5e438e8ae1e717d71c\/apps\/vmq_diversity\/test\/vmq_diversity_auth_cache_SUITE.erl\">https:\/\/github.com\/vernemq\/vernemq\/blob\/c8b92f398e76d6ce4b8cca5e438e8ae1e717d71c\/apps\/vmq_diversity\/test\/vmq_diversity_auth_cache_SUITE.erl<\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-18.png\"><img loading=\"lazy\" decoding=\"async\" width=\"878\" height=\"175\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-18.png\" border=\"0\"><\/a><\/p>\n<blockquote>\n<p>vmq-admin trace client client-id=my_clientid &#8211;mountpoint=jsclient<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-19.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1067\" height=\"403\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-19.png\" border=\"0\"><\/a><\/p>\n<p>Adding some additional debugging for the message in Lua:<\/p>\n<blockquote>\n<p>function auth_on_publish(pub)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;***auth_on_publish debug*** (LUA)&#8221;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; for k,v in pairs(pub) do<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(k .. &#8221; &#8221; .. v)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; end<br \/>&nbsp;&nbsp;&nbsp;&nbsp; print(pub)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; return false<br \/>\nend<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-20.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1093\" height=\"99\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-20.png\" border=\"0\"><\/a><\/p>\n<p>Note that the code seems to be faulty (false apparently can\u2019t be concatenated using .. in Lua \u2013 OK.)<\/p>\n<p>In any case, in the Lua table, which is passed in as \u201cpub\u201d, we have the following parameters:<\/p>\n<ul>\n<li>client_id<\/li>\n<li>mountpoint <\/li>\n<li>payload<\/li>\n<li>qos<\/li>\n<\/ul>\n<p>now we could check for mountpoint being \u201cjsclient\u201d (which should be authenticated using webhooks), and for now force true:<\/p>\n<blockquote>\n<p>function auth_on_publish(pub)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;***auth_on_publish debug*** (LUA)&#8221;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; if pub[&#8220;mountpoint&#8221;] == &#8220;jsclient&#8221; then<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true<br \/>&nbsp;&nbsp;&nbsp;&nbsp; else<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false<br \/>&nbsp;&nbsp;&nbsp;&nbsp; end<br \/>\nend<\/p>\n<\/blockquote>\n<p>Here is how a trace looks like for this artificial condition:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-21.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1094\" height=\"295\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-21.png\" border=\"0\"><\/a><\/p>\n<h2>Back to Erlang<\/h2>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl\">https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl<\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-22.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1086\" height=\"703\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-22.png\" border=\"0\"><\/a><\/p>\n<p>when auth_on_publish is called for the vmq_diversity_plugin.erl the result value will be obtained like this:<\/p>\n<ul>\n<li>if vmq_diversity_cache:match_publish_acl will return true, it will be \u201cok\u201d.<\/li>\n<li>if it returns false, it will throw an error<\/li>\n<li>if it returns no_cache, the result will be dependend on the all_till_ok function (called with auth_on_publish)<\/li>\n<\/ul>\n<p>as you can see here are the values passed on to our Lua script, including the mountpoint<\/p>\n<p>conv_res will modify the returned result:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-23.png\"><img loading=\"lazy\" decoding=\"async\" width=\"521\" height=\"185\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-23.png\" border=\"0\"><\/a><\/p>\n<p>I highly recommend if you are not familiar with Erlang to read my previous article, <a href=\"https:\/\/pi3g.com\/2019\/05\/12\/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook\/\">https:\/\/pi3g.com\/2019\/05\/12\/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook\/<\/a><\/p>\n<p>Basically if {error, lua_script_returned_false} is not matched within the results, for any (_) name and any Other, the result will be Other \u2013 simply passing on the results of all_till_ok to the calling function.<\/p>\n<p><\/p>\n<p>For the name <strong>lua_script_returned_false<\/strong>, the error will be not_authorized.<\/p>\n<p>I am not entirely sure if this vmq_plugin_helper.erl is where the main controlling logic (of passing on on next) is:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-24.png\"><img loading=\"lazy\" decoding=\"async\" width=\"528\" height=\"249\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-24.png\" border=\"0\"><\/a><\/p>\n<p>in any case, probably \u201cnext\u201d is expected to be returned.<\/p>\n<p>Here, in vmq_diversity_plugin.erl all_till_ok is defined:<\/p>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl\">https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl<\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-25.png\"><img loading=\"lazy\" decoding=\"async\" width=\"653\" height=\"735\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-25.png\" border=\"0\"><\/a><\/p>\n<p>As you can see, if \u201ctrue\u201d is returned by the script, the return value is set to \u201cok\u201d.<\/p>\n<p>If \u201cfalse\u201d is returned from the script, the previously mentioned error is returned, and execution stops \u2013&gt; not authorized.<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-26.png\"><img loading=\"lazy\" decoding=\"async\" width=\"485\" height=\"72\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-26.png\" border=\"0\"><\/a><\/p>\n<p><strong><font style=\"background-color: rgb(255, 255, 0);\">This means that if you return false in the Lua scripts, no other plugins are going to be called!<\/font><\/strong><\/p>\n<p>alternatively modifiers can be returned.<\/p>\n<p>The trick is <strong>not to return anything, <\/strong>in case you do not want to handle the request:<\/p>\n<blockquote>\n<p>function auth_on_publish(pub)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;***auth_on_publish debug*** (LUA)&#8221;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp; if pub[&#8220;mountpoint&#8221;] == &#8220;jsclient&#8221; then<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;*** jsclient detected ***&#8221;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;not returning anything&#8221;)<br \/><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212; return true<br \/>\n<\/strong>&nbsp;&nbsp;&nbsp; else<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(&#8220;+++ other client detected +++&#8221;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false<br \/>&nbsp;&nbsp;&nbsp;&nbsp; end<br \/>\nend<\/p>\n<\/blockquote>\n<p>Note that &#8212; (two dashes) is a comment in Lua.<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-27.png\"><img loading=\"lazy\" decoding=\"async\" width=\"581\" height=\"403\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-27.png\" border=\"0\"><\/a><\/p>\n<p>In this case, the auth_on_publish hook gets called using webhooks:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-28.png\"><img loading=\"lazy\" decoding=\"async\" width=\"611\" height=\"153\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-28.png\" border=\"0\"><\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-29.png\"><img loading=\"lazy\" decoding=\"async\" width=\"775\" height=\"65\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-29.png\" border=\"0\"><\/a><\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-30.png\"><img loading=\"lazy\" decoding=\"async\" width=\"612\" height=\"313\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-30.png\" border=\"0\"><\/a><\/p>\n<h1>Bonus<\/h1>\n<p>Error generating config with cuttlefish:<\/p>\n<p>This can be debugged further by setting the command in docker-compose.yml to:<\/p>\n<blockquote>\n<p>command: &#8220;vernemq config generate -l debug \/vernemq\/etc\/vernemq.conf.local&#8221;<\/p>\n<\/blockquote>\n<p>and bringing the container up (note that I have created a .local file, so certain settings are not overwritten anymore).<\/p>\n<p>The error message I get is:<\/p>\n<p>jalpine_morpheus | escript: exception error: no function clause matching<br \/>\njalpine_morpheus |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lists:unzip([[ws,ws],<br \/>\njalpine_morpheus |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {[&#8220;log&#8221;,&#8221;console&#8221;,&#8221;file&#8221;],&#8221;.\/log\/console.log&#8221;},<\/p>\n<p>apparently this is related to cuttlefish choking on lines which contain only a space:<\/p>\n<p><a href=\"https:\/\/github.com\/basho\/cuttlefish\/issues\/222\">https:\/\/github.com\/basho\/cuttlefish\/issues\/222<\/a><\/p>\n<p>pressing <strong>Alt + P<\/strong> in nano will enable whitespace display \u2013 good for debugging this particular issue.<\/p>\n<p>The problematic section in my config looks like this:<\/p>\n<p>\n<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image-31.png\"><img loading=\"lazy\" decoding=\"async\" width=\"548\" height=\"165\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2019\/06\/image_thumb-31.png\" border=\"0\"><\/a><\/p>\n<p>here there are two tabs (?) where they should be nothing. <\/p>\n<p>Removing the problematic line will allow VerneMQ to start again.<\/p>\n<p><\/p>\n<h1>Further reading<\/h1>\n<p>This might also be helpful:<\/p>\n<p><a href=\"http:\/\/www.steves-internet-guide.com\/mqtt-protocol-messages-overview\/\">http:\/\/www.steves-internet-guide.com\/mqtt-protocol-messages-overview\/<\/a><\/p>\n<p><\/p>\n<p>Changelog of VerneMQ:<\/p>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\/blob\/fe514561cbeebb2ac4f7c98a87c64d766587c1d7\/changelog.md\">https:\/\/github.com\/vernemq\/vernemq\/blob\/fe514561cbeebb2ac4f7c98a87c64d766587c1d7\/changelog.md<\/a><\/p>\n<p>NB: in Version 1.8 an interesting new plugin is the vmq_pulse plugin, which will push cluster information to a pulse backend via HTTP(S).<\/p>\n<p><\/p>\n<p><a href=\"https:\/\/github.com\/vernemq\/vernemq\/blob\/c8b92f398e76d6ce4b8cca5e438e8ae1e717d71c\/apps\/vmq_diversity\/test\/cache_test.lua\">https:\/\/github.com\/vernemq\/vernemq\/blob\/c8b92f398e76d6ce4b8cca5e438e8ae1e717d71c\/apps\/vmq_diversity\/test\/cache_test.lua<\/a><\/p>\n<p>Showing some additional Lua scripting for VerneMQ diversity.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR https:\/\/github.com\/vernemq\/vernemq\/blob\/master\/apps\/vmq_diversity\/src\/vmq_diversity_plugin.erl enth\u00e4lt eine Anweisung, die die Authentifizierung \/ Autorisierung \u00fcber andere Kan\u00e4le blockiert, wenn Ihr Lua-Skript \"false\" zur\u00fcckgibt: f\u00fchrt zu: statt andere Plugins zu versuchen, wie Sie vielleicht angenommen haben! Um dieses Problem zu vermeiden, geben Sie einfach nichts von Ihrem Lua-Skript zur\u00fcck, wenn Sie das nicht wollen...<\/p>","protected":false},"author":830,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[608],"tags":[630,634,601,590,632,591,633,631,629,589,627,628,635],"class_list":["post-10550","post","type-post","status-publish","format-standard","hentry","category-vernemq","tag-auth_on_publish","tag-cuttlefish","tag-debugging","tag-erlang","tag-false","tag-lua","tag-next","tag-problem","tag-trace","tag-vernemq","tag-vmq_diversity","tag-webhooks","tag-whitespace"],"_links":{"self":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/10550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/users\/830"}],"replies":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/comments?post=10550"}],"version-history":[{"count":1,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/10550\/revisions"}],"predecessor-version":[{"id":10551,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/10550\/revisions\/10551"}],"wp:attachment":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/media?parent=10550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/categories?post=10550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/tags?post=10550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}