MQTT Client Authentication Options for Your HiveMQ Extension

HiveMQ extensions can use different types of authenticators to authenticate MQTT clients.

Each extension can register an authenticator in the Security Registry. In HiveMQ, an extension that registers an authenticator is called a security extension.

You can use multiple security extensions. When you use more than one security extension, the associated authenticators are called in the same order as their extensions (highest priority first). If an authenticator with a higher priority makes a final decision (such as a successful or failed authentication), authenticators of lower priority extensions are not called. The extension with the next lower priority is only called if the authenticator explicitly delegates the decision to the next extension.

Since version 4.3, HiveMQ only allows MQTT clients to connect if a security extension is present. For testing purposes, HiveMQ includes a hivemq-allow-all-extension that authorizes all MQTT clients to connect to HiveMQ. Before you use HiveMQ in production, you must add an appropriate security extension and remove the hivemq-allow-all-extension. You can download security extensions from the HiveMQ website or develop your own security extension.

The HiveMQ extension system offers two types of authenticators: Simple and Enhanced.

A simple authenticator can only use information from the CONNECT packet of an MQTT client (usually the username and password) and connection information (such as X.509 certificates). Simple authentication works for all MQTT versions but has the following limitations:

  • No challenge/response style authentication.

  • No re-authentication during the same connection.

An enhanced authenticator includes all features of a simple authenticator and can also use AUTH packets (introduced in MQTT 5) to implement enhanced authentication mechanisms:

  • Challenge/response style authentication and

  • Support for re-authentication during the same connection.

An enhanced authenticator is not required to use enhanced authentication mechanisms. Enhanced authenticators can also authenticate MQTT clients that do not support enhanced authentication. For example, MQTT 3 clients.

Simple Authenticator for MQTT Clients

The SimpleAuthenticator interface is used to perform authentication at the moment a CONNECT packet is received from a newly connecting client. For this task, HiveMQ provides SimpleAuthInput and SimpleAuthOutput parameters. Extension input and extension output principles apply. The SimpleAuthOutput parameter can easily be used for asynchronous processing.

The SimpleAuthInput parameter provides the following information:

  • The CONNECT packet from the client (the username and password may be of particular interest)

  • Connection information (the X.509 client certificate may be of particular interest)

  • Client information (the client identifier may be of particular interest)

The SimpleAuthOutput parameter provides three important methods to decide authentication:

  • authenticateSuccessfully() finishes the authentication process for the client and allows it to connect to HiveMQ. A CONNACK packet with reason code SUCCESS is sent to the client. Authenticators of extensions with a lower priority are not called.

  • failAuthentication() finishes the authentication process for the client and disconnects the client. A CONNACK packet with a failure reason code is sent to the client and the connection is closed. Authenticators of extensions with a lower priority are not called.

  • nextExtensionOrDefault() does not decide the authenticity of the client. Authenticators of extensions with a lower priority are called. If no further authenticators are present, the default behavior is applied. The default behaviour is to fail the authentication.

In addition to the authentication decision, a SimpleAuthenticator can also authorize and restrict client actions by modifying the Default Permissions of the client and its Client Settings.

After the SimpleAuthenticator completes, a CONNACK packet is sent to the client. The authenticator can set the reason code, reason string, and user properties of the CONNACK packet. The following failure reason codes and reason strings are possible:

Table 1. CONNACK failure reason codes and reason strings
Action Reason Code Reason String

No authenticator present (no security extension present or all providers returned null)

NOT_AUTHORIZED

Authentication failed, no authenticator registered

nextExtensionOrDefault() + no authenticator present

NOT_AUTHORIZED

Authentication failed

failAuthentication()

NOT_AUTHORIZED

Authentication failed

failAuthentication(ConnackReasonCode)

As specified

Authentication failed

failAuthentication(String)

NOT_AUTHORIZED

As specified

failAuthentication(ConnackReasonCode, String)

As specified

As specified

async(…​) + timeout

NOT_AUTHORIZED

Authentication failed, authenticator timed out

async(…​, ConnackReasonCode) + timeout

As specified

Authentication failed, authenticator timed out

async(…​, String) + timeout

NOT_AUTHORIZED

As specified

async(…​, ConnackReasonCode, String) + timeout

As specified

As specified

Authenticator throws exception (this is not a feature, but a safeguard)

UNSPECIFIED_ERROR

Authentication failed, exception in authenticator

Authenticator did not call any decisive method (this is not a feature, but a safeguard)

NOT_AUTHORIZED

Authentication failed, authenticator did not decide authenticity

The reason string and user properties are only sent to MQTT 5 clients. You can specify all CONNACK reason codes that are defined in the MQTT 5 specification. The MQTT 3 specification defines significantly fewer reason codes. The following table shows the mapping of the CONNACK reason codes between the different MQTT versions:

Table 2. CONNACK reason code mapping
MQTT 5 Reason Code MQTT 3 Reason Code

BAD_USER_NAME_OR_PASSWORD

REFUSED_BAD_USERNAME_OR_PASSWORD

BAD_AUTHENTICATION_METHOD

NOT_AUTHORIZED

REFUSED_NOT_AUTHORIZED

UNSPECIFIED_ERROR

MALFORMED_PACKET

PROTOCOL_ERROR

IMPLEMENTATION_SPECIFIC_ERROR

BANNED

TOPIC_NAME_INVALID

PACKET_TOO_LARGE

QUOTA_EXCEEDED

PAYLOAD_FORMAT_INVALID

RETAIN_NOT_SUPPORTED

QOS_NOT_SUPPORTED

CONNECTION_RATE_EXCEEDED

UNSUPPORTED_PROTOCOL_VERSION

REFUSED_UNACCEPTABLE_PROTOCOL_VERSION

CLIENT_IDENTIFIER_NOT_VALID

REFUSED_IDENTIFIER_REJECTED

SERVER_UNAVAILABLE

REFUSED_SERVER_UNAVAILABLE

SERVER_BUSY

USE_ANOTHER_SERVER

SERVER_MOVED

A SimpleAuthenticator can be provided by an AuthenticatorProvider. The AuthenticatorProvider can be registered via the Security Registry.

A SimpleAuthenticator object can be used to authenticate different clients by returning the same object in the AuthenticatorProvider. Sharing the same object has the following requirements:

  • The implementation does not store the authentication state in the object.

  • The implementation is thread safe.

Enhanced Authenticator for MQTT Clients

Enhanced authentication has two life cycles:

  • Authentication when a client initially connects:

    • onConnect is called when the CONNECT packet is received from the newly connecting client.

    • onAuth is called for each AUTH packet received from the client after you called continueAuthentication in the authenticator.

  • Re-authentication during the client connection:

    • onReAuth is called when an AUTH packet with the reason code REAUTHENTICATE is received from the client.

    • onAuth is called for each AUTH packet received from the client after you called continueAuthentication in the authenticator.

Initial authentication and re-authentication can not interleave.

An EnhancedAuthenticator can behave similarly to a SimpleAuthenticator if the authentication is directly succeeded or failed in the onConnect call.

HiveMQ provides an EnhancedAuthOutput parameter to all methods of the EnhancedAuthenticator. The onConnect method gets an EnhancedAuthConnectInput parameter. The onAuth and onReAuth methods get an EnhancedAuthInput parameter. Extension input and extension output principles apply. The EnhancedAuthOutput parameter can easily be used for asynchronous processing.

The EnhancedAuthConnectInput parameter provides the following information:

  • The CONNECT packet from the client (the username, password, authentication data and authentication method may be of particular interest)

  • Connection information (the X.509 client certificate may be of particular interest)

  • Client information (the client identifier may be of particular interest)

The EnhancedAuthInput parameter provides the following information:

  • The AUTH packet from the client (the authentication data and authentication method may be of particular interest)

  • Connection information (the X.509 client certificate may be of particular interest)

  • Client information (the client identifier may be of particular interest)

The EnhancedAuthOutput parameter provides four important methods to decide authentication:

  • authenticateSuccessfully() finishes the authentication process for the client successfully. Authenticators of extensions with a lower priority are not called.

    • Initial authentication: The client is allowed to connect to HiveMQ. A CONNACK packet with reason code SUCCESS and optionally specified authentication data is sent to the client.

    • Re-authentication: The client is allowed to stay connected to HiveMQ. An AUTH packet with reason code SUCCESS and optionally specified authentication data is sent to the client.

  • failAuthentication() finishes the authentication process for the client and disconnects the client. Authenticators of extensions with a lower priority are not called.

    • Initial authentication: A CONNACK packet with a failure reason code is sent to the client and the connection is closed.

    • Re-authentication: A DISCONNECT packet with a failure reason code is sent to the client and the connection is closed.

  • continueAuthentication() continues the authentication process for the client. HiveMQ sends an AUTH packet with reason code CONTINUE_AUTHENTICATION and optionally specified authentication data to the client. Afterwards HiveMQ awaits another AUTH packet from the client. Authenticators of extensions with a lower priority are not called.

  • nextExtensionOrDefault() does not decide the authenticity of the client. Authenticators of extensions with a lower priority are called. If no further authenticators are present, the default behavior is applied. The default behaviour is to fail the authentication.

continueAuthentication can only be called if the client supports enhanced authentication. MQTT 3.1 and 3.1.1 clients do not support enhanced authentication. MQTT 5 clients only support enhanced authentication if the initial CONNECT packet contains an authentication method.

In addition to the authentication decision, an EnhancedAuthenticator can also authorize and restrict client actions by modifying the Default Permissions of the client and its Client Settings.

After the EnhancedAuthenticator completes, either a CONNACK, AUTH or DISCONNECT packet is sent to the client (depending on the authentication decision). The authenticator can set the user properties of these packets.

When the authentication fails, the CONNACK packet (initial authentication) or DISCONNECT packet (re-authentication) provides a failure reason code and reason string. If the authenticator does not set the reason code and reason string, the default reason codes and default reason strings are used. The following failure reason codes and reason strings are possible:

Table 3. CONNACK or DISCONNECT failure reason codes and reason strings
Action Reason Code Reason String

No authenticator present (no security extension present or all providers returned null)

NOT_AUTHORIZED

Authentication failed, no authenticator registered

Re-authentication failed, no authenticator registered

nextExtensionOrDefault() + no authenticator present

NOT_AUTHORIZED

Authentication failed

Re-authentication failed

failAuthentication()

NOT_AUTHORIZED

Authentication failed

Re-authentication failed

failAuthentication(DisconnectedReasonCode)

As specified

Authentication failed

Re-authentication failed

failAuthentication(String)

NOT_AUTHORIZED

As specified

failAuthentication(DisconnectedReasonCode, String)

As specified

As specified

continueAuthentication(…​) + timeout

NOT_AUTHORIZED

Authentication failed, timeout before the client provided required authentication data

Re-authentication failed, timeout before the client provided required authentication data

continueAuthentication(…​, DisconnectedReasonCode) + timeout

As specified

Authentication failed, timeout before the client provided required authentication data

Re-authentication failed, timeout before the client provided required authentication data

continueAuthentication(…​, String) + timeout

NOT_AUTHORIZED

As specified

continueAuthentication(…​, DisconnectedReasonCode, String) + timeout

As specified

As specified

continueAuthentication(…​) + AUTH packet is too big for client receive maximum

NOT_AUTHORIZED

Authentication failed, could not send AUTH to client

Re-authentication failed, could not send AUTH to client

async(…​) + timeout

NOT_AUTHORIZED

Authentication failed, authenticator timed out

Re-authentication failed, authenticator timed out

async(…​, DisconnectedReasonCode) + timeout

As specified

Authentication failed, authenticator timed out

Re-authentication failed, authenticator timed out

async(…​, String) + timeout

NOT_AUTHORIZED

As specified

async(…​, DisconnectedReasonCode, String) + timeout

As specified

As specified

Authenticator throws exception (this is not a feature, but a safeguard)

UNSPECIFIED_ERROR

Authentication failed, exception in authenticator

Re-authentication failed, exception in authenticator

Authenticator did not call any decisive method (this is not a feature, but a safeguard)

NOT_AUTHORIZED

Authentication failed, authenticator did not decide authenticity

Re-authentication failed, authenticator did not decide authenticity

The reason string and user properties are only sent to MQTT 5 clients. On initial authentication, you can specify all CONNACK reason codes that are defined in the MQTT 5 specification. The MQTT 3 specification defines significantly fewer reason codes. This table shows the mapping of the CONNACK reason codes between the different MQTT versions.

Re-authentication is only possible for MQTT 5 clients. Therefore, you can use all DISCONNECT reason codes that are defined in the MQTT 5 specification.

We recommend that you use reason codes that are suitable for both CONNACK and DISCONNECT packets so you do not have to distinguish between initial authentication and re-authentication.

The following table shows which reason codes can be used for initial authentication (CONNACK reason code) and/or re-authentication (DISCONNECT reason code):

Table 4. Disconnected reason codes
Disconnected Reason Code Initial authentication Re-authentication

UNSPECIFIED_ERROR

MALFORMED_PACKET

PROTOCOL_ERROR

IMPLEMENTATION_SPECIFIC_ERROR

NOT_AUTHORIZED

SERVER_BUSY

BAD_AUTHENTICATION_METHOD

TOPIC_NAME_INVALID

PACKET_TOO_LARGE

QUOTA_EXCEEDED

PAYLOAD_FORMAT_INVALID

RETAIN_NOT_SUPPORTED

USE_ANOTHER_SERVER

SERVER_MOVED

CONNECTION_RATE_EXCEEDED

UNSUPPORTED_PROTOCOL_VERSION

CLIENT_IDENTIFIER_NOT_VALID

BAD_USER_NAME_OR_PASSWORD

SERVER_UNAVAILABLE

BANNED

NORMAL_DISCONNECTION

DISCONNECT_WITH_WILL_MESSAGE

SERVER_SHUTTING_DOWN

KEEP_ALIVE_TIMEOUT

SESSION_TAKEN_OVER

TOPIC_FILTER_INVALID

RECEIVE_MAXIMUM_EXCEEDED

TOPIC_ALIAS_INVALID

MESSAGE_RATE_TOO_HIGH

ADMINISTRATIVE_ACTION

SHARED_SUBSCRIPTION_NOT_SUPPORTED

MAXIMUM_CONNECT_TIME

SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED

WILDCARD_SUBSCRIPTION_NOT_SUPPORTED

An EnhancedAuthenticator can be provided by an EnhancedAuthenticatorProvider. The EnhancedAuthenticatorProvider can be registered via the Security Registry. The provider is only called once per client connection. This enables the EnhancedAuthenticator to store state between the initial authentication and later re-authentications.

An EnhancedAuthenticator object can be used to authenticate different clients by returning the same object in the EnhancedAuthenticatorProvider. Sharing the same object has the following requirements:

  • The implementation does not store the authentication state in the object.

  • The implementation is thread safe.

Client Settings

The output parameters of authenticators provide ModifiableClientSettings for configuring the client specific restrictions.

Client Receive Maximum

For MQTT 5 clients, this setting allows you to override the Receive Maximum that the client provided in the CONNECT packet. For MQTT 3 clients, this setting allows you to set a Receive Maximum.

Example for overwriting the client receive maximum
public class ModifyRestrictionsAuthenticator implements SimpleAuthenticator {
    @Override
    public void onConnect(SimpleAuthInput simpleAuthInput, SimpleAuthOutput simpleAuthOutput) {
        ModifiableClientSettings clientSettings = simpleAuthOutput.getClientSettings();
        clientSettings.setClientReceiveMaximum(10);
    }
}

Overload Protection Throttling Level

This setting enables you to set the overload protection throttling level on a per-client basis. You can disable the overload protection for a client (NONE).

Use the overload protection throttling level NONE with extreme care. This option leaves HiveMQ unprotected against misbehaving clients. This may lead to out of memory errors.

Client Queue Size Maximum

Clients will use per default the globally configured max-queue-size. This may not always the ideal queue size for clients. It is possible to overwrite it in the ModifiableClientSettings like in the following example:

Example for overwriting the client queue size maximum
public class ModifyRestrictionsAuthenticator implements SimpleAuthenticator {
    @Override
    public void onConnect(SimpleAuthInput simpleAuthInput, SimpleAuthOutput simpleAuthOutput) {
        ModifiableClientSettings clientSettings = simpleAuthOutput.getClientSettings();
        clientSettings.setClientQueueSizeMaximum(10);
    }
}