Skip to content

digest auth won't work without content-length #169

Closed
wants to merge 1 commit into from

3 participants

@gregors
gregors commented Oct 7, 2012

OK guys help me out. I'm trying to use http digest auth and I'm running into a bad time.

You guys are much more knowledgeable about this than me so if I'm missing something please let me know. This is my current understanding of how digest works.

  1. You send a request to the server. I would like to place this information here.
  2. Server says, no way. If you want in here's some special nonce super secret stuff you have to mess with.
  3. The client looks at the super secret stuff and makes some special sauce with some authentication header and re-submits it - this time the server looks at it and says yes looks good to me.

The issue I'm having is when the initial request is a POST request. It is not sending the content-length when we send a POST. As we all know sending a POST request without the content-length ends up with a nasty 411, so you don't get your nonce stuff (at least with webrick).

Attempting to to post using digest auth using Curl works fine, but fails using httparty.

I'm assuming that most requests are GET in nature and this hasn't been seen. I did some searching and found this -- #57 looks like it's fixed but I'm definitely getting the 411 and POSTS using digest auth are failing.

So I just manually set body to empty string which seems to set the content length properly and everything works.

So main questions are:
1. how do you guys want to test this? Please give me a pointer. It looks like this has been an issue before but wasn't really tested properly. Should I test the format of the http request itself?
2. Does including a body affect simple GET requests adversely?
3. I would think that POST's and PUT's would automatically make sure they had content-length headers. If so, does the actual problem reside elsewhere?

Comments greatly appreciated.

@jnunemaker
Owner

I'm really not even a fan that digest auth made it in to httparty. Never used it and not really sure how to maintain it, which means I'm not sure how to test it, not sure how it affects GET's and also agree that it seems like they should have content-length headers.

Are you sure that you are using >= 0.9 so that it includes the fixes by someone else?

@gregors
gregors commented Oct 10, 2012

I'm using 0.9.0.

The current code works if you're not using a POST or if the server doesn't care about content-length and isn't returning a 411. Now I believe one should expect a server to return 411 if you're trying to post data without the content-length. The content length lets the server know how much data one is attempting to send - the server can then decide if it wants to tackle such a large job.

If you don't send a content-length. The server can respond with 411 in which case the client can then resubmit the request with the content-length.
So I see the 2 options are
1. if we get a 411 then add a content length
2. Just set the content-length on POST or PUT from the beginning

Perhaps just creating a test which checks for content-length on the header for a POST or PUT is a good enough test? I just haven't figured out where is the best place for such a change needs to go. Maybe adding a check to only add that empty body if the request is a POST or PUT might be less likely to impact things.

Obviously I'm thankful httparty does support digest auth ;)

@jnunemaker
Owner

That would work for me. Just add a test that content length is there for post and/or puts and then make it pass.

@Jokery
Jokery commented Dec 7, 2012

This issue is because some web service(like lighttpd) will check Content-Length headers but missing if http request method is POST

i simplely modify lib/httparty/request.rb

def setup_raw_request
@raw_request = http_method.new(uri.request_uri)
@raw_request.body = body if body
@raw_request.content_length = body ? body.length : 0 # Add this line to setup content-length
@raw_request.initialize_http_header(options[:headers])
@raw_request.basic_auth(username, password) if options[:basic_auth]
setup_digest_auth if options[:digest_auth]
end

And:

def setup_digest_auth
auth_request = http_method.new(uri.request_uri)
auth_request.initialize_http_header(options[:headers])
auth_request.content_length = 0 # Add this line to setup content-length
res = http.request(auth_request)

  if res['www-authenticate'] != nil && res['www-authenticate'].length > 0
    @raw_request.digest_auth(username, password, res)
  end
end
@jnunemaker
Owner

Happy to pull something related to this, I'd just like to see some good tests around it as I'm not great at maintaining things I never use without tests. Please re-open if/when tests are added and we'll continue discussion. Closing for now. Thanks!

@jnunemaker jnunemaker closed this Jan 1, 2013
@gregors
gregors commented Jan 1, 2013

This was actually a problem with the ruby Net::HTTP library, I've submitted a patch so this will work with ruby 2.0. I may come back and offer a fix for older versions when I get the chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.