MQTT Security Fundamentals: OAuth 2.0 & MQTT
Welcome to the seventh part of the MQTT Security Fundamentals series. The topic for this post is OAuth 2.0 and MQTT. Learn what OAuth 2.0 is and how it can be used with MQTT. Before you jump into this post, it’s a good idea to read the previous posts on authentication and authorization first.
The scope of this post is to introduce OAuth 2.0 and explain how it can be used with MQTT. In IoT, there are a lot of different use cases that involve OAuth 2.0. This post explains the basic concepts and obstacles, but does not attempt to provide solutions for all possible scenarios. If you have specific questions after reading the post, please start a conversation with us in the comments.
What is OAuth 2.0 ?
OAuth 2.0 is an authorization framework that allows a client to access a resource that is owned by a resource owner without giving unencrypted credentials to the client. For example, a mobile app wants to access your Facebook profile to post status updates. You don’t need to give your Facebook password to the app, instead you log into Facebook and authorize the app to use Facebook on your behalf. You can revoke this authorization anytime by deleting the privilege in the Facebook settings.
How does it work?
To understand OAuth 2.0, you need to understand the different roles that are involved:
A resource server provides resources that need protection and can only be accessed by authorized users. Access is granted when the client shows a valid access token. The token allows access to a specific resource. In the example above, the resource server is the Facebook server.
The resource owner is a human who owns the resource on the resource server. In the example, the resource owner is the person who owns the Facebook account that is stored on the Facebook server.
The client is an application that needs to access a resource on the resource server that belongs to the resource owner. In the example, the client is the mobile app.
The authorization server is a central server that controls the access to all resources. the authorization server can issue tokens to clients and revoke issued tokens. The authorization server and the resource server must trust each other. In the example, this server is the Facebook authorization server.
This simplified OAuth 2.0 flow shows how the different roles interact with each other:
OAuth 2.0 commonly uses JSON Web Tokens (JWT), which are JSON objects with base64 encoding. A JWT token contains header, payload, and signature. The header of each token contains information about the cryptographic algorithms for signature and encryption. The payload of the token holds some basic claims about the token (issuer, issue date, expiration date, audience, scope). You can extend the payload with your own information. Each token is signed by the authorization server so the resource server can validate that the issuer is the trusted authorization server and not somebody else.
OAuth 2.0 uses two different types of JWTs: Access Tokens and Refresh Tokens. An access token is a short-living token that grants access to a certain resource. The expire date is commonly between one hour and one day. A refresh token can not be used to access a resource.The refresh token is needed to get a new access token from the server once the previous one expires. Refresh tokens have longer expiration dates than access tokens.
OAuth 2.0 authorization grant types
The specification describes four different flows that can be used to authorize a client and retrieve an access token from the authorization server. We will explain each flow briefly. Before we dive into the explanation, keep in mind that OAuth 2.0 has been designed for use with HTTP and web applications. Therefore, some flows are very specific to this kind of application architecture. For more detailed information on the different grant types, please see the OAuth 2.0 specification.
The authorization code flow is specifically designed for trusted clients (web application) where the web browser of the user should never see the access token. When a client tries to access a resource, the web browser is redirected to a login window of the authorization server. After the resource owner is successfully authenticated, an authorization code is sent back to the browser. The web browser sends this code to the client, which then requests an access token from the resource server.
The implicit flow is meant for public clients where trust comes only from the interaction of the resource owner with the authorization server. After the resource owner is redirected and successfully logged in, the web browser receives an access token directly from the authorization server. The web browser hands the token to the client. The client can then access the resource.
Resource Owner Credentials
The resource owner credentials flow is used when the resource owner trusts the client application. For example, when you want to log into the Dropbox mobile app that Dropbox created, you can enter your password, because Dropbox knows your password anyway. The resource owner enters their credentials directly into the client application. The client then requests an access token and a refresh token from the authorization server. After the client receives the tokens, it should drop the credentials.
If the client application can access resources, the client credential flow can be used. The specification is very vague on the authentication method and declares it out of scope.The client has to authenticate with username password or any other method and receives an access token as response. The client can use the access token to request the resource from the resource server. In this flow no refresh tokens should be used, because the client can provide the credentials again any time.
OAuth 2.0 and MQTT
The official OAuth web site describes OAuth in the following way:
An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications. The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service. –oauth.net
This quote emphasises that OAuth 2.0 was designed for the HTTP protocol. Additionally, the specification includes this statement:
This specification is designed for use with HTTP. The use of OAuth over any protocol other than HTTP is out of scope. – OAuth 2.0 specification
When you look at the OAuth flows, it is obvious that a constrained IoT device, which acts without human interaction is not covered by the OAuth specification. Three of the four OAuth flows do not make sense without human interaction. The Client Credential Flow is an exception.
The client credential flow, however, requires that the MQTT client holds the credentials. The reason to use OAuth 2.0 for MQTT in the first place is to avoid storing credentials on the client, which is exactly what the Client Credential flow suggests. The key questions is how to authenticate the client towards the authorization server. The answer depends on many different factors (provisioning, capabilities, trustworthiness, and location of the device). Additionally, some devices do have the possibility of human interaction, for example, a mobile app using MQTT. Howerver, there are numerous other scenarios that cannot be covered in this post. We will probably write a post about this topic in the future.
Connect to an MQTT broker with an access token
If the client has successfully acquired an access token, it can send this token to the broker in the CONNECT message using the password field. The username can be a special string for recognizing token usage. The limit of a password in MQTT is 65535 bytes, so the token can’t be longer than that.
When the broker gets the token it can do different types of validations:
- Check the validity of the signature from the token.
- Check the expiration date of the token.
- Check on the authorization server if the token was revoked.
When you use HiveMQ, these validation can be done by a custom plugin during the authentication callback.
Only if all of validations succeed, the client is connected to the broker.
Publish/Subscribe with an access token
The same validations that are used for connecting to the MQTT broker can be used when clients want to publish messages or subscribe to a topic. In MQTT, it is common that a large number of publish and subscribe messages are send. A caching implementation is needed to avoid performance degradation when validating the token each time for every message. Additionally, when publishing or subscribing, the broker needs to authorize the client. This client authorization can be achieved in two different ways:
- The token includes the authorization for the client in the scope claim.
- The broker has a third party source (for example, a database or an LDAP server) to look up the authorizations for the client.
Since the size of the token is limited to only 65535 bytes, a third party is needed when the authorization rules exceed the token size limit.
This was a quick introduction to OAuth 2.0 and how it fits together with MQTT. In this post, we barely scratched the surface of the topic. We probably need another post in the future to delve into the individual parts of OAuth 2.0 and MQTT. If you would be interested in a more detailed post, let us know in the comments!
We hope you enjoyed the seventh part of the MQTT Security Fundamentals. If you want to get notified as soon as we publish the next post, subscribe to our newsletter or RSS feed. If you think that we missed some important information, please tell us in the comments. We are always open to questions and suggestions.