Hello to lovers of the IoT and M2M things. My name is Artyom Sorokin and I’m a software engineer who has gained great experience working and developing IoT projects with the help of DeviceHive!
This is a series of posts where I am going to show you the Authentication and Authorization models which are available in DeviceHive and how to use them. In this tutorial we will get in touch with the basic auth approaches implemented in DH. If you are just looking for a complete list of approaches without examples and the long description, just proceed to the “Summary” section at the bottom of this post.
To go through this tutorial a DeviceHive server with an admin console should be deployed somewhere. Personally, I like to use the playgrounds provided by the devicehive.com web site because they are free to use and you do not need to waste your time with messy deployments.
Credentials
After DeviceHive has been deployed there is always a default admin user created (for custom deployments – dhadmin, password – dhadmin_#911). Open your terminal and type:
$ curl --user adminUsername:adminPassword http://devicehiveApiUrl/user
For my playground the command will look like this:
$ curl --user admin:mysupersecurepassword http://nn1344.pg.devicehive.com/api/user
Right now we have used Basic Authentication to access the DH user list. It is the first auth mechanism available in DeviceHive. This approach is used by an admin console and you can use it for all DH API endpoints. In addition to the administrator role a regular client user can also be created. There are more restrictions for this role and not all of the API resources can be accessed by it.
Hm… But it is not always convenient to access API endpoints directly, there are plenty of DH libraries which wrap DH REST and websockets API, encapsulates transport and authentication logic. Let’s use one of them. Here is an example of using a javascript library with user credentials to access the network list:
var dhClient = new DHClient("http://devicehiveApiUrl/", "adminUsername", "adminPassword");
dhClient.getNetworks(null, function(err, res){
console.log(err ? 'Error' : res);
});
In this example the dhClient.getNetworks method issues a request with a header “Authorization: Basic encodedCredentials” and the user will receive network parameters which are accessible for them.
Access Keys
Although authentication with credentials is an essential feature, it is not very convenient to use and permissions for the users are not quite configurable. To provide a good authorization model, DeviceHive Access Keys can be used. Access Keys are generated by users using the API AccessKey/insert endpoint. Let’s create a key for our admin user. We will use the admin console to finish this up quicker. To do this, follow the steps:
- Go to your admin console and login with an admin credentials (for my playground the URL is – http://playground.devicehive.com)
- Navigate to the Access Keys section and click the “create new access key” button
- Click the “Add new permission” button
You can see now that an Access Key can be configured with an expiration date, authorized domain list, IP subnet list, actions, networks and devices. Let’s use the default permission and save the key.
To provide a more real-world scenario, let’s consider a simple device. Any device should be able to register itself in DeviceHive. To perform registration an application which is running on the Device side should be authorized to some network. As we have already created an access key with default permission and we can use it to authorize our app.
Let’s check some sample code for such a device written in JavaScript:
var dhDevice = new DHDevice("http://devicehiveApiUrl/", "someUniqueDeviceId", "AccessKeyExampleAccessKeyExampleAccessKeyEx=");
dhDevice.registerDevice({
name: "My Temperature Device",
deviceClass: {
name: 'My Device Class',
version: '0.0.1',
equipment: [
{ name: 'Temperature sensor', type: 'sensor', code: '0' },
{ name: 'Fan', type: 'control', code: '1' }
]
}
}, function(err, res) {
console.log(err ? 'failed' : 'success');
});
So here we are trying to initialize the DH library with our new accessKey and to register the device with DeviceHive. Under the hood the DH js library will commit a request to the Device Register endpoint with the header “Authorization: Bearer AccessKeyExampleAccessKeyExampleAccessKeyEx”. The same goes for client requests. Let’s create a simple client which will send some custom command to this device:
var dhClient = new DHClient("http://devicehiveApiUrl/", "AccessKeyExampleAccessKeyExampleAccessKeyEx=");
dhClient.openChannel(function(err) {
if (err) return;
// Send device command with custom parameters to the device with deviceId identifier
var cmd = dhClient.sendCommand("someUniqueDeviceId", 'someCustomCommand');
});
In this scenario we used one access key for both client side and device side. Your application can configure any number of keys for any entities. You can have one key for all devices and a separate key for all clients. Or you can create a system where each device or client has its own access key. This all depends on your needs and your imagination. Also, as the DeviceHive is fully open-source you can even implement your own unique approach by creating a fork of the DH repository.
Websockets Authentication
As you probably know, there are websocket endpoints which can be used to communicate with DeviceHive. The libraries for different platforms encapsulate websocket related logic, but what if you want to use websockets directly? You should consider how to authenticate your entity. It is done by issuing an “authenticate” action (http://devicehive.com/restful#WsReference/Client/authenticate) to the DH server via a websocket after a connection to the “Client” endpoint is established and before any command is issued. You can provide credentials or an access key in the parameters.
How can I understand which Authentication model can be used to access API endpoints?
So how can you understand which authentication mechanism is supported by the API resource and which permissions to configure for an access key? Check the official API documentation – http://devicehive.com/restful. For each API resource, there is a section named “Authorization” where available auth approaches are listed, as well as the name of the action used to configure access key permission.
Let’s check DeviceNotification:insert endpoint. The list of the available auth methods is: User or Device or Key. That is: – Admin – goes for authentication by using admin user credentials – User – authentication by using any user credentials – Key – access keys – Device – deprecated auth method (discussed below).
Also you can see a name of this action – CreateDeviceNotification. Check this action in the Access Key settings if you want to allow inserting device notifications for your applications.
Deprecated Device Authentication Alternative
Another way devices can authenticate themselves is by using Device authentication approach. For HTTP this is achievable by passing two custom HTTP headers:
- Auth-DeviceID: Device unique identifier.
- Auth-DeviceKey: Device authentication key.
Both the device unique identifier and authentication key are specified during device registration.
For the websocket you should use the deprecated Device endpoint and issue the authenticate command.
This auth method is deprecated and will probably be fully replaced with an Access Key approach in future. If you think this method is very useful, create a ticket about it in the DeviceHive Issue Tracker.
Summary
The API supports three types of authentication: User
, Access Key
, and the deprecated Device
method.
User
- The users are authenticated using login and password credentials.
- Access is provided based on authenticated user role (Client or Administrator).
- For HTTP transport the HTTP Basic Authentication is used
- For WebSockets use the “Client” websocket endpoint and send an “authenticate” action with login and password parameters
Access Key
- Access key authentication is useful, when third-party applications, clients, or devices have to access the DeviceHive API. It is possible to limit the rights of a particular access key to specific resources and actions, networks, devices, as well as restrict usage of the key to a range of source domains and/or IP subnets.
- For HTTP – The access key is passed in the Authorization HTTP header using the Bearer scheme as follows: Authorization: Bearer
- For WebSockets – “Client” websocket endpoint, “authenticate” action with accessKey parameter
Device
- Deprecated authentication approach unique for devices.
- For HTTP – pass 2 custom headers with the device unique identifier and authentication key which are specified during device registration: Auth-DeviceID: Device unique identifier. Auth-DeviceKey: Device authentication key.
- For WebSockets – use the “Device” websocket endpoint and provide the id and key in the “authenticate” action
If you find something which could be useful and is not implemented in DeviceHive, you can always create a feature request in the GitHub issue tracker, for any repository in the DeviceHive GitHub organization. In the next post I will show you, how to securely grant access to resources in your DeviceHive instance for any 3rd party applications.