An image of an Arduino device and other Electric components

Protecting Data in a URL

Print Friendly and PDF

Posted: July 1, 2018 | | Categories: Internet of Things (IoT)

A while back, I created a remote garage door opener project using the Particle platform.

The Particle Platform (devices and cloud services) enables developers to write code running on an Arduino-compatible device that can be remotely executed via a cloud service. Connect a Photon and a relay to a garage opener and you have the gist of my project.

One of the cool features of the project's mobile app is that it enables app users to generate a single-use key, deploy it to the garage door opener, then send a URL to someone who requires access to the garage. The feature is something I hacked together and it works pretty well (I've been using it in my house for years). The system only supports one single-use code at a time, but when you need to get someone into your house when you're not around, it works great.

I've been working on an update to the project, and one of the things I wanted to do is protect the homeowner's private information in the URL sent to others. In order to use the Particle platform from an application, you must have the Particle user's Access Token plus the device ID for the Particle Photon attached to the garage door opener. For the single-use code scenario, you also need the single-use code.

For my project, I basically built a web application that has the user's configuration hard-coded in the app's configuration. The mobile app that generates the single-use code merely builds a URL pointing to a hosted web app and passes in the single-use code on the URL. The hosted web app pulls the access token and device ID from it's local config file, and it's all ready to go. The problem with this approach is that it requires the user to modify a web app and host it somewhere in order to deploy the project. Now, there are a few places where you can host a web application for free, but it's still too complicated for many users to configure, setup and deploy the web app. I needed a better way.

I decided to build my own hosted web page to use for the garage opener project, I'd remove the configuration from the web application code and just include the three required configuration settings in the URL generated by my project's mobile app.

As I started thinking through the implementation of this approach, I quickly realized that I didn't want to pass the Access Token, Device ID, and Single-Use code in clear text in the generated URL. Nope, I needed a way to encrypt those values in the URL. Otherwise, anyone snooping traffic could grab those values and hack their way into the garage. Granted it's not a high risk that someone will be snooping your garage door opener traffic, but I'd rather be safe than sorry, and this gave me an interesting computing problem to solve (my favorite).

I'm not a native mobile developer, so the mobile app I'd deliver would be an Apache Cordova, Ionic, or React Native app. I knew there were encryption libraries for JavaScript, and I set about finding the best one to use for my project. I realized through that encrypting the data in an app wasn't safe, a knowledgeable user could tear apart my code and hack the system. The encryption key, and encryption algorithm would be in the code, so that's not even close to being secure. That wouldn't work.

I poked and prodded at several potential solutions, but none panned out. I wanted (needed) this architecture to be both simple and secure, and nothing good came to mind. I started asking a colleague about possible options for encrypting the data using JavaScript and he quickly suggested using a serverless function to encrypt the data.

I tried to quickly discount this approach because I didn't want to pay for compute in the cloud, but then he reminded me that I could use Azure Functions for free (Microsoft offers Azure Functions in a free tier for a ridiculous number of function calls per month [more than I think I'll ever use for this project]).

To prove the validity of this solution, I logged into my personal Azure account, created an Azure App Service Functions instance and got to work. Before long I had it working; it was quick, simple, and a rather elegant solution to my problem. The purpose of this article is to show you how I did it in order to help others who may have this same problem.

For my implementation, I created two services:

  • setSingleUseCode
  • pushButtonWithCode

The setSingleUseCode function:

  1. Gets the Particle Access Token and Device ID in the body of an HTTP request.
  2. Generates a single use code
  3. Calls my project's Particle API to register the single-use code with the selected device (by the Device ID passed to the function)
  4. Once the function knows that the single-use code was successfully registered with the Photon device, it:
    1. Creates a JSON object containing Access Token, Device ID, and Single-use code.
    2. Encrypts the JSON object using my super special, secret encrypting key.
    3. Builds a URL for my hosted web application, appending the encrypted data as a parameter in the URL.
    4. Returns the URL to the calling application.

The calling application copies the URL to the clipboard, enabling the user to open and email or SMS message, and paste the URL in the message body.

When the receiving user invokes the URL, my hosted web application opens, then:

  1. Validates the format of the URL (that the encrypted data is there).
  2. Displays a button the user clicks/taps to open the garage door.
  3. When the user clicks/taps the button, the application invokes the pushButtonWithCode Azure function, passing it the encrypted data from the URL.

The pushButtonWithCode function:

  • Decrypts the data from the request
  • Uses the decrypted Access Token, Device ID, and single-use code to call the Particle Cloud and invoke a function on the selected Particle Photon device.

That's it, a very simple and elegant solution to my problem. Implementation-wise, it's a couple of hundred lines of JavaScript code (most of it shared across the two functions). Performance is great, and my only cost is a few cents a month to pay for the Azure storage used to store information about my functions.

I'm still working through what I want to do with this thing. My ultimate goal is to make this whole project public and share the code. I'll let you know when that happens.


Next Post: Apache Cordova 3 Programming Site Retired

Previous Post: Particle Photon and the National Control Devices Relay Board

If this content helps you in some way, please consider buying me a coffee.

Header image: Photo by Robin Glauser on Unsplash.