How To Provide Additional Protection For Agents That Host APIs
In its simplest form, communication between an end-user and their imp-enabled device involves a tablet or smartphone app talking to the device’s agent by way of a REST API that you have designed and implemented in your agent code using the standard HTTP request handler callback and recommended methodology.
This approach provides a number of security benefits. Firstly, the agent’s URL is provided to the mobile app when the end-user first configures their device using BlinkUp™. It is unique, randomly generated and obsolete URLs are never re-used.
Secondly, the operations provided by your API are known only to you and those of your team members who have worked on the mobile app and the agent code. This is security by obscurity.
Finally, all communication between the app and device agents is passed via secure HTTPS with full encryption.
This level of security is sufficient for most applications. However, some developers and manufacturers may demand further levels of security. Although no part of the system explicitly makes the full agent URL public, the URL should not be regarded as secret.
A simple way to guard against this contingency is to add a further shared secret, which can be used to authorize or reject attempts to access your agent’s API even if the request is made to a valid agent URL. This also provides a rudimentary check that the system has been compromised in some way: any agent can notify you if it has received an access attempt it was unable to authorize. In such circumstances, the shared secret can be reset and end-users asked to re-configure their devices using BlinkUp to gain new agent URLs.
Listed below are five methods for achieving this basic shared-secret approach to further securing agent-hosted APIs.
The first of these is the recommended method, but is more complex than the later examples. When a device is configured in the field by an end-user, the mobile app use to perform the configuration generates a new UUID using native mobile OS APIs. This secret is then sent to the agent, which stores it for future use. From this point on, when a command is sent from app to agent, possibly via your server, it is accompanied by an HMAC (Hash-based Message Authentication Code) — the result of applying a standard hash function to the shared UUID.
Upon receipt of an incoming API call, the agent checks that, first, the request contains an HMAC and, second, that it matches the hash generated by hashing the agent’s own copy of the shared secret. If it does match, the request is considered authentic and the command contained in the request can be actioned. The comparison is made using the imp API method crypto.equals().
If the request contains no HMAC or its value does not match the hashed local shared key, the request is rejected.
The second example, like those that follow it, is considered less secure because the secret is included with each message sent to the agent, and is baked into each and every agent based on your source code. The quid pro quo is that it is easier to implement: no code is required to persist the secret across agent restarts, for instance.
The first of these examples provides the least visible technique as the shared secret, an API key, is delivered ‘out of band’ in the HTTP request headers. This is the recommended approach
It is not always possible for the mobile app to modify the HTTP headers included with the request made to the agent API, so the next two methods are intended to provide alternative options for this circumstance. The first of these requires that an extra query parameter be added to the end of every request containing the API key.
The second method (see above) embeds the API key into the URL path itself.
The final example uses Electric Imp’s Rocky framework, implemented as a library that you can freely incorporate into your own agent code. Rocky helps you design powerful REST APIs in agents and includes built-in functions that simplify the process of responding to HTTP requests.
All of these methods apply equally to architectures in which the mobile app doesn’t communicate directly with each agent, but talks to them via your own server infrastructure. Such an approach allows you to integrate app-agent communications into your user account management system and, for instance, preserve product state data — handy if a given end-user is likely to run multiple instances of your app in order to control a one product or a set of products.
All of the following techniques are limited to API calls to agents from servers or mobile apps and are not effective security measures for use by a web browser. Different techniques, such as user account logins and session authentication, should be considered for web-based interfaces. Alternatives such as third-party OAuth authentication are particularly effective if your userbase overlaps with those of services such as Google, Facebook or Twitter.