MQTT and the Basics of Authorization

As you probably know, VerneMQ has different options when it comes to Authentication and Authorization. But let's take a step back here, and look into Authorization only (the more complex issue of both). We'll go through a couple of basic questions, and from there we can develop a basic understanding of what Authorization means for MQTT in general.

Self-provisioning vs Access Control

The first thing to understand is that MQTT is a protocol that allows self-provisioning by the clients. This is somewhat similar to self-service provisioning known from DevOps or Cloud providers. MQTT clients have quite some control over the server. For instance, they can decide whether the server should save session state, including full persistence of any sent messages. When a client subscribes to a topic, the server will create a subscription (the details are, of course, implementation-dependent). Most notably, a client can require:

  • Message persistence
  • Subscription persistence
  • Quality of Service (and related state handling)

We can consider this aspect "communication as code". It represents client-side code and server-side software components like a topic tree.

While it seems useful for clients to treat communication in a dynamic and scriptable way, for the server operator things are a little more complicated. The server operator (that's probably YOU, right?) needs to have some control over the access to and creation of server resources and services within the broker. To put that out more drastically, you need to have damage control in place if an authenticated client decides to go amok.

So, to limit client-side configuration, you'll have a server-side configuration.

What does the MQTT specification tell us on Authorization?

Let's have a quick look into the MQTT spec to see what it recommends to server implementors, regarding server-side configuration and Authorization. We'll only look at the MQTT 5.0 spec here.

"If a Client has been successfully authenticated, a Server implementation should
check that it is authorized before accepting its connection.
Authorization may be based on information provided by the Client such as User
Name, the hostname/IP address of the Client, or the outcome of authentication mechanisms.

In particular, the implementation should check that the Client is authorized
to use the Client Identifier as this gives access to the MQTT Session State
(described in section 4.1). This authorization check is to protect against
the case where one Client, accidentally or maliciously, provides a Client
Identifier that is already being used by some other Client.

An implementation should provide access controls that take place after
CONNECT to restrict the Clients ability to publish to particular Topics or to
subscribe using particular Topic Filters. An implementation should consider
limiting access to Topic Filters that have broad scope, such as the # Topic Filter."

That's quite general but interesting!

So, there's a recommendation to do Authorization during CONNECT, and also after CONNECT.

There's also a particular note about checking the ClientID that seems from the Department of Redundancy Departement ("check that the client is authorized to use the ClientID").

It's not. You have to make sure that no client (device) can use or "attack" ClientIDs from others, basically by ensuring authentication for ClientID, Username, Password as a whole. The VerneMQ broker will do this during CONNECT, that is, as a one-time authorization step during connection setup. VerneMQ also caches the publish and subscribe policies for the client session during that setup.

In addition to that, you have to have Continuous Acces Control for PUBLISH and SUBSCRIBE. Every single publish and subscribe action will have to hit Authorization. This gives you a pretty clear idea for what you'll be using the VerneMQ Auth plugin hooks in the VerneMQ Plugin architecture: auth_on_register, auth_on_publish, auth_on_subscribe

What Authorization model should we use?

Based on the information we have so far, it seems that Authorization will mainly protect three things: ClientIDs, Where to publish to, and Where to subscribe to. Alternatively, we can also say that we protect the MQTT CONNECT (register), PUBLISH and SUBSCRIBE commands.

What's less clear at this point is what Authorization model to use. Is this a case for RBAC (role-based access control)? ABAC (attribute-based access control)? Something else completely?

Most of the time, the clients connecting to the MQTT server are devices, not human system users who have roles. On the other hand, some role-based model might be what you are looking for within your use case.

With the DB based approach, VerneMQ gives you some form of policy-based Access Control. This is very close to ABAC, but VerneMQ will attach the (PUBLISH and SUBSCRIBE) policies to a specific ClientID.

With the VerneMQ plugin system, you are not forced to use a single approach. You are free to use a model that suits you best. The spec states, that "authorization may be based on information the client provides" or "the outcome of authentication mechanisms". VerneMQ plugins allow you three additional things:

  • The control of other attributes coming from the Client. An example of that would be limiting the message size allowed for a client.
  • The use of Modifiers, although technically they are not Authorization attributes. An example of this would be a topic re-write.
  • External context, or realtime decisions, by hooking your plugin into external data or policy systems.

Note that the above applies to native plugins (Erlang/Elixir), Lua plugins, and WebHook plugins as well.

I've intentionally kept this blog post to the basics. If you consider yourself a beginner in MQTT, it should allow you to answer the basic questions, and explore further by yourself. If something essential is missing, as always, please do let us know. If you have specific interests in Authorization, let's spark a discussion!

Next time, on the topic of Authorization, we're probably going to be a little bit more advanced and look into full-blown integration with one of the best policy systems out there.