Authentication#
User Authentication#
Mainflux uses JWT-based authentication keys for all user-facing operations. There are three types of authentication keys:
| Key type | Issued by | Expiry | Revocable | Purpose |
|---|---|---|---|---|
| Login key | Login endpoint | Short-lived (session) | No | Authenticates interactive sessions |
| API key | User request | Configurable (default: never) | Yes | Long-lived programmatic access |
| Recovery key | Password reset flow | Short-lived | No | Password recovery only |
Login keys are issued automatically when a user logs in. They expire after a short session period and cannot be revoked individually. Every authenticated request (other than registration and login) must carry a valid key in the Authorization: Bearer <key> header.
API keys are created on demand and provide stable, long-lived access for scripts, integrations, and automated workflows. They can be given an explicit expiration time; if none is set, they never expire. Because API keys must be validated against the database on each request (unlike login keys, which are self-contained JWTs), they are the only key type that supports revocation. An API key holder can perform all the same operations as a logged-in user — managing things, profiles, groups, and the user's own profile — except creating additional API keys.
Recovery keys are short-lived tokens generated during the password reset flow. They are single-use and expire quickly.
Supported operations per key type:
| Operation | Login key | API key | Recovery key |
|---|---|---|---|
| Create | ✓ | ✓ | ✓ |
| Verify | ✓ | ✓ | ✓ |
| List | — | ✓ | — |
| Revoke | — | ✓ | — |
Device Authentication#
Mainflux authenticates devices using Thing keys — secret keys generated by the platform when a thing is provisioned. There are two thing key types:
| Key type | Header scheme | Set by | Use case |
|---|---|---|---|
| Internal key | Authorization: Thing <key> |
Platform at provisioning | Standard device authentication |
| External key | Authorization: External <key> |
User or hardware provisioner | Hardware-provisioned or pre-shared keys |
The platform resolves either key type to the thing's identity when processing inbound messages. The external key can be updated or removed independently via the API without reprovisioning the thing.
For details on how keys are passed per protocol (HTTP, MQTT, CoAP), see the messaging section.
This is the default device authentication mechanism and it is active when the composition is started using the following command:
docker-compose -f docker/docker-compose.yml up
Mutual TLS Authentication with X.509 Certificates#
In most of the cases, HTTPS, MQTTS or secure CoAP are secure enough. However, sometimes you might need an even more secure connection. Mainflux supports mutual TLS authentication (mTLS) based on X.509 certificates. By default, the TLS protocol only proves the identity of the server to the client using the X.509 certificate and the authentication of the client to the server is left to the application layer. TLS also offers client-to-server authentication using client-side X.509 authentication. This is called two-way or mutual authentication. Mainflux currently supports mTLS over HTTP, MQTT and MQTT over WS protocols. In order to run Docker composition with mTLS turned on, you can execute the following command from the project root:
AUTH=x509 docker-compose -f docker/docker-compose.yml up -d
Mutual authentication includes client-side certificates. Certificates can be generated using the simple script provided here. In order to create a valid certificate, you need to create Mainflux thing. After that, you need to fetch created thing key. Thing key will be used to create x.509 certificate for the corresponding thing. To create a certificate, execute the following commands:
cd docker/ssl
make ca CN=<common_name> O=<organization> OU=<organizational_unit> emailAddress=<email_address>
make server_cert CN=<common_name> O=<organization> OU=<organizational_unit> emailAddress=<email_address>
make thing_cert THING_KEY=<thing_key> CRT_FILE_NAME=<cert_name> O=<organization> OU=<organizational_unit> emailAddress=<email_address>
These commands use OpenSSL tool, so please make sure that you have it installed and set up before running these commands. The default values for Makefile variables are
CRT_LOCATION = certs
THING_KEY = d7cc2964-a48b-4a6e-871a-08da28e7883d
O = Mainflux
OU = mainflux
EA = info@mainflux.com
CN = localhost
CRT_FILE_NAME = thing
Normally, in order to get things running, you will need to specify only THING_KEY. The other variables are not mandatory and the termination should work with the default values.
- Command
make cawill generate a self-signed certificate that will later be used as a CA to sign other generated certificates. CA will expire in 3 years. - Command
make server_certwill generate and sign (with previously created CA) server cert, which will expire after 1000 days. This cert is used as a Mainflux server-side certificate in usual TLS flow to establish HTTPS or MQTTS connection. - Command
make thing_certwill finally generate and sign a client-side certificate and private key for the thing.
In this example <thing_key> represents key of the thing and <cert_name> represents the name of the certificate and key file which will be saved in docker/ssl/certs directory. Generated Certificate will expire after 2 years. The key must be stored in the x.509 certificate CN field. This script is created for testing purposes and is not meant to be used in production. We strongly recommend avoiding self-signed certificates and using a certificate management tool such as Vault for the production.
Once you have created CA and server-side cert, you can spin the composition using:
AUTH=x509 docker-compose -f docker/docker-compose.yml up -d
Then, you can create user and provision things and profiles within the same group. Now, in order to send a message from the specific thing (which has an assigned profile), you need to generate corresponding client certificate using the aforementioned commands. To publish a message, thing should send following request:
HTTPS#
curl -s -S -i --cacert docker/ssl/certs/ca.crt --cert docker/ssl/certs/<thing_cert_name>.crt --key docker/ssl/certs/<thing_cert_key>.key -X POST -H "Content-Type: application/senml+json" https://localhost/http/messages -d '[{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]'
MQTTS#
Publish#
mosquitto_pub -u <thing_id> -P <thing_key> -t /messages -h localhost -p 8883 --cafile docker/ssl/certs/ca.crt --cert docker/ssl/certs/<thing_cert_name>.crt --key docker/ssl/certs/<thing_cert_key>.key -m '[{"bn":"some-base-name:","bt":1.276020076001e+09, "bu":"A","bver":5, "n":"voltage","u":"V","v":120.1}, {"n":"current","t":-5,"v":1.2}, {"n":"current","t":-4,"v":1.3}]'
Subscribe#
mosquitto_sub -u <thing_id> -P <thing_key> --cafile docker/ssl/certs/ca.crt --cert docker/ssl/certs/<thing_cert_name>.crt --key docker/ssl/certs/<thing_cert_key>.key -t /messages -h localhost -p 8883