{"id":21131801,"url":"https://github.com/denherrring/mosquitto-auth","last_synced_at":"2026-04-16T10:05:11.249Z","repository":{"id":81760103,"uuid":"194081223","full_name":"DenHerrRing/mosquitto-auth","owner":"DenHerrRing","description":"This is a plugin to authenticate and authorize Mosquitto users from one or more of a variety of back-ends","archived":false,"fork":false,"pushed_at":"2019-06-27T11:20:51.000Z","size":135,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-14T12:34:12.870Z","etag":null,"topics":["authentication","bear","http","jwt","ldap","mongodb","mosquitto","mysql","postgresql","redis","sqlite3"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DenHerrRing.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-27T11:15:52.000Z","updated_at":"2021-12-24T03:52:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"37f1d45e-04a2-45b4-a199-8f456e69196e","html_url":"https://github.com/DenHerrRing/mosquitto-auth","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DenHerrRing/mosquitto-auth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenHerrRing%2Fmosquitto-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenHerrRing%2Fmosquitto-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenHerrRing%2Fmosquitto-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenHerrRing%2Fmosquitto-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DenHerrRing","download_url":"https://codeload.github.com/DenHerrRing/mosquitto-auth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenHerrRing%2Fmosquitto-auth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31880904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T09:23:21.276Z","status":"ssl_error","status_checked_at":"2026-04-16T09:23:15.028Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","bear","http","jwt","ldap","mongodb","mosquitto","mysql","postgresql","redis","sqlite3"],"created_at":"2024-11-20T06:00:18.167Z","updated_at":"2026-04-16T10:05:11.231Z","avatar_url":"https://github.com/DenHerrRing.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mosquitto-auth\n\n\u003e  Forked by [mosquitto-auth-plug]:https://github.com/jpmens/mosquitto-auth-plug (archived!)\n\nThis is a plugin to authenticate and authorize [Mosquitto] users from one or more\nof a variety of back-ends:\n\n* [CDB][cdb]\n* [Files][files]\n* **[HTTP][http]** (custom HTTP API)\n* **[JWT][jwt]**\n* [LDAP][ldap]\n* **[MongoDB][mongo]**\n* **[MySQL][mysql]**\n* **[PostgreSQL][postgres]**\n* [Redis][redis] key/value store\n* [SQLite3 database][sqlite]\n* [TLS PSK][psk] (the `psk` back-end is a bit of a shim which piggy-backs on the other database back-ends)\n\n## Introduction\n\nThis plugin can perform authentication (check username / password)\nand authorization (grant permission to subscribe and/or publish to specific topics via ACL). Currently, not all back-ends have the same capabilities\n(see the section on the back-end you're interested in).\n\n| Capability                 | [cdb] |[files]|[http]|[jwt]|[ldap]| [mongo] |[mysql]|[postgres]|[psk]|[redis]|[sqlite]|\n| -------------------------- | :---: | :----:| :--: | :-: | :-:  | :-----: | :---: | :------: | :-: | :---: | :---:\n| authentication             |   Y   | Y     |  Y   |  Y  |  Y   |  Y      |   Y   |    Y     |  Y  |   Y   |   Y\n| superusers                 |       |       |  Y   |  Y  |      |  Y      |   Y   |    Y     |  3  |       |        |\n| acl checking               |   2   | Y     |  Y   |  Y  |      |  Y      |   Y   |    Y     |  3  |   1   |   2\n| static superusers          |   Y   | Y     |  Y   |  Y  |      |  Y      |   Y   |    Y     |  3  |   Y   |   Y\n\n 1. Topic wildcards (+/#) are not supported\n 2. Currently not implemented; back-end returns TRUE\n 3. Dependent on the database used by PSK\n\nMultiple back-ends can be configured simultaneously for authentication, and they're attempted in\nthe order you specify. Once a user has been authenticated, the _same_ back-end is used to\ncheck authorization (ACLs). Superusers are checked for in all back-ends.\nThe configuration option is called `auth_opt_backends` and it takes a\ncomma-separated list of back-end names which are checked in exactly that order.\n\n```\nauth_opt_backends cdb,sqlite,mysql,redis,postgres,http,jwt,mongo\n```\n\nNote: anonymous MQTT connections are assigned a username configured in the\nplugin as `auth_opt_anonusername` and they\nare handled by a so-called _fallback back-end_ which is the *first* configured\nback-end.\n\nPasswords are obtained from the back-end as PBKDF2 strings (see [Passwords](#passwords) below). If you store a clear-text password or any hash not generated the same way,\nthe comparison and the authentication will fail.\n\nThe mysql and mongo back-ends support expansion of `%c` and `%u` as clientid and username\nrespectively. This allows ACLs in the database to look like this:\n\n```\n+-----------+---------------------------------+----+\n| username  | topic                           | rw |\n+-----------+---------------------------------+----+\n| bridge-01 | $SYS/broker/connection/%c/state |  2 |\n+-----------+---------------------------------+----+\n```\n\nThe plugin supports so-called _superusers_. These are usernames exempt\nfrom ACL checking. In other words, if a user is a _superuser_, that user\ncan access any topic without needing ACLs.\n\nA _static superuser_ is one configured with the _fnmatch(3)_ `auth_opt_superusers`\noption. Regular _superusers_ are configured (i.e., enabled) from within the\nparticular database back-end. Effectively, both are identical in that ACL\nchecking is disabled if a user is a superuser.\n\nNote that not all back-ends currently have 'superuser' queries implemented.\nThis is a todo and the `auth_opt_superusers` option will probably disappear when it is finished.\n\n## Building the plugin\n\nIn order to compile the plugin you'll require:\n* a copy of the [Mosquitto] source code together with the libraries required for the back-end you want to use in\nthe plugin, and\n* a recent version of OpenSSL (if the version with your OS, e.g., OS X, is too old, you may need to use one\nsupplied by home brew or build your own).\n\nCopy `config.mk.in` to `config.mk` and modify `config.mk` to suit your building environment. In particular, you have\nto configure which back-ends you want to provide as well as the path to the\n[Mosquitto] source and its library, and possibly the path to OpenSSL (`OPENSSLDIR`).\n\nAfter a `make` you should have a shared object called `auth-plug.so`\nwhich you will reference in your `mosquitto.conf`.\n\n## Configuration\n\nThe plugin is configured in [Mosquitto]'s configuration file (typically `mosquitto.conf`),\nand it is loaded into Mosquitto auth with the ```auth_plugin``` option.\n\n\n```\nauth_plugin /path/to/auth-plug.so\n```\n\nOptions therein with a leading ```auth_opt_``` are handed to the plugin. The following\n\"global\" ```auth_opt_*``` plugin options exist:\n\n| Option         | default    |  Mandatory  | Meaning               |\n| -------------- | ---------- | :---------: | --------------------- |\n| backends       |            |     Y       | comma-separated list of back-ends to load |\n| superusers     |            |             | fnmatch(3) case-sensitive string\n| log_quiet      | false      |             | don't log DEBUG messages |\n| cacheseconds   |                   |             | Deprecated. Alias for acl_cacheseconds\n| acl_cacheseconds  | 300               |             | number of seconds to cache ACL lookups. 0 disables\n| auth_cacheseconds | 0                 |             | number of seconds to cache AUTH lookups. 0 disables\n| acl_cachejitter   | 0                 |             | maximum number of seconds to add/remove to ACL lookups cache TTL. 0 disables\n| auth_cachejitter  | 0                 |             | maximum number of seconds to add/remove to AUTH lookups cache TTL. 0 disables\n\nIndividual back-ends each have various additional options described in the sections below.\n\nThere are two caches, one for ACL and another for authentication. By default only the ACL cache is enabled.\n\nAfter a backend responds (postitively or negatively) to an ACL or AUTH lookup, the result will be kept in cache for\nthe configured TTL. The same ACL lookup will be served from the cache as long as the TTL is valid.\nThe configured TTL is the `auth_cacheseconds`/`acl_cacheseconds` combined with a random value between -`auth_`/`acl_cachejitter` and +`auth_`/`acl_cachejitter`.\nFor example, with an acl_cacheseconds of 300 and acl_cachejitter of 10, ACL lookup TTLs are distributed between 290 and 310 seconds.\n\nSet auth/acl_cachejitter to 0 disable any randomization of cache TTL. Setting auth/acl_cacheseconds to 0 disables caching entirely.\nCaching is useful when your backend lookup is expensive. Remember that ACL lookup will be performed for each message which is sent/received on a topic.\nJitter is useful to reduce lookup storms that could occur every auth/acl_cacheseconds if lots of clients connect at the same time (for example,\nafter a server restart, all your clients may reconnect immediately and each cause ACL lookups every acl_cacheseconds).\n\n### MySQL auth\n\nThe `mysql` back-end is currently the most feature-complete: it supports\nobtaining passwords, checking for _superusers_, and verifying ACLs by\nconfiguring up to three distinct SQL queries used to obtain those results.\n\nYou configure the SQL queries in order to adapt to whichever schema\nyou currently have.\n\nThe following `auth_opt_` options are supported by the mysql back-end:\n\n| Option         | default           |  Mandatory  | Meaning               |\n| -------------- | ----------------- | :---------: | --------------------- |\n| host           | localhost         |             | hostname/address\n| port           | 3306              |             | TCP port\n| user           |                   |             | username\n| pass           |                   |             | password\n| dbname         |                   |     Y       | database name\n| userquery      |                   |     Y       | SQL for users\n| superquery     |                   |             | SQL for superusers\n| aclquery       |                   |             | SQL for ACLs\n| mysql_opt_reconnect | true         |             | enable MYSQL_OPT_RECONNECT option\n| mysql_auto_connect  | true         |             | enable auto_connect function\n| anonusername   | anonymous         |             | username to use for anonymous connections\n| ssl_enabled    | false \t     |\t\t   | enable SSL \n| ssl_key        |   \t \t     |\t\t   | path name of client private key file\n| ssl_cert       | \t \t     |\t\t   | path name of client public key certificate file  \n| ssl_ca         | \t \t     |\t\t   | path name of Certificate Authority(CA) certificate file \n| ssl_capath     | \t \t     |\t\t   | path name of directory that contains trusted CA certifcate files \n| ssl_cipher     | \t \t     |\t\t   | permitted ciphers for SSL encryption \n\nThe SQL query for looking up a user's password hash is mandatory. The query\nMUST return a single row only (any other number of rows is considered to be\n\"user not found\"), and it MUST return a single column with only the PBKDF2\npassword hash. Two `'%s'` in the `auth_opt_userquery` string are replaced by the\nusername attempting to access the broker and the clientid, in that order. If the clientid is not\nto be used in the SQL, insert just a single `'%s'`:\n\n```sql\nSELECT pw FROM users WHERE username = '%s' LIMIT 1\n```\n\nThe SQL query for checking whether a user is a _superuser_ - and thus\ncircumventing ACL checks - is optional. If it is specified, the query MUST\nreturn a single row with a single value: 0 is false and 1 is true. We recommend\nusing a `SELECT IFNULL(COUNT(*),0) FROM ...` for this query as it satisfies\nboth conditions. A single `'%s`' in the `auth_opt_superquery` string is replaced by the\nusername attempting to access the broker. The following example uses the\nsame `users` table, but it could just as well reference a distinct table\nor view.\n\n```sql\nSELECT IFNULL(COUNT(*), 0) FROM users WHERE username = '%s' AND super = 1\n```\n\nThe SQL query for checking ACLs is optional, but if it is specified, the\n`mysql` back-end can try to limit access to particular topics or topic branches\ndepending on the value of a database table. The query MAY return zero or more\nrows for a particular user, each containing EXACTLY one column containing a\ntopic (wildcards are supported). A single `'%s`' in the query string is\nreplaced by the username attempting to access the broker, and a single `'%d`' is\nreplaced with an integer, `1` signifying a read-only access attempt\n(SUB) or `2` signifying a read-write access attempt (PUB).\n\nIn the following example, the table has an `INT(1)` column `rw` containing `1` for\nreadonly topics, and `2` for read-write topics:\n\n```sql\nSELECT topic FROM acls WHERE (username = '%s') AND (rw \u003e= %d)\n```\n\nSample Mosquitto configuration (e.g., `mosquitto.conf`) for the `mysql` back-end:\n\n```\nauth_plugin /home/jpm/mosquitto-auth-plug/auth-plug.so\nauth_opt_host localhost\nauth_opt_port 3306\nauth_opt_dbname test\nauth_opt_user jjj\nauth_opt_pass supersecret\nauth_opt_userquery SELECT pw FROM users WHERE username = '%s'\n# auth_opt_userquery SELECT pwhash FROM user WHERE username = '%s' AND clientid = '%s'\nauth_opt_superquery SELECT COUNT(*) FROM users WHERE username = '%s' AND super = 1\nauth_opt_aclquery SELECT topic FROM acls WHERE (username = '%s') AND (rw \u003e= %d)\nauth_opt_anonusername AnonymouS\n```\n\nAssuming the following database tables:\n\n```\nmysql\u003e SELECT * FROM users;\n+----+----------+---------------------------------------------------------------------+-------+\n| id | username | pw                                                                  | super |\n+----+----------+---------------------------------------------------------------------+-------+\n|  1 | jjolie   | PBKDF2$sha256$901$x8mf3JIFTUFU9C23$Mid2xcgTrKBfBdye6W/4hE3GKeksu00+ |     0 |\n|  2 | a        | PBKDF2$sha256$901$XPkOwNbd05p5XsUn$1uPtR6hMKBedWE44nqdVg+2NPKvyGst8 |     0 |\n|  3 | su1      | PBKDF2$sha256$901$chEZ4HcSmKtlV0kf$yRh2N62uq6cHoAB6FIrxIN2iihYqNIJp |     1 |\n+----+----------+---------------------------------------------------------------------+-------+\n\nmysql\u003e SELECT * FROM acls;\n+----+----------+-------------------+----+\n| id | username | topic             | rw |\n+----+----------+-------------------+----+\n|  1 | jjolie   | loc/jjolie        |  1 |\n|  2 | jjolie   | $SYS/something    |  1 |\n|  3 | a        | loc/test/#        |  1 |\n|  4 | a        | $SYS/broker/log/+ |  1 |\n|  5 | su1      | mega/secret       |  1 |\n|  6 | nop      | mega/secret       |  1 |\n+----+----------+-------------------+----+\n```\n\nthe above SQL queries would enable the following combinations (the `*` at\nthe beginning of the line indicates a _superuser_)\n\n```\n  jjolie     PBKDF2$sha256$901$x8mf3JIFTUFU9C23$Mid2xcgTrKBfBdye6W/4hE3GKeksu00+\n\tloc/a                                    DENY\n\tloc/jjolie                               PERMIT\n\tmega/secret                              DENY\n\tloc/test                                 DENY\n\t$SYS/broker/log/N                        DENY\n  nop        \u003cnil\u003e\n\tloc/a                                    DENY\n\tloc/jjolie                               DENY\n\tmega/secret                              PERMIT\n\tloc/test                                 DENY\n\t$SYS/broker/log/N                        DENY\n  a          PBKDF2$sha256$901$XPkOwNbd05p5XsUn$1uPtR6hMKBedWE44nqdVg+2NPKvyGst8\n\tloc/a                                    DENY\n\tloc/jjolie                               DENY\n\tmega/secret                              DENY\n\tloc/test                                 PERMIT\n\t$SYS/broker/log/N                        PERMIT\n* su1        PBKDF2$sha256$901$chEZ4HcSmKtlV0kf$yRh2N62uq6cHoAB6FIrxIN2iihYqNIJp\n\tloc/a                                    PERMIT\n\tloc/jjolie                               PERMIT\n\tmega/secret                              PERMIT\n\tloc/test                                 PERMIT\n\t$SYS/broker/log/N                        PERMIT\n```\n\nThe `mysql` back-end will re-connect to the MySQL server when the connection has been lost.\nIf you wish, you can disable this by configuring:\n\n```\nauth_opt_mysql_opt_reconnect false\nauth_opt_mysql_auto_connect false\n```\n\n### LDAP auth\n\nThe LDAP plugin currently does authentication only; authenticated users are allowed\nto publish/subscribe at will.\n\nThe user that connects to the broker is searched for in the LDAP directory indicated\nvia the `ldap_uri` configuration parameter. This LDAP search MUST return exactly one\nentry. The user's password is then used with the DN of the that entry to bind to the\ndirectory. If that LDAP bind succeeds, the user is authenticated. In all other cases,\nauthentication fails.\n\n\n| Option         | default           |  Mandatory  | Meaning     |\n| -------------- | ----------------- | :---------: | ----------  |\n| binddn         |                   |     Y       | the DN of an object which may search users |\n| bindpw         |                   |     Y       | its password                               |\n| ldap_uri       |                   |     Y       | an LDAP uri with filter                    |\n| ldap_acl_deny  | false             |             | return DENY instead of ALLOW to ACL checks |\n\nExample configuration:\n\n```\nauth_plugin /path/to/auth-plug.so\nauth_opt_backends ldap\nauth_opt_binddn cn=manager,dc=mens,dc=de\nauth_opt_bindpw s3crit\nauth_opt_ldap_uri ldap://127.0.0.1/ou=Users,dc=mens,dc=de?cn?sub?(\u0026(objectclass=inetOrgPerson)(uid=@))\nauth_opt_ldap_acl_deny false\n```\n\nWith the `ldap_acl_deny` we return DENY instead of ALLOW for every ACL check. This makes it possible to chain other backends with ldap backend, and use LDAP for authentification and, e.g., MySQL for ACL checking.\n\n### CDB auth\n\n| Option         | default           |  Mandatory  | Meaning     |\n| -------------- | ----------------- | :---------: | ----------  |\n| cdbname        |                   |     Y       | path to .cdb |\n\n### SQLITE auth\n\n| Option          | default           |  Mandatory  | Meaning     |\n| --------------- | ----------------- | :---------: | ----------  |\n| dbpath          |                   |     Y       | path to database |\n| sqliteuserquery |                   |     Y       | SQL for users |\n\nExample:\n\n```\nauth_opt_sqliteuserquery SELECT pw FROM users WHERE username = ?\n```\n\n### Redis auth\n\n\n```\nauth_opt_redis_userquery GET %s\nauth_opt_redis_aclquery GET %s-%s\n```\n\nIn `auth_opt_redis_userquery` the `%s` parameter is the _username_, whereas in `auth_opt_redis_aclquery`, the first `%s` is the _username_ and the second is the _topic_. When using ACLs, _topic_ must be an exact match - wildcards are not supported.\n\nIf no options are provided, then the plugin will default to not using an ACL and using the above userquery.\n\n\n| Option         | default           |  Mandatory  | Meaning     |\n| -------------- | ----------------- | :---------: | ----------  |\n| redis_host     | localhost         |             | hostname / IP address\n| redis_port     | 6379              |             | TCP port number |\n\n### HTTP auth\n\nThe `http` back-end is for auth by custom HTTP API.\n\nThe following `auth_opt_` options are supported by the `http` back-end:\n\n| Option            | default           |  Mandatory  | Meaning     |\n| ----------------- | ----------------- | :---------: | ----------  |\n| http_ip           |                   |      Y      | IP address, will skip DNS lookup |\n| http_port         | 80                |             | TCP port number                 |\n| http_hostname     |                   |             | hostname for HTTP header        |\n| http_getuser_uri  |                   |      Y      | URI for checking username/password |\n| http_superuser_uri|                   |      Y      | URI for checking superuser         |\n| http_aclcheck_uri |                   |      Y      | URI for checking acl               |\n| http_with_tls     | false             |             | Use TLS on connect              |\n| http_basic_auth_key|                  |             | Basic Authentication Key        |\n| http_retry_count  | 3                 |             | Number of retries done if backend is unavailable |\n\nIf the configured URLs return an HTTP status code == `2xx`, the authentication /\nauthorization succeeds. If the status code == `4xx`, authentication /\nauthorization fails. For a status code == `5xx` or server `Unreachable`, the HTTP request\nwill be retried up to `http_retry_count`. If all tries fail and if no other backend succeeded,\nthen an error is returned and the client is disconnected.\n\n| URI-Param         | username | password | clientid | topic | acc |\n| ----------------- | -------- | -------- | -------- | :---: | :-: |\n| http_getuser_uri  |   Y      |   Y      |   N      |   N   |  N  |\n| http_superuser_uri|   Y      |   N      |   N      |   N   |  N  |\n| http_aclcheck_uri |   Y      |   N      |   Y      |   Y   |  Y  |\n\nMosquitto configuration for the `http` back-end:\n\n```\nauth_opt_backends http\nauth_opt_http_ip 127.0.0.1\nauth_opt_http_port 8089\n#auth_opt_http_hostname example.org\nauth_opt_http_getuser_uri /auth\nauth_opt_http_superuser_uri /superuser\nauth_opt_http_aclcheck_uri /acl\n```\n\nA very simple example service using Python and [bottle](https://bottlepy.org/docs/dev/) can be found in [examples/http-auth-be.py](examples/http-auth-be.py).\n\nThe _http_ plugin can utilize environment variables which are exported before it (i.e., Mosquitto) is started by adding configuration settings like\n\n```\nauth_opt_\u003cinterface\u003e_\u003cmethod\u003e_params \u003ckey\u003e=\u003cevn_name\u003e[,\u003ckey\u003e=\u003cevn_name\u003e]*\n```\n\nFor example, set the following:\n\n```bash\nexport DOMAIN=example.com\nexport PORT=8080\n```\n\nand add the following settings to `mosquitto.conf`:\n\n```\nauth_opt_http_getuser_params domain=DOMAIN,port=PORT\nauth_opt_http_superuser_params domain=DOMAIN,port=PORT\nauth_opt_http_aclcheck_params domain=DOMAIN,port=PORT\n```\n\n\n\n### JWT auth\n\nThe `jwt` back-end is for auth by [JWT-webtokens](https://jwt.io/). The JWT and HTTP configurations are identical, so please read the `http`-section above.\n\nThe `username` field is interpreted as the token-field and passed to the http-server in an Authorization-header.\n```\nAuthorization: Bearer %token\n```\n\n**Note**: Some clients require the `password` field to be populated. This field is ignored by the JWT-backend, so feel free to input some gibberish.\n\n\n\n### PostgreSQL auth\n\nThe `postgres` back-end, like `mysql`, is currently the most feature-complete: it supports\ndistinct SQL queries for obtaining passwords, checking for _superusers_, and verifying ACLs,\neach configurable to suit your schema.\n\nThe following `auth_opt_` options are supported by the `postgres` back-end:\n\n| Option         | default           |  Mandatory  | Meaning                  |\n| -------------- | ----------------- | :---------: | ------------------------ |\n| host           | localhost         |             | hostname/address\n| port           | 5432              |             | TCP port\n| user           |                   |             | username\n| pass           |                   |             | password\n| dbname         |                   |     Y       | database name\n| userquery      |                   |     Y       | SQL for users\n| superquery     |                   |             | SQL for superusers\n| aclquery       |                   |             | SQL for ACLs\n| sslcert        |                   |             | SSL/TLS Client Cert.\n| sslkey         |                   |             | SSL/TLS Client Cert. Key\n\nThe SQL query for looking up a user's password hash is mandatory. The query\n**must** return a single row only (any other number of rows is considered to be\n\"user not found\"), and it **must** return a single column only with the PBKDF2\npassword hash. A single `$1` in the query string is replaced by the\nusername attempting to access the broker.\n\n```sql\nSELECT pass FROM account WHERE username = $1 limit 1\n```\n\nThe SQL query for checking whether a user is a _superuser_ - and thus\ncircumventing ACL checks - is optional. If it is specified, the query **must**\nreturn a single row with a single value: 0 is false and 1 is true. We recommend\nusing a `SELECT COALESCE(COUNT(*),0) FROM ...` for this query as it satisfies\nboth conditions. A single `$1` in the `auth_opt_superquery` string is replaced by the\nusername attempting to access the broker. The following example uses the\nsame `account` table, but it could just as well reference a distinct table\nor view.\n\n```sql\nSELECT COALESCE(COUNT(*),0) FROM account WHERE username = $1 AND super = 1\n```\n\nThe SQL query for checking ACLs is optional, but if it is specified, the\n`postgres` back-end can try to limit access to particular topics or topic branches\ndepending on the value of a database table. The query MAY return zero or more\nrows for a particular user, each containing EXACTLY one column containing a\ntopic (wildcards are supported). A single `$1` in the query string is\nreplaced by the username attempting to access the broker, and a single `$2` is\nreplaced with an integer, `1` signifying a read-only access attempt\n(SUB) or `2` signifying a read-write access attempt (PUB).\n\nIn the following example, the table has a column `rw` containing 1 for\nreadonly topics, 2 for writeonly topics and 3 for readwrite topics:\n\n```sql\nSELECT topic FROM acl WHERE (username = $1) AND rw \u003e= $2\n```\n\nSample Mosquitto configuration for the `postgres` back-end:\n\n```\nauth_plugin /home/jpm/mosquitto-auth-plug/auth-plug.so\nauth_opt_host localhost\nauth_opt_port 5432\nauth_opt_dbname test\nauth_opt_user jjj\nauth_opt_pass supersecret\nauth_opt_userquery SELECT pw FROM account WHERE username = $1 limit 1\nauth_opt_superquery SELECT COALESCE(COUNT(*),0) FROM account WHERE username = $1 AND mosquitto_super = 1\nauth_opt_aclquery SELECT topic FROM acls WHERE (username = $1) AND (rw \u0026 $2) \u003e 0\nauth_opt_sslcert /etc/postgresql/ssl/client.crt\nauth_opt_sslkey /etc/postgresql/ssl/client.key\n```\nAssuming the following database tables:\n\n```\n=\u003e SELECT * FROM account;\n+----+----------+---------------------------------------------------------------------+-------+\n| id | username | pw                                                                  | super |\n+----+----------+---------------------------------------------------------------------+-------+\n|  1 | jjolie   | PBKDF2$sha256$901$x8mf3JIFTUFU9C23$Mid2xcgTrKBfBdye6W/4hE3GKeksu00+ |     0 |\n|  2 | a        | PBKDF2$sha256$901$XPkOwNbd05p5XsUn$1uPtR6hMKBedWE44nqdVg+2NPKvyGst8 |     0 |\n|  3 | su1      | PBKDF2$sha256$901$chEZ4HcSmKtlV0kf$yRh2N62uq6cHoAB6FIrxIN2iihYqNIJp |     1 |\n+----+----------+---------------------------------------------------------------------+-------+\n\n=\u003e SELECT * FROM acls;\n+----+----------+-------------------+----+\n| id | username | topic             | rw |\n+----+----------+-------------------+----+\n|  1 | jjolie   | loc/jjolie        |  1 |\n|  2 | jjolie   | $SYS/something    |  1 |\n|  3 | a        | loc/test/#        |  1 |\n|  4 | a        | $SYS/broker/log/+ |  1 |\n|  5 | su1      | mega/secret       |  1 |\n|  6 | nop      | mega/secret       |  1 |\n+----+----------+-------------------+----+\n```\n\nthe above SQL queries would enable the following combinations (the `*` at\nthe beginning of the line indicates a _superuser_)\n\n```\n  jjolie     PBKDF2$sha256$901$x8mf3JIFTUFU9C23$Mid2xcgTrKBfBdye6W/4hE3GKeksu00+\n  loc/a                                    DENY\n  loc/jjolie                               PERMIT\n  mega/secret                              DENY\n  loc/test                                 DENY\n  $SYS/broker/log/N                        DENY\n  nop        \u003cnil\u003e\n  loc/a                                    DENY\n  loc/jjolie                               DENY\n  mega/secret                              PERMIT\n  loc/test                                 DENY\n  $SYS/broker/log/N                        DENY\n  a          PBKDF2$sha256$901$XPkOwNbd05p5XsUn$1uPtR6hMKBedWE44nqdVg+2NPKvyGst8\n  loc/a                                    DENY\n  loc/jjolie                               DENY\n  mega/secret                              DENY\n  loc/test                                 PERMIT\n  $SYS/broker/log/N                        PERMIT\n* su1        PBKDF2$sha256$901$chEZ4HcSmKtlV0kf$yRh2N62uq6cHoAB6FIrxIN2iihYqNIJp\n  loc/a                                    PERMIT\n  loc/jjolie                               PERMIT\n  mega/secret                              PERMIT\n  loc/test                                 PERMIT\n  $SYS/broker/log/N                        PERMIT\n```\n\n_Note that the above sample `auth_opt_aclquery` is sensitive to [new permission values used in Mosquitto 1.5.](#https://github.com/jpmens/mosquitto-auth-plug/issues/356)_\n\nYou can either adapt to the updated binary-style permissions \n(`2` for write, `5` for read+subscribe, `7` for read/write),\nmodify your query to work around them, or modify the constants in the Mosquitto source.\n\n## MongoDB auth\nThe `mongo` back-end works with superuser and ACL checks. Additional build dependencies are https://github.com/mongodb/mongo-c-driver `\u003e=1.4.0`\nand https://github.com/mongodb/libbson `\u003e=1.4.0`.\n\nYou should set up a users collection (required) and a topic lists collection (optional) with the following format:\n\n#### Users collection\n\nEach user document must have a username, a hashed password, and at least one of:\n\n - A superuser prop, allowing full access to all topics\n - An embedded array or sub-document to use as an ACL (see 'ACL format')\n - A foreign key pointing to another document containing an ACL (see 'ACL format')\n\nYou may use any combination of these options; authorisation will be granted if any check passes.\n\nThe user document has the following format (note that the property names are configurable variables, see 'Configuration').\n\n```\n{\n    [user_username_prop]: string, // Username as given in the MQTT connect request\n    [user_password_prop]: string, // A PBKDF2 hash, see 'Passwords' section\n    [user_topiclist_fk_prop]: int | oid | string, // reference to a document in collection_topics)\n    [user_topics_prop]: string[] | { [topic: string]: \"r\"|\"w\"|\"rw\" }, // see 'ACL format'\n    [user_superuser_prop]: int | boolean // optional, superuser if truthy\n}\n```\n\nAs an example using default options, a user document with an embedded ACL might look like:\n\n```json\n{\n    \"username\": \"user1\",\n    \"password\": \"PBKDF2$sha256$901$8ebTR72Pcmjl3cYq$SCVHHfqn9t6Ev9sE6RMTeF3pawvtGqTu\",\n    \"superuser\": false,\n    \"topics\": {\n        \"public/#\": \"r\",\n\t\"client/user1/#\": \"rw\"\n    }\n}\n```\n\n#### Topic lists collection (optional)\n\nIf the user document references a separate topics document, that document should exist and must have the format:\n\n```\n{\n    [topiclist_key_prop]: int | oid | string, // unique id, as referenced by users[user_topiclist_fk_prop],\n    [topiclist_topics_prop]: string[] | { [topic: string]: \"r\"|\"w\"|\"rw\" } // see 'ACL format'\n}\n```\n\nThis strategy will be especially suitable if you have a complex ACL shared between many users.\n\n#### ACL format\n\nTopics may be given as either an array of topic strings, eg `[\"topic1/#\", \"topic2/+\"]`, in which case all topics will\nbe read-write, or as a sub-document mapping topic names to the strings `\"r\"`, `\"w\"`, `\"rw\"`, eg\n`{ \"article/#\":\"r\", \"article/+/comments\":\"rw\", \"ballotbox\":\"w\" }`.\n\n#### Configuration\n\nThe following `auth_opt_mongo_` options are supported by the mongo back-end:\n\n| Option                 | default       | Meaning               |\n| ---------------------- | ------------- | --------------------- |\n| uri                    | mongodb://localhost:27107 | [MongoDB connection string] (database part is ignored)\n| database               | mqGate                    | Name of the database containing users (and topiclists)\n| user_coll              | users                     | Collection for user documents\n| topiclist_coll         | topics                    | Collection for topiclist documents (optional if embedded topics are used)\n| user_username_prop     | username                  | Username property name in the user document\n| user_password_prop     | password                  | Password property name in the user document\n| user_superuser_prop    | superuser                 | Superuser property name in the user document\n| user_topics_prop       | topics                    | Name of a property on the user document containing an embedded topic list\n| user_topiclist_fk_prop | topics                    | Property used as a foreign key to reference a topiclist document\n| topiclist_key_prop     | _id                       | Unique key in the topiclist document pointed to by user_topiclist_fk_prop\n| topiclist_topics_prop  | topics                    | Property containing topics within the topiclist document\n\nMosquitto configuration for the `mongo` back-end:\n```\nauth_plugin /home/jpm/mosquitto-auth-plug/auth-plug.so\nauth_opt_mongo_uri mongodb://localhost:27017\n```\n## Files auth\n\nThe `files` backend attempts to re-implement the files behavior in vanilla Mosquitto, however the user's password file contains PBKDF2 passwords instead of passwords hashed with the `mosquitto-passwd` program; you would use our `np` utility or similar to create the PBKDF2 hashes.\n\nThe configuration directives for the `Files` backend are as follows:\n\n```\nauth_opt_backends files\nauth_opt_password_file file.pw\nauth_opt_acl_file file.acl\n```\n\nwith examples of these files being:\n\n#### `password_file`\n\n```\n# comment\njpm:PBKDF2$sha256$901$UGfDz79cAaydRsEF$XvYwauPeviFd1NfbGL+dxcn1K7BVfMeW\njane:PBKDF2$sha256$901$wvvH0fe7Ftszt8nR$NZV6XWWg01dCRiPOheVNsgMJDX1mzd2v\n```\n\n#### `acl_file`\n\n```\nuser jane\ntopic read #\n\nuser jpm\ntopic dd\n\n```\n\nThe syntax for the ACL file is that as described in `mosquitto.conf(5)`.\n\n## PSK auth\n\nIf [Mosquitto] has been built with PSK support, and _auth-plug_ has been built\nwith `BE_PSK` defined, it supports authenticating PSK connections over TLS, as\nlong as Mosquitto is appropriately configured.\n\nThe way this works is that the `psk` back-end actually uses one of _auth-plug_'s\nother databases (`mysql`, `sqlite`, `cdb`, etc.) to obtain the pre-shared key\nfrom the \"users\" query, and it uses the same database's back-end for performing\nauthorization (aka ACL checks).\n\nConsider the following `mosquitto.conf` snippet:\n\n```\n...\nauth_opt_psk_database mysql\n...\nlistener 8885\npsk_hint hint1\ntls_version tlsv1\nuse_identity_as_username true\n```\n\nTLS PSK is available on port 8885 and is activated with, say,\n\n```\nmosquitto_pub -h localhost -p 8885 -t x -m hi --psk-identity ps2 --psk 020202\n```\n\nThe `use_identity_as_username` option has _auth-plug_ see the name `ps2` as the\nusername, and this is given to the database back-end (here: `mysql`) to look up\nthe password as defined for the `mysql` back-end. _auth-plug_ uses its `getuser()` query\nto read the clear-text (not PKBDF2) hex key string which it returns to Mosquitto\nfor authentication. If authentication passes, the connection is established.\n\nFor authorization, _auth_plug_ uses the identity as the username and the topic to\nperform ACL-checking as described earlier.\n\nThe following log-snippet serves as an illustration:\n\n```\nNew connection from ::1 on port 8885.\n|-- psk_key_get(hint1, ps1) from [mysql] finds PSK: 1\nNew client connected from ::1 as mosqpub/90759-tiggr.ww. (c1, k60).\nSending CONNACK to mosqpub/90759-tiggr.ww. (0)\n|-- user ps1 was authenticated in back-end 0 (psk)\n|--   mysql: topic_matches(x, x) == 1\n|-- aclcheck(ps1, x, 2) AUTHORIZED=1 by psk\nReceived PUBLISH from mosqpub/90759-tiggr.ww. (d0, q0, r0, m0, 'x', ... (2 bytes))\nReceived DISCONNECT from mosqpub/90759-tiggr.ww.\n```\n\nIn the case of this MySQL example, we added the clear text of the PSK key to the database:\n\n```\nmysql\u003e INSERT INTO user (username, pwhash, superuser) VALUES ('mylistener', 'F0BEEF', 0);\n```\n\n## Passwords\n\nA user's password is stored as a [PBKDF2] hash in the back-end. An example\n\"password\" is a string with five pieces in it, delimited by `$`, inspired by\n[this][1].\n\n```\nPBKDF2$sha256$901$8ebTR72Pcmjl3cYq$SCVHHfqn9t6Ev9sE6RMTeF3pawvtGqTu\n--^--- --^--- -^- ------^--------- -------------^------------------\n  |      |     |        |                       |\n  |      |     |        |                       +-- : hashed password\n  |      |     |        +-------------------------- : salt\n  |      |     +----------------------------------- : iterations\n  |      +----------------------------------------- : hash function\n  +------------------------------------------------ : marker\n```\n\nNote that the `salt` by default will be taken as-is (thus it will not be\nbase64 decoded before the validation). In case your own implementation uses\nthe raw bytes when hashing the password and base64 is only used for display\npurpose, compile this project with the `-DRAW_SALT` flag (you could add this\nin the `config.mk` file to `CFG_CFLAGS`).\n\n## Creating a user\n\nA trivial utility to generate hashes is included as `np`. Copy and paste the\nwhole string generated into the respective back-end.\n\n```bash\n$ np\nEnter password:\nRe-enter same password:\nPBKDF2$sha256$901$Qh18ysY4wstXoHhk$g8d2aDzbz3rYztvJiO3dsV698jzECxSg\n```\n\nFor example, in [Redis][Redis-Ext]:\n\n```\n$ redis-cli\n\u003e SET n2 PBKDF2$sha256$901$Qh18ysY4wstXoHhk$g8d2aDzbz3rYztvJiO3dsV698jzECxSg\n\u003e QUIT\n```\n\n## Configuring Mosquitto\n\n```\nlistener 1883\n\nauth_plugin /path/to/auth-plug.so\nauth_opt_redis_host 127.0.0.1\nauth_opt_redis_port 6379\n\n# Usernames with this fnmatch(3) (a.k.a glob(3))  pattern are exempt from the\n# module's ACL checking\nauth_opt_superusers S*\n```\n\n## ACL\n\nIn addition to the ACL checking which might be performed by a back-end,\nthere's a more \"static\" checking which can be configured in `mosquitto.conf`.\n\nNote that if ACLs are being verified by the plugin, this also applies to\nWill topics (_last will and testament_). Failing to correctly set up\nan ACL for these, will cause a broker to silently fail with a 'not\nauthorized' message.\n\nUsers can be given \"superuser\" status (i.e. they may access any topic)\nif their username matches the _glob_ specified in `auth_opt_superusers`.\n\nIn our example above, any user with a username beginning with a capital `\"S\"`\nis exempt from ACL-checking.\n\n## PUB/SUB\n\nAt this point you ought to be able to connect to [Mosquitto] using, e.g., the Mosquitto client: \n\n```\nmosquitto_pub  -t '/location/n2' -m hello -u n2 -P secret\n```\n\n## Requirements\n\n* A [Mosquitto] broker\n* OpenSSL (tested with 1.0.0c, but should work with earlier versions)\n\nSome of the back-ends require a server instance or client libraries. For example:\n* for [redis]: a [Redis][Redis-Ext] server and [hiredis], the Minimalistic C client for Redis\n* for [cdb]: [TinyCDB](http://www.corpit.ru/mjt/tinycdb.html) by Michael Tokarev (included in `contrib/`)\n* for [postgres]: the latest `dev` version of `postgresql-server`\n\n## Credits\n\n* Uses `base64.[ch]` (and yes, I know OpenSSL has base64 routines, but no thanks). These files are\n\u003e  Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan (Royal Institute of Technology, Stockholm, Sweden).\n* Uses [uthash] by Troy D. Hanson.\n\n\n [Mosquitto]: http://mosquitto.org\n [Redis-Ext]: http://redis.io\n [pbkdf2]: http://en.wikipedia.org/wiki/PBKDF2\n [1]: https://exyr.org/2011/hashing-passwords/\n [hiredis]: https://github.com/redis/hiredis\n [uthash]: http://troydhanson.github.io/uthash/\n [MongoDB connection string]: https://docs.mongodb.com/manual/reference/connection-string/\n \n [mysql]: #mysql-auth\n [postgres]: #postgresql-auth\n [cdb]: #cdb-auth\n [sqlite]: #sqlite-auth\n [redis]: #redis-auth\n [psk]: #psk-auth\n [ldap]: #ldap-auth\n [http]: #http-auth\n [jwt]: #jwt-auth\n [mongo]: #mongodb-auth\n [files]: #files-auth\n\n## Possibly related\n\n * [docker-mosquitto](https://github.com/jllopis/docker-mosquitto) - easy installation of this plugin\n * [mosquitto_pyauth](https://github.com/mbachry/mosquitto_pyauth)\n * [mosquitto-auth-plugin-http](https://github.com/hadleyrich/mosquitto-auth-plugin-http)\n * [lua_auth_plugin](https://github.com/DenkiYagi/lua_auth_plugin)\n\n## Press\n\n * [How to make Access Control Lists (ACL) work for Mosquitto MQTT Broker with Auth Plugin](http://my-classes.com/2015/02/05/acl-mosquitto-mqtt-broker-auth-plugin/)\n * [PostgreSQL-based MQTT access control](https://mberka.com/web/postgresql-based-mqtt-access-control)\n * [Raspberry Pi: How to install MQTT broker and mosquitto auth plugin](http://wei48221.blogspot.com/2017/08/raspberry-pi-how-to-install-mqtt-broker.html)\n * [Securing MQT connection using Mosquitto Auth Plugin - HTTP API](http://www.yasith.me/2016/04/securing-mqtt-connection-using.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenherrring%2Fmosquitto-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenherrring%2Fmosquitto-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenherrring%2Fmosquitto-auth/lists"}