Jump to content
C4 Forums | Control4

Basic Authentication with C4:NetConnect


zaphod

Recommended Posts

I am trying to adapt a driver to allow it to hit a web server that uses basic authentication.  What I am looking to do is to have Control4 send the equivalent of: http://user:pass@192.168.1.99:7070/sage/SageCommand?context=001d6a4cf481&command=play.  

In the existing driver there is the NetConnect line and then the actual command is sent in a C4:SendToNetwork command that include a string with the URLPacket.  So the URL Packet would look like this: GET sage/SageCommand?context=001d6a4cf481&command=play

How do I adapt the C4:NetConnect call to add a user/pass?  Or is this done in a different manner, such as via the URLPacket?

For example in the line: C4:NetConnect(6001, Properties["Web Server Port"]) is there a way to add additional properties such as username and password.

 

Link to comment
Share on other sites


To reply to my own thread - it looks like you may be able to do this by appending a bunch more stuff in your URLPacket.  For example the following should work (I have done it in a telnet script in Ubuntu, but not in a driver yet):

GET /sage/SageCommand?context=001d6a4cf481&command=pause HTTP/1.1
Host: 192.168.1.99
Authorization: Basic dxNlcJPwYXNz

So to do this you will also need the IP address which comes from the binding and you have to base64 encode the "user:pass" string to come up with the string to pass after Authorization: Basic.

So that raises two other questions - how do I get the Host IP address?  And how do you base64 encode within lua code in the driver?  Is there a function that makes this easy?

Is this the right way to be doing all of this or should I just be using C4:urlGet instead?

Link to comment
Share on other sites

--[[
	Create the Authorization header for http request.
--]]
function auth_header()

	local http_headers = {}

	if gAuthRequired then
		if gAuthType == "BASIC" then
			local http_header_field = gUsername .. ":" .. gPassword
			http_header_field = "Basic " .. C4:Base64Encode(http_header_field)
			Dbg:Trace("HTTP Authentication: " .. http_header_field)
			
			http_headers["Authorization"] = http_header_field
		end
	end

	return http_headers
end

--[[
	Perform URL 'Get" request using authentication if required.
	Returns ticket (number) that identifies response with 'ReceivedAsync' callback function.
--]]
function url_get_request(url)
	local l_url = url
	
	if gAuthRequired and gAuthType == "DIGEST" then
		l_url = string.sub(url, 1, 7) .. gUsername .. ":" .. gPassword .. "@" .. string.sub(url, 8)
	end
	
	return C4:urlGet(l_url, auth_header())
end

--[[
	Perform URL 'Post" request using authentication if required.
	Returns ticket (number) that identifies response with 'ReceivedAsync' callback function.
--]]
function url_post_request(url, data)
	local l_url = url
	
	if gAuthRequired and gAuthType == "DIGEST" then
		l_url = string.sub(url, 1, 7) .. gUsername .. ":" .. gPassword .. "@" .. string.sub(url, 8)
	end
	
	return C4:urlPost(l_url, data, auth_header())
end

--[[
	Build HTTP request URL using global address and HTTP port variables and provided query string.
--]]
function build_http_url(query_string)
	return "http://" .. gAddress .. ":" .. gHttpPort .. "/" .. query_string
end

 

Link to comment
Share on other sites

Thanks Mitch.  Up early?  You posted at like 5:30am!

The driver that I am adapting for SageTV is older and just uses C4:SendToNetwork and C4:NetConnect.  Were these other methods like urlGet and urlPost added later on?  Does it make more sense to use them rather than building a more convoluted string as shown in my second post above and continuing to use C4:SendToNetwork?

 

Link to comment
Share on other sites

Thanks Mitch.  Up early?  You posted at like 5:30am!
The driver that I am adapting for SageTV is older and just uses C4:SendToNetwork and C4:NetConnect.  Were these other methods like urlGet and urlPost added later on?  Does it make more sense to use them rather than building a more convoluted string as shown in my second post above and continuing to use C4:SendToNetwork?
 
Up usual time. Netconnect is more of an open socket not really http. If it's http the code I sent should get you pointed in the right direction

Sent from my Pixel XL using Tapatalk

Link to comment
Share on other sites

I have the driver working for the most part now using the Get command.  But I am having one other issue.  When I restart the Driver by updating the version, as I am doing frequently when I am making changes,  everything works fine.  But if I reboot the controller or if I restart Director then I am having an issue.

Right at the beginning of my Driver's Lua file there is this code:  ip = C4:GetBindingAddress(6001).  The variable ip is not getting populated.  If I enter this statement from the Lua code window then it is fine.  Or when I install or update the driver while Director has been running everythign is fine. Why wouldn't this variable get populated when Director is starting up?  Is it possible that the Binding and/or the network isn't yet initialized?  If so is there some way of waiting until Director has been up for a minute or two before populating the ip variable?

Link to comment
Share on other sites

I have the driver working for the most part now using the Get command.  But I am having one other issue.  When I restart the Driver by updating the version, as I am doing frequently when I am making changes,  everything works fine.  But if I reboot the controller or if I restart Director then I am having an issue.
Right at the beginning of my Driver's Lua file there is this code:  ip = C4:GetBindingAddress(6001).  The variable ip is not getting populated.  If I enter this statement from the Lua code window then it is fine.  Or when I install or update the driver while Director has been running everythign is fine. Why wouldn't this variable get populated when Director is starting up?  Is it possible that the Binding and/or the network isn't yet initialized?  If so is there some way of waiting until Director has been up for a minute or two before populating the ip variable?
Do you have it in your init function?

Sent from my Pixel XL using Tapatalk

Link to comment
Share on other sites

By init function do you mean the OnDriverInit or OnDriverLateInit function?  I don't have either of those functions, so I guess I may need to add them.

Right now the IP address is set at the top of the code where there are some constants set, like a remapping table of commands.

So I am thinking that adding a function for OnDriverLateInit might do the trick.

Link to comment
Share on other sites

I am actually considering changing this from a binding to a property - the reason is that an end user could then change it himself without needing a dealer.  Especially since I am now using URL Gets which aren't really a persistent connection the way that a NetConnect and SendToNetwork worked.

Any main reason to choose betwen a network binding and a Property that can more easily be changed?  I have seen Drivers with both - I think the Hue binding has the IP for the hub as a property.

Link to comment
Share on other sites

Binding is better if your device supports SDDP.

Bindings also can show online status in 2.9.2+ (maybe it's 2.10, I forget), but the driver has to manually manage that itself.  i.e. it can reflect that the device is online, even if using urlGet, and even if it's not actually online all the time (since HTTP is connectionless).  I doubt it's all that useful in the driver you're doing.

Otherwise, property is not a bad choice for drivers that use urlGet/urlPost/etc.

RyanE

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.