http icon indicating copy to clipboard operation
http copied to clipboard

Feature Request: Support digest authentication (digest_auth, RFC2617)

Open rgaufman opened this issue 7 years ago • 6 comments

New report:

Http.rb does not currently support digest authentication out of the box, e.g. https://www.ietf.org/rfc/rfc2617.txt

It would be a really welcome addition as the current workaround (in comment 4) is pretty clunky.

Original text:

I'm on Ubuntu linux, using Ruby 2.4.2p198 and http 3.0.0

When I try to make a connection to a Dahua camera, I get this:

> HttpClient.basic_auth(user: 'admin', pass: 'admin').get('http://192.168.1.108/cgi-bin/configManager.cgi?action=getConfig&name=General')
=> #<HTTP::Response/1.1 401 Unauthorized {"Www-Authenticate"=>"Digest realm=\"Login to 2L05ABCPAA00246\",qop=\"auth\",nonce=\"671353293\",opaque=\"f1f47336b1c3f6c079c49377096a6ed59f81806c\"", "Connection"=>"close", "Content-Length"=>"0"}>
>
> HttpClient.basic_auth(user: 'admin', pass: 'admin').get('http://admin:[email protected]/cgi-bin/configManager.cgi?action=getConfig&name=General')
=> #<HTTP::Response/1.1 401 Unauthorized {"Www-Authenticate"=>"Digest realm=\"Login to 2L05ABCPAA00246\",qop=\"auth\",nonce=\"2128627133\",opaque=\"f1f47336b1c3f6c079c49377096a6ed59f81806c\"", "Connection"=>"close", "Content-Length"=>"0"}>

However, wget seems to work:

$ wget 'http://admin:[email protected]/cgi-bin/configManager.cgi?action=getConfig&name=General'
--2018-01-12 15:33:14--  http://admin:*password*@192.168.1.108/cgi-bin/configManager.cgi?action=getConfig&name=General
Connecting to 192.168.1.108:80... connected.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Digest realm="Login to 2L05ABCPAA00246",qop="auth",nonce="665254639",opaque="f1f47336b1c3f6c079c49377096a6ed59f81806c"
Connecting to 192.168.1.108:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 207 [text/plain]
Saving to: ‘configManager.cgi?action=getConfig&name=General’

configManager.cgi?action=getConfig&name=General         100%[============================================================================================================================>]     207  --.-KB/s    in 0s

2018-01-12 15:33:14 (14.1 MB/s) - ‘configManager.cgi?action=getConfig&name=General’ saved [207/207]

Any ideas what I'm doing wrong?

rgaufman avatar Jan 12 '18 15:01 rgaufman

Your server requires digest authentication. It's a bit different to Basic Authentication. So in case of wget you can see that it makes two calls, first with basic auth, server responds with 401 and some authentication params, and it retries with digest auth from that point.

So, for now you will need to implement digest auth for yourself.

ixti avatar Jan 15 '18 03:01 ixti

You can either write your own digester, or use net-http-digest_auth:

require "net/http/digest_auth"

url = "http://192.168.1.108/cgi-bin/configManager.cgi?action=getConfig&name=General"
response = HTTP.basic_auth(:user => "admin", :pass => "admin").get(url)

if 401 == response.status.code
  digest = Net::HTTP::DigestAuth.new
  auth = digest.auth_header(response.uri, response["WWW-Authenticate"], "GET")
  response = HTTP["Authorization" => auth].get(url)
end

The above is just a sketch (not sure if it will actually work) :D

ixti avatar Jan 15 '18 04:01 ixti

Ah, thank you for that, got it working with this:

require 'net/http/digest_auth'

username = 'admin'
password = 'admin'
@http = HTTP.basic_auth(user: username, pass: password)
ip = '192.168.1.108'
@url = "http://#{username}:#{password}@#{ip}"
url = @url + '/cgi-bin/configManager.cgi?action=getConfig&name=General'
uri = URI(url)
response = @http.get(url)

if 401 == response.status.code
  digest = Net::HTTP::DigestAuth.new
  auth = digest.auth_header(uri, response['WWW-Authenticate'], 'GET')
  config = @http.auth(auth).get(url)
end

It would be great if the http.rb library supported digest auth though :)

rgaufman avatar Jan 16 '18 11:01 rgaufman

Yeah I have some some plans on providing that support when will have time.

ixti avatar Jan 16 '18 12:01 ixti

Note to future me or the one who will be working on this feature: HTTP::Response needs to be extended to provide request reference (needed to encode body in case of qop=auth-int.

ixti avatar Jan 16 '18 12:01 ixti

Implemented a solution in #583

Silex avatar Jan 09 '20 09:01 Silex