User-Specific Device Authorisation with AWS IoT

Amazon Web Services Internet of Things (AWS IoT) is a platform that simplifies building IoT applications by providing infrastructure and APIs to support common use cases and needs for IoT applications, including, but not limited to: multi-platform SDKs, a message broker, a device gateway, authentication/authorisation and a device registry. An almost universal requirement for IoT-based apps is representing users and their connection to IoT devices, including the access they have to interact with devices; AWS IoT provides this, eliminating the need for a lot of boilerplate code to enable this functionality in your app. Given that a lot of our projects involve IoT use cases, we decided to give AWS IoT a try to attempt to reap the apparent productivity and standardisation/consistency gains.

 

Limitations of Multi-User Access Management

Out of the box, AWS IoT makes it easy to represent users and their relationship to devices, but the permission model is binary (i.e. a user does or does not have access to all devices), which for our problem context, we had to overcome. Say you have a scenario where you are living in a house with 2 of your friends and you want to make your lights controllable remotely. The requirement is that all 3 of you will need to have access to all the common areas (i.e. living room and kitchen), but not to each other’s bedrooms. You want to be the only person to have access to your own bedroom, and so do your friends. This is not possible to achieve using only AWS IoT gives you.

 

Overcoming the Limitation

While this limitation does make it difficult for AWS IoT to satisfy our hypothetical scenario, with a relatively basic workaround you can both satisfy your use case and leverage the productivity that AWS IoT provides. The approach is to build a web service that sits in between your app and the IoT stack and handles the nuance of your domain’s authorisation requirements (see Figure 1,1). Thankfully, there are SDKs and examples available for a number of popular languages.

Figure 1.1 Application Architecture Design

There are a couple of things that you’ll need to set up to use this workaround. First, you’ll need to create an Amazon IAM account that you will use with your selected SDK on your web service application. Here is a recommended account configuration:

Component Value
Access type Programmatic access
Permission Attach existing policies directly, choose:
– AWSIoTFullAccess

At the end of the wizard, make sure you keep a copy of your access key id and secret access key. You will need it to grant access to your web service to manage your smart devices.

From there, you can start working on your web service application. Figure 1.2 shows an example of a data structure to help you manage your devices from your server. These tables are the minimum information that you will need to fully support it.

Figure 1.2 Example data structure to support multiple user access

Here are the table descriptions:

  1. User:
    • Contains information to identify a user, including user’s authentication and user’s access level.
  2. Access level:
    • Defines users access to device groups.
  3. Device group:
    • A group of devices. Group can be used to separate devices by room or even location.
  4. Device:
    • Contains information to identify a device.

 

Java SDK Example

Below is an example of how to turn on your bedroom light remotely. You need to start with configuring the SDK with the IAM account details that you have created. Once this is done, you can populate your request to update your device shadow. In this case, you can pass ‘true’ value to turn it on. Finally, you can send the request to update device shadow. Upon receipt of the request, AWS IoT will notify your device of the change.

BasicAWSCredentials creds = new BasicAWSCredentials(
    accessKey, secretKey)
    AWSIotData iotData = AWSIotDataClientBuilder.standard()
    .withRegion(Regions.AP_SOUTHEAST_2.getName())
    .withCredentials(new AWSStaticCredentialsProvider(creds))
    .build();

Device device = getDeviceById(1);
String iotName = device.getIotName();

ShadowRequest shadowRequest = new ShadowRequest(true);

try {
    ByteBuffer payloadBuffer = shadowRequest.toByteBuffer();
    UpdateThingShadowResult result = iotData
    .updateThingShadow(new UpdateThingShadowRequest()
    .withThingName(iotName)
    .withPayload(payloadBuffer));
} catch (Exception e) {
    e.printStackTrace();
}

With your web service application set up, you can now redirect your front end applications to talk to your web service, instead of talking directly to AWS IoT, and you now have the ability to restrict access of multiple users to particular devices from the same account. An added benefit to this approach is that you can also have greater control over things like your authentication protocol (e.g. use JWT for your public-facing authentication), rather than using only what AWS IoT offers.

 

Header image courtesy of Joshua Sortino.