Coding an HTTPS request with authentication

I've picked this up as a starting point for getting digest auth working in a new Venstar thermostat integration I'm doing right now, so thanks for that!

Just something I noticed right away, the opaque is not required in a server response, so you need to guard for not getting it and trying to send it back (null exception will be thrown).

I've embellished on your code a little as well to support other hashes. It's possible for the server to return multiple www-authenticate headers, each with a different supported algorithm, and the client is expected to choose. MD5 has fallen from grace.

Poking along, I'm new to groovy and HE (but not Java and others) so half of my time is spent figuring out how to do basic things the "right" way. Do you happen to know if there's any persistent/static storage for a driver outside of the state structure and the device attributes? The www-authenticate information can be stored so subsequent requests can use them to build auth headers up front, but I'm not sure where to keep it (state gets displayed in the UI, so not great). I think this would help smooth out async calls a lot.

Could use the encrypt() function when storing and the unencrypt() when you need to use it.

1 Like

Sounds good. Please feel free to create a pull request on the repo with any suggested changes - all contributions are very welcome!

That is interesting - at the moment I am coding for the specific API servers which (touch wood) have so far responded with the opaque info but I will bear this in mind. I have noticed that even within the same API ecosystem the www-auth response varies in composition.

I attempt to do something similar with the latest version of the code (will commit the latest shortly but is still WIP so bear that in mind). The particular service that I have to use always returns a 401 when talking to the first [director] server so the response needs to be constructed afresh each time. The latest code moves onto the next server (that I call the ASN server) where 200 codes are returned and there is merit in constructing an auth header from stored values. Have a look and let me know what you think.

I can appreciate your point regarding the state variable being visible but from my perspective this is an acceptable security risk. You could always use @thebearmay idea of encryption or explore using th new concept of hub variables brought in with 2.2.8

P.S. if you are creating a driver then you might want to take a look at some of the earlier examples posted by @tomw. I do plan on creating a driver as well once I have the app working but it is slow going for me! :slight_smile:

2 Likes

Actually it caught me a bit off guard, too. The "server" in my case is a Venstar thermostat, so I'm not surprised that an embedded webserver is taking as many shortcuts as possible. RFC7617 says that component of the header is a "SHOULD", and darned if I didn't run across one that avails itself of the option that creates. But it's a first out of many.

In general, I agree, but as you know, code like this has a habit of migrating its way into other things (ahem), so if the problem can be solved and the example that persists is strong in this regard, I think it's doing the community a service. If it can be done easily, it should be done, IMO. But also not a hill to die on.

By the way... I note in the example you linked, it returns an empty opaque for its Authorization header. So now two examples!

Random question along similar lines (maybe)... I'm grappling with conversions between charsets that I think I need to do, anyone converted a potentially UTF-16 byte array to UTF-8? I can convert the byte array to a string, is that enough, is there (hopefully) some kind of implicit conversion? It does display the same output in the logs as is displayed in Notepadd++ when I display the same decoded output, with Notepadd++ indicating it is working in UTF-8.

Basically, I can't seem to include the Charset.forName("UTF-8") in a new String constructor call.

EDIT: Solved my issue, using getBytes("UTF-8") on either a byte array or String seems to do the trick.
Thanks for @kahn-hubitat for sharing his work here, which I'd almost forgotten about...

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.