Recommended authentication flow

#1

I’m using the Losant REST client for JavaScript. The example in the README shows the following flow to authenticate and send a message:

var api = require('losant-rest');
var mySensor = require('./my-analog-sensor');

var client = api.createClient();

client.auth.authenticateDevice({ credentials: {
  deviceId: 'my-device-id',
  key: 'my-app-access-key',
  secret: 'my-app-access-secret'
}}).then(function (response) {
  client.setOption('accessToken', response.token);
  var appId = response.applicationId;

  var state = { data: { temperature: mySensor.read() } };
  return client.device.sendState({
    deviceId: 'my-device-id',
    applicationId: appId,
    deviceState: state
  });
})
.then(function (response) {
  console.log(response); // { success: true }
})
.catch(function (error) {
  console.error(error);
});

I’ve used the example to connect to Losant, but when it’s time to deploy code to my devices, I want to avoid storing the API secret anywhere on the device. Normally, this would be accomplished by storing only the JWT issued in response to my authentication request; then, I would use the API secret only during device provisioning.

However, it isn’t clear from the documentation how long the authenticated token lasts until it expires. I inspected one, and it doesn’t seem to have an expiration; can I rely on the token to stay valid, or is there another recommended way to avoid storing secrets on devices in the field?

Thanks!
Travis

#2

The tokens do not expire. We do, however, recommend using the access key and secret to generate a token on each session. Typically we define a session to be whenever the device restarts. API tokens and access keys provide the same level of authorization so one is not more secure than the other in terms of being hard-coded on the device.

Access keys are revokable, so they do provide additional protection if one is compromised. API tokens are not currently revokable.

We do plan on providing the ability in the web portal to generate API tokens at the user-level. These tokens would be revokable and provide the functionality that you’re looking for.

Long story short, they do not expire so you can use them as you intend, but we currently recommend using the access key and secret for authorization.

#3

Was about to ask this same question. Thanks.

Regarding the code above, the auth piece always returns 401 for me. I also tried the example in the Auth section on GitHub. Also 401.

var api = require('losant-rest');
var client = api.createClient();

client.auth.authenticateDevice(
  {
    credentials: {
      deviceId: 'my-deviceid',
      key: 'my-key',
      secret: 'my-secret'
    }
  }, function (err, result) {
  if (err) { return console.error(err); }
  console.log(result);
});
#4

Another developer and I both tried your exact code and successfully received tokens. A 401 is “Unauthorized”, which means the key and secret are incorrect, device id is incorrect, or the key does not provide access for that device.

If the device id is valid, you can watch the application log as you attempt to authenticate. It should show an authentication error.

#5

Thanks for the prompt reply!

#6

I used the “copy” button next to the id, key, and secret to copy it, so I don’t think that’s the issue. What URL does the Node package attempt to go to? Where are the application logs?

#7

Found the app log. It just says, “Device not allowed to connect” when I make the attempt.

#8

Is the device type “virtual” or “peripheral”? Those device types are not permitted to directly connect.

#9

It is virtual. In the description, it says, “A common example is to request data from an API and report it as a virtual device’s state.” If I am writing an app that uses the API, isn’t that a virtual device? Should I be using a standalone device instead?

#10

Sorry for the confusion there. Virtual device states can only be set using a workflow. A common way to request data from an API is using a workflow’ http node and a timer. If you’re making the API call yourself on the device, then you’ll want to us the stand-alone type.

#11

I misinterpreted your reply for my previous answer. I thought you were using some other api, not the Losant api. The api referred to in the virtual device description is a third party - something like a weather api. A workflow would periodically request data from the third party api and report it as state on the virtual device.

If a device connects directly to Losant - either using our rest api or mqtt broker, it’ll need to be stand-alone or gateway.

#12

Thanks Brandon. I know this reply is late, but I wanted future generations to know that this resolved my authentication issue.

#13

Awesome. I described an upcoming change to virtual devices here that will eliminate this confusion. We’re going to replace virtual devices with virtual attributes. So in your case you would use a standalone device with all virtual attributes and be able to connect and authenticate as that device normally.