Anyone Integrated With ST/Webcore?

Has anyone been successful in making this happen using the BETA API?

It will certainly be easier with the Device actions and state exposed in v2.6.21-beta!

@smckdwn989 Unfortunately, it is not currently possible to integrate Webcore with the Bond API. This is due to limitations on the Webcore side with regards to HTTP headers. The Bond API itself is straightforward enough to put into Webcore pistons. The problem is the authentication method. The Bond API uses a custom header with a token to authenticate. As of now, there is no way to set custom headers within Webcore, so there just isn’t a way to authenticate. I spent quite a bit of time troubleshooting this, and worked with some people on the Webcore forums, but it just isn’t going to happen at the moment. I was able to get everything working using a really ugly method. I put up a small nginx instance in a docker container that takes requests from Webcore and then fires off the appropriate curl command to the Bond. It works, but is at least 73% evil.

Would it be helpful if there were an option to disable the token authentication on the local API?

@merck heh, I am almost afraid to say yes :slight_smile: I mean, I would love to integrate with Webcore, it is the original reason I signed up for the beta. But, I also am not thrilled with having no authentication at all. If there were a way to allow the API to work with no token, but restrict it by IP address, perhaps?

1 Like

@merck How about this: accept the token as a standard get or put request with no headers to a specific endpoint, and that authenticates the sending IP for a period of time, such as 5 minutes? The process would be:

curl -i http://IP ADDRESS/v2/authput/TOKEN -X PUT -d {}

(The API then responds with either SUCCESS or FAILURE with a timestamp that indicates how long the sender has received authentication)

Now issue the normal API calls, again with no headers, and the Bond will accept them until the timer expires. It is useful to have that timestamp so the calling entity knows when it would need to re-authenticate.

Another option would be that instead of blindly accepting any requests from that IP, you could use the PUT request like I suggested above and instead of returning SUCCESS and a timestamp, you also return a URL-based token to use that will work for a period of time. The API calls then require that token as part of the URL. You would have to create a dynamic API end-point with this option, but it is more flexible. As in:
curl -i http://IP ADDRESS/v2/authput/TOKEN -X PUT -d {}
return SUCCESS a timestamp and a SESSION-TOKEN

Until timestamp expires, the Bond will now accept API calls at:
http://IP ADDRESS/v2/SESSION-TOKEN/devices/id/etc/etc

In theory, you could use the second method and allow that to work from any local IP address. That would be more flexible and no less secure.

shudder haha.
Interesting thoughts, @j4nd3rs0n. Could see it being useful for some folks if they don’t want to set up their own REST-style listener on a RPi or something.

Me personally? The header method works for me and is relatively straightforward. My vote would be to keep that, and any newfangled method(s) are additional option vs a replacement.

@residualimages I would not suggest replacing the current method with one of my suggestions, certainly out-of-bounds to pull that rug out from under everyone already moving down the road with integrations. But, there a lot of things out there that don’t have an easy code-path to supply custom headers. Having a second method that does not require headers would open up additional integration options. There are many existing items that use one of the methods I suggested to handle auth. For example, Synology uses the second method I described for their API.

Yep, I get what you’re saying. I can see the value, like I said, but I also think it is a little bit of an inconvenient method which is dictated by the constraints of Webcore.

It’s sort of like how I have a local IP-based method for controlling TP-Link Kasa bulbs, but the resulting URLs cannot be very elegantly handled by my ISY controller, so I have my ISY controller call my local RPi via some REST-like URLs, and then the RPi forms the URL in Python and then calls it.
Inconvenient method, but dictated by constraints of my system.

In any case, if the Bond API evolves in such a way that I need to redo my integrations, I’m willing. That’s the risk I gladly take with the ol’ Beta tag hanging around. Even still, I like the header auth token method, so I hope it would stay.

Thanks for the input on the IP-based authentication. That could be a possible way to go, and maintains the level of security provided by the HTTP token, but does seem a bit more complex on the integrator’s side.


I would propose doing two things:

(A) allow the token to be provided inside the request body (_token), as an alternative to the header. We have been using the pattern of underscore-prefixed keys for meta data, so this seems natural.

(B) To both simplify some integrations (where acquiring the token may be awkward), and to provide improved security for users who are not using the local API, we can add an option in the app with three choices:

Local API Security Level

  1. no token required
    (token still required on Bond Config network)

  2. require token [default]

  3. disabled
    (internet connection required for using Bond Home app)


If there is a lot of interest, we could add TLS and certificate validation to the Local API, but this would come at the cost of higher control latency and much more complex to implement for the integrator.

Similarly, it would be possible to create an IP address “whitelist”, but if the above proposal works, I’d prefer to keep things as simple as possible.


Thoughts?

I like option (A): request body token -or- header.

Not sure I like token-less option personally but I suppose it’s nice to give users / integrators the option.

I might also say default would be disabled API Access; when setting up initially user is prompted. Later, a toggle on could enable it for devices already set up.

In either case (initial setup or subsequent enabling), it could be said on screen that there is going to be reboot and the token would need to be saved within 10 minutes - if you wanted to be really kind and it is feasible, the app then could initiate Bond device reboot, listen for reconnection, and show the token on screen in a copy-able format once (until the ‘Next’ / ‘Continue’ button is pressed).

This would allow the folks who want integrations but who rely on the work of others in their respective systems to get their feet wet being guided all the while.

Meantime, low level integrators are not prohibited from using that or just cURLing in to get the token themselves.

To clarify, the Bond Home app actually uses the same Local API to support “offline control”, which many users seem to enjoy, that’s why we want to keep the API enabled by default.

That does work right now, but is actually unintended. We should really base the availability of the token on time since power applied rather than since the last reboot.

Ah, brilliant. Makes sense.

is that discretely discernable? You can tell if a power up was from a software initiated reboot vs a physical power up? And would we need to, in the future, physically power off / on (rather than software reboot) to get the token (if you did the ‘we should’ change)?

On ZZ units and Smart by Bond, yes!

I’m actually not sure about Snowbird units though. We’d need an area of volatile memory which is not erased on reboot. They may just need to keep the current behavior.

1 Like

@merck when you say provide the token inside the request body, can you be more specific? Can you provide an example of what a curl call would look like in this scenario? thx

The example listed in the API docs to get devices:

curl -H "BOND-Token: f074b61f628018fd" -i http://192.100.0.61/v2/devices

The proposed alternate version:

curl -i http://192.100.0.61/v2/devices -d '{"_token":"f074b61f628018fd"}'

The important difference being the lack of the custom BOND-Token header.

1 Like

@jacob that works for me. Thanks!

2 Likes

Hi @j4nd3rs0n, we’ve implemented the embedded _token in request body as an alternative method for authentication. It will be available in the next firmware release (days away).

3 Likes

Awesome! I will try it out as soon as the firmware is available.

@merck any update on the next firmware release? Thanks.