diff options
author | S. Brent Faulkner <brentf@unwwwired.net> | 2009-02-04 23:38:32 -0500 |
---|---|---|
committer | Ryan Tomayko <rtomayko@gmail.com> | 2009-02-25 09:10:09 -0800 |
commit | a2b8481d7ed33d882fe1850713aa9059f4bfe1fb (patch) | |
tree | 58e411f18fd09fd086e34665063a7741679f0186 | |
parent | 65fe834bca9899d97d43201c294096c2bf3d257a (diff) | |
download | rack-a2b8481d7ed33d882fe1850713aa9059f4bfe1fb.tar.gz |
Make MethodOverride + Auth::Digest play well together
Auth::Digest::Request#method now uses any value in rack.methodoverride.original_method to override the value in REQUEST_METHOD Signed-off-by: Ryan Tomayko <rtomayko@gmail.com>
-rw-r--r-- | lib/rack/auth/digest/request.rb | 2 | ||||
-rw-r--r-- | test/spec_rack_auth_digest.rb | 100 |
2 files changed, 63 insertions, 39 deletions
diff --git a/lib/rack/auth/digest/request.rb b/lib/rack/auth/digest/request.rb index a40f57b7..a8aa3bf9 100644 --- a/lib/rack/auth/digest/request.rb +++ b/lib/rack/auth/digest/request.rb @@ -8,7 +8,7 @@ module Rack class Request < Auth::AbstractRequest def method - @env['REQUEST_METHOD'] + @env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD'] end def digest? diff --git a/test/spec_rack_auth_digest.rb b/test/spec_rack_auth_digest.rb index b5b5afc4..34c7e7b4 100644 --- a/test/spec_rack_auth_digest.rb +++ b/test/spec_rack_auth_digest.rb @@ -14,7 +14,7 @@ context 'Rack::Auth::Digest::MD5' do [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ] end end - + def protected_app app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username| { 'Alice' => 'correct-password' }[username] @@ -23,7 +23,7 @@ context 'Rack::Auth::Digest::MD5' do app.opaque = 'this-should-be-secret' app end - + def protected_app_with_hashed_passwords app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username| username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil @@ -40,17 +40,21 @@ context 'Rack::Auth::Digest::MD5' do '/protected' => protected_app }) end - + + def protected_app_with_method_override + Rack::MethodOverride.new(protected_app) + end + setup do @request = Rack::MockRequest.new(protected_app) end - def request(path, headers = {}, &block) - response = @request.get(path, headers) + def request(method, path, headers = {}, &block) + response = @request.request(method, path, headers) block.call(response) if block return response end - + class MockDigestRequest def initialize(params) @params = params @@ -62,22 +66,25 @@ context 'Rack::Auth::Digest::MD5' do super end def method - 'GET' + @params['method'] end def response(password) Rack::Auth::Digest::MD5.new(nil).send :digest, self, password end end - - def request_with_digest_auth(path, username, password, options = {}, &block) - response = request(path) - + + def request_with_digest_auth(method, path, username, password, options = {}, &block) + request_options = {} + request_options[:input] = options.delete(:input) if options.include? :input + + response = request(method, path, request_options) + return response unless response.status == 401 - + if wait = options.delete(:wait) sleep wait end - + challenge = response['WWW-Authenticate'].split(' ', 2).last params = Rack::Auth::Digest::Params.parse(challenge) @@ -86,12 +93,14 @@ context 'Rack::Auth::Digest::MD5' do params['nc'] = '00000001' params['cnonce'] = 'nonsensenonce' params['uri'] = path - + + params['method'] = method + params.update options - + params['response'] = MockDigestRequest.new(params).response(password) - - request(path, { 'HTTP_AUTHORIZATION' => "Digest #{params}" }, &block) + + request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block) end def assert_digest_auth_challenge(response) @@ -101,7 +110,7 @@ context 'Rack::Auth::Digest::MD5' do response.headers['WWW-Authenticate'].should =~ /^Digest / response.body.should.be.empty end - + def assert_bad_request(response) response.should.be.a.client_error response.status.should.equal 400 @@ -109,44 +118,44 @@ context 'Rack::Auth::Digest::MD5' do end specify 'should challenge when no credentials are specified' do - request '/' do |response| + request 'GET', '/' do |response| assert_digest_auth_challenge response end end - + specify 'should return application output if correct credentials given' do - request_with_digest_auth '/', 'Alice', 'correct-password' do |response| + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end - end + end specify 'should return application output if correct credentials given (hashed passwords)' do @request = Rack::MockRequest.new(protected_app_with_hashed_passwords) - - request_with_digest_auth '/', 'Alice', 'correct-password' do |response| + + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end - end - + end + specify 'should rechallenge if incorrect username given' do - request_with_digest_auth '/', 'Bob', 'correct-password' do |response| + request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response| assert_digest_auth_challenge response end end - + specify 'should rechallenge if incorrect password given' do - request_with_digest_auth '/', 'Alice', 'wrong-password' do |response| + request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response| assert_digest_auth_challenge response end end - + specify 'should rechallenge with stale parameter if nonce is stale' do begin Rack::Auth::Digest::Nonce.time_limit = 1 - - request_with_digest_auth '/', 'Alice', 'correct-password', :wait => 2 do |response| + + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response| assert_digest_auth_challenge response response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/ end @@ -156,40 +165,55 @@ context 'Rack::Auth::Digest::MD5' do end specify 'should return 400 Bad Request if incorrect qop given' do - request_with_digest_auth '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response| + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response| assert_bad_request response end end specify 'should return 400 Bad Request if incorrect uri given' do - request_with_digest_auth '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response| + request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response| assert_bad_request response end end specify 'should return 400 Bad Request if different auth scheme used' do - request '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response| + request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response| assert_bad_request response end end specify 'should not require credentials for unprotected path' do @request = Rack::MockRequest.new(partially_protected_app) - request '/' do |response| + request 'GET', '/' do |response| response.should.be.ok end end specify 'should challenge when no credentials are specified for protected path' do @request = Rack::MockRequest.new(partially_protected_app) - request '/protected' do |response| + request 'GET', '/protected' do |response| assert_digest_auth_challenge response end end specify 'should return application output if correct credentials given for protected path' do @request = Rack::MockRequest.new(partially_protected_app) - request_with_digest_auth '/protected', 'Alice', 'correct-password' do |response| + request_with_digest_auth 'GET', '/protected', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + specify 'should return application output if correct credentials given for POST' do + request_with_digest_auth 'POST', '/', 'Alice', 'correct-password' do |response| + response.status.should.equal 200 + response.body.to_s.should.equal 'Hi Alice' + end + end + + specify 'should return application output if correct credentials given for PUT (using method override of POST)' do + @request = Rack::MockRequest.new(protected_app_with_method_override) + request_with_digest_auth 'POST', '/', 'Alice', 'correct-password', :input => "_method=put" do |response| response.status.should.equal 200 response.body.to_s.should.equal 'Hi Alice' end |