This is an authentication plugin for mosquitto written (almost) entirely in Go. It uses cgo to expose mosquitto's auth plugin needed functions, but internally just calls Go to get everything done. It is greatly inspired in [jpmens'](https://github.com/jpmens) [mosquitto-auth-plug](https://github.com/jpmens/mosquitto-auth-plug).
As it was intended for use with [brocaar's](https://github.com/brocaar) [Loraserver project](https://www.loraserver.io/), right now it only implements a few backends for authentication and authorization, namely those that make sense for that project:
Though the plugin may have multiple backends enabled, there's a way to specify which backends must be used for a given user: prefixes. When enabled, prefixes allows to check if the username contains a predefined prefix in the form prefix_rest_of_username and use the configured backend for that prefix. Options to enable and set prefixes are the following:
Prefixes must meet the backends' order and number. If amounts don't match, the plugin will default to prefixes disabled.
Underscores (\_) are not allowed in the prefixes, as a username's prefix will be checked against the first underscore's index. Of course, if a username has no underscore or valid prefix, it'll be checked against all backends.
verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA)
verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate)
depending on the value of a database table. The query MAY return zero or more
rows for a particular user, each returning EXACTLY one column containing a
topic (wildcards are supported). A single `'$1`' in the query string is
replaced by the username attempting to access the broker, and a single `'$2`' is
replaced with the integer value `1` signifying a read-only access attempt
(SUB) or `2` signifying a read-write access attempt (PUB).
In the following example, the table has a column `rw` containing 1 for
readonly topics, 2 for writeonly topics and 3 for readwrite topics:
```sql
SELECT topic FROM acl WHERE (username = $1) AND rw >= $2
```
Example configuration:
```
auth_opt_pg_host localhost
auth_opt_pg_port 5432
auth_opt_pg_dbname appserver
auth_opt_pg_user appserver
auth_opt_pg_password appserver
auth_opt_pg_userquery select password_hash from "user" where username = $1 and is_active = true limit 1
auth_opt_pg_superquery select count(*) from "user" where username = $1 and is_admin = true
auth_opt_pg_aclquery select distinct 'application/' || a.id || '/#' from "user" u inner join organization_user ou on ou.user_id = u.id inner join organization o on o.id = ou.organization_id inner join application a on a.organization_id =$
The `mysql` backend works almost exactly as the `postgres` one, except for a couple of configurations and that options start with `mysql_` instead of `pg_`. One change has to do with the connection protocol, either a Unix socket or tcp (options are unix or tcp). If unix socket is the selected protocol, then a socket path must be given:
```
auth_opt_mysql_protocol unix
auth_opt_mysql_socket /path/to/socket
```
The default protocol when the option is missing will be tcp, even if a socket path is given.
Another change has to do with sslmode options, with options being true, false, skip-verify or custom. When custom mode is given, sslcert, sslkey and sslrootcert paths are expected. If the option is not set or one or more required paths are missing, it will default to false.
The 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 may use the `pw` utility included in the plugin or build your own. Check pw-gen dir to check `pw` flags.
The configuration directives for the `Files` backend are as follows:
When set as remote false, the backend will try to validate JWT tokens against a postgres DB. Options for the DB connection are the same as the ones given in the Postgres backend, but include one new option and 3 options that will voerride Postgres' ones only for JWT cases (in case both backends are needed).
Also, as it uses the postgres backend for local auth, the following postgres options must be set, though queries (pg_userquery, pg_superquery and pg_aclquery) need not to be correct if the postgres backend is not used as they'll be over overridden by the jwt queries when jwt is used for auth:
Queries will override postgre's backend ones when checking for JWT tokens. Options for the queries are the same except for the user query, which now expects an integer result instead of a password hash, as the JWT token needs no password checking. An example of a different query using the same DB is given for the user query.
```
auth_opt_jwt_userquery select count(*) from "user" where username = $1 and is_active = true limit 1
The `redis` backend allows to check user, superuser and acls in a defined format. As with postgres and files, passwords hash must be stored and can be created with the `pw` utility.
For user check, Redis must contain a KEY with the username and the password hash as a value:
For superuser check, a user will be a superuser if there exists a KEY username:su and it return a string value "true".
Normal and Wildcard acls are supported and are expected to be stored in a SET with KEY username:acls, with the members being the allowed acls following the conventional format (as in files).