Integrating HiveMQ with Okta
The 1.4.0 release of our HiveMQ Enterprise Security Extension (ESE) adds support for JSON Web Tokens (JWT). This new feature lets you integrate HiveMQ into OAuth 2 / OpenID Connect deployments.
There are many providers of JWT authentication and authorization infrastructure that offer cloud and on premise solutions. We like Okta because it is one of the fastest to setup while still enabling in-depth customization.
Tooling and Requirements
Most of the work in this tutorial can be done with a modern web browser. Here are the additional tools that you will need:
HiveMQ and the Enterprise Security Extension
The MQTT CLI
A command line HTTP client, we use HTTPie
Set up Okta
Okta is a cloud-based identity and access management platform. It supports the OAuth 2/OpenID Connect standards for token-based authentication and authorization in the web. HiveMQ ESE uses these standards, transposes them into the MQTT world, and integrates them into your enterprise MQTT deployment.
Get an Okta Developer Account
First, head over to developer.okta.com and select Create Free Account.
After you enter your account information, accept the terms and conditions and select Get Started.
Now, you should be redirected to the Okta developer console of your newly-created organisation.
Note your organisational URL in the top right corner (directly under the red Upgrade button). This URL is unique to your Okta account and the basis for a lot of the API calls later in this tutorial. The URL should look somewhat like https://dev-123456.okta.com
. Later, this URL is referred to as [OKTA DOMAIN]
.
Set Up an Application in Okta
Next, we set up an application in Okta. The application is the abstraction in the Okta developer console for a service that accepts tokens for authentication and/or authorization.
Switch to the Applications tab and select Add Application. The application creation wizard opens. Here, you can choose the type of application that you want to create. The application types are intrinsically linked to the different OAuth authentication flows that allow the user to generate tokens. The application type also determines the granularity of trust that a user can be granted.
For now, we will use a very simple setup and select the Service category.
Select Next and enter a name for the application. For this tutorial, we enter ESE Service App
. To confirm the configuration, select Done.
Now, you are redirected to the settings page of the newly created application. Here, two pieces of information are important: the Client ID and Client Secret. This information is sensitive for you setup. Copy both items somewhere and keep them safe. In this tutorial, we will refer to them as [OKTA CLIENT ID]
and [OKTA CLIENT SECRET]
.
Configure the Authorization Server
In the next step, we adapt the default authorization server for our purposes.
Select the API > Authorization Servers tab. On this tab, you can see the authorization APIs that are active. Right now, only the default server should be active. To open the settings page of the default authorization server, select the pencil icon.
To customize the default settings, select Edit. We change the Audience field to HiveMQ
. After you press Save, note the Metatdata URI which is equal to [OKTA DOMAIN]/oauth2/default/.well-known/oauth-authorization-server
. You will need this URI later when we configure the ESE realm.
Remain in the default server configuration and switch to the Scopes tab. To create a new scope, select Add Scope. Set the name of the new scope to mqtt
and enable the Set as a default scope setting.
To verify your configuration, go to the Token Preview tab.
Enter the application name into the OAuth/OIDC client field and select Client Credentials
for the Grant type. After you press Preview Token, you should see something like this:
Note that the audience (aud) claim in line 5 is set to HiveMQ
and the scopes (scp) claim in lines 9 - 11 contains the mqtt
scope.
The setup on the Okta side is now complete. We continue with the configuration of our HiveMQ deployment.
Configure and Install HiveMQ ESE
If you have not already done so, now is the time to download and install the following:
HiveMQ (once installed, stop HiveMQ again)
There is no need to set up a SQL database for ESE. We will authenticate with JWTs.
Open the enterprise-security-extension.xml and change the default configuration to:
Similar to how an Okta application is an abstraction for a token accepting service a ESE realm is an abstraction for an external trust-source. The configuration of the JWT realm with name Okta
in lines 7 - 18 must match the parameters from the Okta authorization server and application.
You can always query (with a HTTP GET request) for the endpoints against the Metadata URI and copy-paste them:
The next part of the ESE configuration, lines 21 - 32, is a listener pipeline. A listener pipeline usually corresponds to a single listener in the HiveMQ config. For this tutorial we use the keyword ALL
to tell the ESE that this pipeline should apply to every listener.
An ESE pipeline always consists of two steps, one for authentication and one for authorization. We use the configured Okta realm for the authentication step with the help of a JWT authentication manager. The authorization step utilizes the very permissive allow-all authorization manager, that grants the authenticated MQTT client the full scope of the MQTT broker.
The example configuration already uses one of the more advanced features: the reserved claims validation. The ESE will only accept JWTs as valid that have the aud claim set to HiveMQ
and contain the mqtt
scope. Of course, the basic necessities of a cryptographic signature and token expiry date are also validated.
Now, restart HiveMQ and wait for the HiveMQ log to show an output like this:
This concludes the configuration of HiveMQ and the ESE.
Authenticate Clients with JWTs
Now, it is time to authenticate some MQTT clients. We use the mqtt-cli in shell mode for this:
First, we try to connect without a valid token:
Because the MQTT client did not provide a valid JWT, the connection attempt was not successful.
Now, we use the client_credentials
authentication flow to generate a JWT from Okta. The flow is very simple and only requires a single HTTP POST request against the token endpoint. This request must contain the [OKTA CLIENT ID] and the [OKTA CLIENT SECRET] as HTTP simple auth header and grant_type client_credentials
application/x-www-form-urlencoded in the body.
In the response body, we receive a JSON object that contains the needed access token.
You can inspect the token over at jwt.io and use it to authenticate a MQTT client:
If you look into the ESE access log you will see a failed connection attempt followed by a successful one:
Conclusion and Next Steps
It is very easy to secure access to your MQTT broker with a cloud-based OAuth 2/OpenID Connect solution.
Here are some possible next steps:
Encrypt your MQTT endpoints to secure against token theft
Set up user based JWT generation
Use more JWT features of the ESE such as automatic authentication expiry
Configure Role Based Access Control after authentication