Skip to content
Stand with Ukraine flag

X.509 certificate authentication

X.509 Certificate Chain Authentication is a widely used method for securing MQTT connections in enterprise environments and IoT deployments requiring strong identity verification. Instead of relying on a username and password, clients present a client certificate during the TLS handshake, allowing the broker to authenticate them based on the Common Name (CN) certificate attribute.

With X.509 Certificate Chain Authentication, the client presents its certificate chain as part of the TLS handshake. TBMQ extracts the Common Name (CN) from the client’s certificate, or any certificate in the chain, to generate a credentialsId and match it against the configured MQTT client credentials.

TBMQ supports two matching modes:

  • Exact match — the CN in the certificate must exactly match the configured pattern.
  • Regular expression (regex) match — the CN must match a regex pattern, allowing flexible matching for groups of certificates.

After a successful match, the client is authenticated. For performance and low-latency lookups, TBMQ caches credentials in Redis, while PostgreSQL ensures persistent storage. The following sections explain provider configuration, credential matching, credentialsId generation, and how authorization is applied after successful authentication.

You can check the authentication provider status and enable or disable it directly from the TBMQ user interface, without modifying configuration files or restarting the broker.

  • On the Home page, in the Broker Settings card, you’ll find quick-toggle buttons for each available authentication provider. Click the button next to the desired provider to enable or disable it.
  • On the Authentication Providers page, you have more control and visibility:
    • You can enable or disable a provider directly from the table by clicking the Switch button in the corresponding row.
    • For more detailed management, click on a provider to open its details page, where you can change the status or other parameters.

The Skip certificate validity check for client certificates parameter controls whether the broker verifies the validity period of the client’s certificate during authentication.

  • When enabled, TBMQ skips the validation of the Not Before and Not After dates in the certificate, meaning expired or not-yet-valid certificates will still be accepted.
  • When disabled, the broker enforces standard validity checks, and authentication will fail if the certificate is expired or not yet valid.

The Client authentication setting controls whether the broker asks for — or insists on — a certificate from the client during the TLS handshake:

  • Requested (default) — the broker requests a client certificate, but the TLS handshake still completes if the client does not present one. Suitable when X.509 is one of several enabled providers.
  • Required — the client must present a certificate; otherwise the TLS handshake is aborted. This enforces true mutual (two-way) TLS.

The X.509 Certificate Chain credentials have a “Use certificate CN regex” option that controls how credentials are matched.

  • When “Use certificate CN regex” is disabled: the “Certificate common name (CN)” must exactly match the CN of the client’s certificate or, if present, one of the parent’s certificates in the chain. Authentication will fail if none of the certificates have an exactly matching CN.

  • When “Use certificate CN regex” is enabled: the “Certificate common name (CN) matcher regex” must match the CN of the client’s certificate or, if present, one of the parent’s certificates in the chain. Authentication will fail if no certificate in the chain matches the regex.

A credential can also restrict which MQTT client IDs may use it. Set Client ID to the exact client ID, or enter a regular expression and turn on Use client ID regex (the field is then labelled Client ID regex). Unlike the CN regex, which only has to occur somewhere in the CN, the client ID regex must match the whole client ID: sensor-.* accepts sensor-01 but not my-sensor-01. Leave the field empty to accept any client ID.

The client ID is checked after the CN. If a credential matches the certificate’s CN but not the client ID, TBMQ tries the other credentials for the same certificate — those with Use certificate CN regex enabled first, then the exact-CN one. If none of them allows the client ID, X.509 authentication fails and TBMQ moves on to the next provider in the execution order. TBMQ does not fall back to the credentials of a parent certificate in the chain, so a client cannot pick up the issuing CA’s credentials by sending a different client ID.

Each credential is still identified by its CN pattern (see Credentials ID), so two credentials cannot share a CN and differ only in their client ID. To give each client on a shared certificate its own topics, use the ${clientId} placeholder in the authorization rules instead.

A shared certificate also means a shared private key: whoever holds it can connect with any client ID the credential allows. The constraint narrows which client IDs are accepted; it does not give each device its own cryptographic identity.

The credentialsId is generated as follows:

  • ssl|$CERTIFICATE_COMMON_NAME — for exact CN matching.
  • ssl|$CERTIFICATE_COMMON_NAME_REGEX — for regex-based CN matching.

Where $CERTIFICATE_COMMON_NAME is the common name of the certificate from the chain, and $CERTIFICATE_COMMON_NAME_REGEX is a regex-based string that should be matched with the certificate’s CN from the chain.

After the client is authenticated, it is possible to restrict its access to topics it can publish or subscribe to. To provide flexible control over authorization rules, TBMQ uses regular expressions.

For example, to allow clients to publish or subscribe to all topics that begin with city/, an authorization rule should be created with the value city/.*.

For the X.509 Certificate Chain type, authorization is configured using the authRulesMapping field of the corresponding MQTT client credentials:

{
"certCnPattern": "$certCnPattern",
"certCnIsRegex": "$certCnIsRegex",
"clientIdPattern": "$clientIdPattern",
"clientIdIsRegex": "$clientIdIsRegex",
"authRulesMapping": {
"example_1": {
"pubAuthRulePatterns": ["example_pub_topic/.*"],
"subAuthRulePatterns": ["example_sub_topic/.*"]
},
"example_2": {
"pubAuthRulePatterns": [".*"],
"subAuthRulePatterns": [".*"]
}
}
}

Where:

  • certCnPattern — the pattern for the common name that should be present in the certificate chain.
  • certCnIsRegex — option to control whether the CN pattern is treated as a regular expression for matching.
  • clientIdPattern — optional client ID constraint. Omit it to accept any client ID.
  • clientIdIsRegex — option to treat clientIdPattern as a regular expression that must match the whole client ID.
  • authRulesMapping — the mapping used to configure the access restrictions for different keywords.

This allows clients to connect with a certificate containing example_1 in its CN to publish only to topics that start with example_pub_topic/ and subscribe to topics that start with example_sub_topic/. Clients with a certificate containing example_2 are allowed to publish and subscribe to any topic.

The pubAuthRulePatterns and subAuthRulePatterns may also include the ${cn} placeholder, which TBMQ substitutes at connection time with the client certificate’s Common Name — enabling per-device rules such as ${cn}/data/.*.

Patterns may also include the ${clientId} placeholder, which TBMQ replaces with the MQTT client ID of the connection — for example, devices/${clientId}/telemetry. Both placeholders are inserted as literal text, so regex characters in the CN or client ID, such as ., match only themselves. If a rule uses ${clientId} and the client ID contains +, # or /, X.509 authentication fails for that client (TBMQ then tries the next provider in the execution order), so a client cannot widen its own rules with a crafted ID. Rules without ${clientId} do not restrict the client ID.

X.509 certificates are used to set up mutual (two-way) authentication for MQTT over TLS. Set Client authentication to Required (see above) if the broker should reject connections that do not present a client certificate. There are two strategies that can be used for establishing a connection between the client and TBMQ:

  • X.509 Certificate chain — configure TBMQ to trust all client certificates from a specific trust anchor (intermediate certificate). This feature eliminates the need for manual certificate updates on each MQTT client credential when certificate rotation occurs.
  • X.509 Certificate — configure TBMQ to accept connections from specific devices using pre-configured client certificates.
  1. Prepare your server and client certificate chain

    Follow the MQTT over SSL guide to provision a server certificate for your TBMQ instance.

    Once provisioned, prepare a CA root certificate in PEM format. This certificate will be used by MQTT clients to validate the server certificate. Save the CA root certificate to your working directory as ca.pem.

  2. Generate client certificate chain

    This example creates a certificate chain with reasonable Common Names (CNs). The intermediate certificate signs certificates for the devices. For example, the certificate chain CNs might be:

    • Root certificate CN: company-name.com
    • Intermediate certificate: device-group-name.company-name.com
    • Device certificate: device-name.device-group-name.company-name.com

    Step 2.1: Generate root certificate

    Terminal window
    openssl req -x509 -newkey rsa:4096 -keyout rootKey.pem -out rootCert.pem -sha256 -days 365 -nodes

    When prompted for the Common Name, enter something like company.com.

    Step 2.2: Generate intermediate certificate

    Terminal window
    openssl req -new -newkey rsa:4096 -keyout intermediateKey.pem -out intermediate.csr -sha256 -nodes

    When prompted for the Common Name, enter something like group.company.com.

    Then sign the intermediate certificate with the root CA:

    Terminal window
    openssl x509 -req -in intermediate.csr -out intermediateCert.pem \
    -CA rootCert.pem -CAkey rootKey.pem -days 365 -sha256 -CAcreateserial \
    -extfile <(echo "basicConstraints=CA:TRUE,pathlen:0")

    Step 2.3: Generate device certificate

    Terminal window
    openssl req -new -newkey rsa:4096 -keyout deviceKey.pem -out device.csr -sha256 -nodes

    When prompted for the Common Name, enter something like device123.group.company.com.

    Then sign the device certificate with the intermediate CA:

    Terminal window
    openssl x509 -req -in device.csr -out deviceCert.pem \
    -CA intermediateCert.pem -CAkey intermediateKey.pem -days 365 -sha256 -CAcreateserial

    Finally, concatenate the certificates into a chain starting from the device certificate to the root:

    Terminal window
    cat deviceCert.pem intermediateCert.pem rootCert.pem > chain.pem

    The next steps use the device key file deviceKey.pem and the certificate chain chain.pem.

  3. Provision intermediate public key in MQTT client credentials

    Go to TBMQ Web UI → Authentication → Credentials → Create new or update existing one. Select X.509 Certificate Chain type and insert the CN of intermediateCert.pem.

  4. Trust the certificate

    For the MQTT client to establish a secure TLS connection, the CA (Certificate Authority) that signed its certificate must be trusted. If both TBMQ and the clients use certificates issued by the same CA, no additional configuration is required. If it is another private or internal CA, you must add the CA certificate (rootCert.pem) to the Java truststore used by TBMQ.

    Run the following command to import the CA certificate into the truststore.

  5. Test the connection

    Execute the following command to publish to TBMQ using the secure channel:

    Terminal window
    mosquitto_pub --cafile ca.pem -d -q 1 -h "YOUR_TBMQ_HOST" -p "8883" \
    -t "sensors/temperature" --key deviceKey.pem --cert chain.pem -m '{"temperature":25}'

    For a self-signed server certificate:

    Terminal window
    mosquitto_pub --insecure --cafile server.pem -d -q 1 -h "YOUR_TBMQ_HOST" -p "8883" \
    -t "sensors/temperature" --key deviceKey.pem --cert chain.pem -m '{"temperature":25}'

    Replace YOUR_TBMQ_HOST with the host of your TBMQ instance.