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 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?
@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
-
no token required
(token still required on Bond Config network) -
require token [default]
-
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.
@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.
@jacob that works for me. Thanks!
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).
Awesome! I will try it out as soon as the firmware is available.
@merck any update on the next firmware release? Thanks.