As Spark.io is evolving quickly, in case this post is found in the future, everything in this post is related to the Spark.io ecosystem as of August 14th 2014.
@zachary thanks for the reply. I failed to recognize that, currently, one access token provides access to every device registered to an account. I was under the, incorrect, impression that access tokens were paired against devices. What this means is that in order to achieve the “box opening experience” I described above while maintaining security, we would need to create a separate spark account for every device we sell. Not impossible, but it seems like a rube-goldberg solution.
I’ve just read through the OAuth 2.0 RFC (6749) and I don’t see why creating a new extension grant type is required. I think within the scope of the “box opening experience” problem, it’s unrelated to the grant type used.
OAuth 2.0 already has the required components to make this system work. The spec says that authorization tokens can carry with them a scope. In this way tokens can carry both the scope of a specific device ID, as well as the scope of whether or not they are allowed to update the given device with new firmware or just make requests against the existing firmware.
[Sidebar: I would also like to see the Spark.io accounts support 2-factor authentication as passwords stink for really important stuff]
Using OAuth 2.0 then, I would suggest the following architecture and control flow for a very simple improved version, which I think should be a lot less work than a new OAuth grant type.
Initial Step:
User (USR) claims spark device ID from Spark (SPK), becomes owner.
Access Generation Step:
USR------> SPK,
Request new access token
where the request includes:
- USR login
- USR password
- USR 2-factor
- device ID: if null, => global scope token requested
- access_level: a simple first proposal is, ENUM {all, noFlash}, where noFlash restricts the user from the “PUT /v1/devices/{DEVICE_ID}” endpoint and allows all others
Response SPK ------> USR provides an access and a refresh token with the requested scope.
Request Step:
All requests to https://api.spark.io/v1/devices/0123456789abcdef01234567 are checked against the token for both device scope and access scope before being granted.
We could then distribute these auth+refresh tokens as printed items with our devices, and our Android app could handle the “token refresh” cycle when needed. How to handle the new auth+refresh tokens after a refresh is the only part of this flow that is still a bit thorny because it would mean the printed tokens we ship with the device are now invalid. I could see prompting users that their tokens have changed and that they need to email/store the new tokens and throw away the old ones. If that is all done on device, (easy on Android using Intents) then they still wouldn’t need to register any PII with us. This accomplishes our goals of 1. not having users register with us, and 2. not requiring us to build and maintain an authentication intermediary web-service. This scheme assumes that we must have tokens expire and we therefore need refresh tokens.
Changing subjects a bit, I see a larger vision (which may be what you are getting at) where the authorization step could be delegated to a third party (e.g. me). This way, I can control and create the authorization logic however I want. This would allow authorization scopes as finely grained as desired and potentially allow me to include things like time-of-day, gps location, and the moon cycle in determining when users can access a given device. A very neat and exciting thought experiment indeed! If this approach was required it would carry the downside of requiring everyone a lot of work (implementing and maintaining the auth server). Something we, in our specific case, would love to avoid.
For this reason, would you consider making a smaller step, something more in the direction of what was suggested above?
The IoT is already a lot of fun, I’m glad to be a part of it. Cheers.