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. You will learn what OAuth 2.0 is and how it can be used with MQTT. Before reading this post it’s recommended to read the posts about authentication and authorization first.
The scope of this post is to introduce OAuth 2.0 and explain how it could be used with MQTT. There are a lot of different use cases in which OAuth 2.0 could play a role in IoT. This post will explain the basic concepts and obstacles, but will not provide solutions for all possible scenarios. If you have specific questions after reading the post, please leave us a comment.
What is OAuth 2.0 ?
OAuth 2.0 is an authorization framework, that allows a third party to access a resource owned by a resource owner without giving unencrypted credentials to the third party. 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 as a result the app is authorized to use Facebook on your behalf. You can also revoke this authorization any time by deleting the privilege in the Facebook settings.
How does it work?
In order to understand OAuth 2.0 we explain the different roles that are involved:
A resource server has resources, which need protection and can only be accessed by authorized users. Access is granted when the client shows a valid access token, which allows the access to the specific resource. In the example above this would be the Facebook server.
The resource owner is a human, who owns the resource on the resource server. In the example this would be the person, who owns the Facebook account, which is stored on the Facebook servers.
The client is an application, which needs to access a resource on the resource server, which belongs to the resource owner. In the example, the client would be the mobile app.
The authorization server is a central server, which controls the access to all resources. It can issue tokens to clients and also revoke issued tokens. The authorization server and the resource server must trust each other. In the example this would be the Facebook authorization server.
In the following a 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 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 hold some basic claims about the token (issuer, issue date, expiration date, audience, scope, ..) and can be extended with own information. Each token will be signed by the authorization server, so the resource server can validate 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 rather short-living token, which 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, but it is needed to get a new access token from the server, when the previous one is expired. Refresh tokens have rather long expiration dates compared to access tokens.
OAuth 2.0 authorization grant types
The specification describes four different flows, which can be used to authorize a client and retrieve an access token from the authorization server. We will explain each of them briefly. Before diving in it has to be noted that OAuth 2.0 has been designed for the usage 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. So when a client tries to access a resource the web browser will be redirected to a login window from the authorization server. After the resource owner was successfully authenticated an authorization code will be send back to the browser. Then the web browser sends the code to the client, which then requests an access token from the resource server.
This flow is meant for public clients, where the trust only comes from the interaction of the resource owner with the authorization server. After the resource owner got redirected and successfully logged in, the web browser will get an access token directly from the authorization server. It will hand over the token to the client, which is able to access the resource.
Resource Owner Credentials
This flow is used when the resource owner has trust into the client application. For example when you want to log into the Dropbox mobile app which is created by Dropbox, you can enter your password, because Dropbox has it anyways. The resource owner enters his credentials directly into the client application and then the client requests an access token and a refresh token from the authorization server. After receiving the tokens the client 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. It 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 as:
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
That already makes cleat that OAuth 2.0 was designed for the HTTP protocol. If somebody is still not convinced, the specification also states that
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
If you look at the just described OAuth flows, it is obvious that a constrained IoT device, which is out in the field without human interaction is a scenario that is not covered by the OAuth specification. At least three of the four OAuth flows do not make sense without human interaction, only the Client Credential Flow is an exception.
But the difficulty with this flow is that the MQTT client must hold the credentials. The reason why using OAuth 2.0 in the first place is that no credentials are on the client, which is exactly what the Client Credential flow suggests. So the key questions is how to authenticate the client towards the authorization server. This depends on a lot of different factors, e.g. provisioning, capabilities, trustworthiness and location of the device. Also some device do have the possibility for human interaction, like a mobile app using MQTT. There are a lot of different scenarios, which can not 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 retrieved an access token, it can send it 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 if the expiration date of the token has already passed
- Check on the authorization server if the token was revoked
When using HiveMQ these validation can be done by using a custom plugin and adding the validations in an authentication callback.
Only when all of the validation succeed, the client is successfully connected to the broker.
Publish/Subscribe with an Access Token
The same validations used when connecting to the MQTT broker can be used when clients want to publish or subscribe. In MQTT often a huge number of publish and subscribe message messages occur constantly, so some kind of caching is needed to avoid performance losses when validating the Token every time a publish or subscribe message happens. Additionally when publishing or subscribing, the broker needs to authorize the client. This can be done in two different ways:
- The token has the authorization for the client included in the scope claim
- The broker has a third party source, for example a database or LDAP to look up the authorizations for the client.
With the limitation of a token to only 65535 bytes, a third party is needed when all the authorization rules don’t fit into that length.
This was a first introduction into OAuth 2.0 and how it fits together with MQTT. In this post we only scratched the surface of the whole topic. So there will be most likely another post in the future we a more focused and in detail view of individual parts of OAuth 2.0 and MQTT. Let us know if you would be interested in that 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, you can subscribe to our newsletter or RSS feed. You think we have missed some important information? Please tell us, we are always open to questions and suggestions.