Permalink
Browse files

Search for Oauth2Token that are authorized and not invalidated in the…

… Rack middleware

I was surprised that when using `OAuth::Controllers::ApplicationControllerMethods.oauthenticate`, every token were valid for authentication, even the invalidated ones!

So I think this patch fix this (I've updated the specs). I've also simplified a condition in `OAuth::Rack::OAuthFilter#oauth2_token` and the Guardfile to remove the deprecation notice.
  • Loading branch information...
1 parent 68cb534 commit fa8c375df38ede4bf2fe3711b5eb3ac02be31dc1 Rémy Coutable committed with Jul 14, 2011
Showing with 161 additions and 110 deletions.
  1. +2 −0 .gitignore
  2. +23 −0 Gemfile
  3. +0 −66 Gemfile.lock
  4. +3 −3 Guardfile
  5. +8 −11 lib/oauth/rack/oauth_filter.rb
  6. +125 −30 spec/rack/oauth_filter_spec.rb
View
2 .gitignore
@@ -8,3 +8,5 @@ pkg
.swp
.idea
.rvmrc
+
+Gemfile.lock
View
23 Gemfile
@@ -2,3 +2,26 @@ source "http://rubygems.org"
# Specify your gem's dependencies in oauth-plugin.gemspec
gemspec
+
+require 'rbconfig'
+
+platforms :ruby do
+ if Config::CONFIG['target_os'] =~ /darwin/i
+ gem 'rb-fsevent'
+ gem 'growl'
+ end
+ if Config::CONFIG['target_os'] =~ /linux/i
+ gem 'rb-inotify', '>= 0.5.1'
+ gem 'libnotify', '~> 0.1.3'
+ end
+end
+
+platforms :jruby do
+ if Config::CONFIG['target_os'] =~ /darwin/i
+ gem 'growl'
+ end
+ if Config::CONFIG['target_os'] =~ /linux/i
+ gem 'rb-inotify', '>= 0.5.1'
+ gem 'libnotify', '~> 0.1.3'
+ end
+end
View
66 Gemfile.lock
@@ -1,66 +0,0 @@
-PATH
- remote: .
- specs:
- oauth-plugin (0.4.0.pre7)
- multi_json
- oauth (~> 0.4.4)
- oauth2
- rack
-
-GEM
- remote: http://rubygems.org/
- specs:
- addressable (2.2.6)
- diff-lcs (1.1.2)
- fakeweb (1.3.0)
- faraday (0.7.4)
- addressable (~> 2.2.6)
- multipart-post (~> 1.1.0)
- rack (< 2, >= 1.1.0)
- fuubar (0.0.5)
- rspec (~> 2.0)
- rspec-instafail (~> 0.1.4)
- ruby-progressbar (~> 0.0.10)
- growl (1.0.3)
- guard (0.3.4)
- thor (~> 0.14.6)
- guard-rspec (0.3.1)
- guard (>= 0.2.2)
- multi_json (1.0.3)
- multi_xml (0.2.2)
- multipart-post (1.1.3)
- oauth (0.4.4)
- oauth2 (0.5.0)
- faraday (< 0.8, >= 0.6.1)
- multi_json (~> 1.0.0)
- opentransact (0.1.2)
- multi_json
- multi_xml
- oauth (~> 0.4.4)
- rack (1.3.0)
- rack-test (0.6.0)
- rack (>= 1.0)
- rspec (2.4.0)
- rspec-core (~> 2.4.0)
- rspec-expectations (~> 2.4.0)
- rspec-mocks (~> 2.4.0)
- rspec-core (2.4.0)
- rspec-expectations (2.4.0)
- diff-lcs (~> 1.1.2)
- rspec-instafail (0.1.7)
- rspec-mocks (2.4.0)
- ruby-progressbar (0.0.10)
- thor (0.14.6)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- fakeweb
- fuubar
- growl
- guard-rspec
- oauth-plugin!
- opentransact
- rack-test
- rspec (~> 2.4.0)
View
6 Guardfile
@@ -2,7 +2,7 @@
# More info at http://github.com/guard/guard#readme
guard 'rspec', :version => 2 do
- watch('^spec/(.*)_spec.rb')
- watch('^lib/oauth/(.*)\.rb') { |m| "spec/#{m[1]}_spec.rb" }
- watch('^spec/spec_helper.rb') { "spec" }
+ watch(%r{^spec/(.*)_spec.rb})
+ watch(%r{^lib/oauth/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch('spec/spec_helper.rb') { "spec" }
end
View
19 lib/oauth/rack/oauth_filter.rb
@@ -14,21 +14,18 @@ module Rack
# require 'oauth/rack/oauth_filter'
# config.middleware.use OAuth::Rack::OAuthFilter
-
-
class OAuthFilter
def initialize(app)
@app = app
end
def call(env)
request = ::Rack::Request.new(env)
- env["oauth_plugin"]=true
+ env["oauth_plugin"] = true
strategies = []
if token_string = oauth2_token(request)
- token = Oauth2Token.find_by_token(token_string) if token_string
- if token
- env["oauth.token"] = token
+ if token = Oauth2Token.find(:conditions => ['invalidated_at IS NULL AND authorized_at IS NOT NULL and token = ?', token_string])
+ env["oauth.token"] = token
env["oauth.version"] = 2
strategies << :oauth20_token
strategies << :token
@@ -37,15 +34,15 @@ def call(env)
elsif oauth1_verify(request) do |request_proxy|
client_application = ClientApplication.find_by_key(request_proxy.consumer_key)
env["oauth.client_application_candidate"] = client_application
- # Store this temporarily in client_application object for use in request token generation
- client_application.token_callback_url=request_proxy.oauth_callback if request_proxy.oauth_callback
+ # Store this temporarily in client_application object for use in request token generation
+ client_application.token_callback_url = request_proxy.oauth_callback if request_proxy.oauth_callback
oauth_token = nil
if request_proxy.token
- oauth_token = client_application.tokens.first(:conditions=>{:token => request_proxy.token})
+ oauth_token = client_application.tokens.first(:conditions => { :token => request_proxy.token })
if oauth_token.respond_to?(:provided_oauth_verifier=)
- oauth_token.provided_oauth_verifier=request_proxy.oauth_verifier
+ oauth_token.provided_oauth_verifier = request_proxy.oauth_verifier
end
env["oauth.token_candidate"] = oauth_token
end
@@ -88,7 +85,7 @@ def oauth1_verify(request, options = {}, &block)
def oauth2_token(request)
(request.params["oauth_token"] && !request.params["oauth_signature"] ? request.params["oauth_token"] : nil ) ||
request.env["HTTP_AUTHORIZATION"] &&
- request.env["HTTP_AUTHORIZATION"][/^(OAuth|Token) ([^\s]*)$/] && $2
+ request.env["HTTP_AUTHORIZATION"][/^(OAuth|Token) ([^\s]*)$/, 2]
end
end
end
View
155 spec/rack/oauth_filter_spec.rb
@@ -3,14 +3,15 @@
require 'oauth/rack/oauth_filter'
require 'multi_json'
require 'forwardable'
+
class OAuthEcho
def call(env)
response = {}
- response[:oauth_token] = env["oauth.token"].token if env["oauth.token"]
+ response[:oauth_token] = env["oauth.token"].token if env["oauth.token"]
response[:client_application] = env["oauth.client_application"].key if env["oauth.client_application"]
- response[:oauth_version] = env["oauth.version"] if env["oauth.version"]
- response[:strategies] = env["oauth.strategies"] if env["oauth.strategies"]
- [200 ,{"Accept"=>"application/json"}, [MultiJson.encode(response)] ]
+ response[:oauth_version] = env["oauth.version"] if env["oauth.version"]
+ response[:strategies] = env["oauth.strategies"] if env["oauth.strategies"]
+ [200, { "Accept" => "application/json" }, [MultiJson.encode(response)]]
end
end
@@ -55,32 +56,122 @@ def app
response.should == {"client_application" => "my_consumer", "oauth_token"=>"my_token","oauth_version"=>1, "strategies"=>["oauth10_token","oauth10_request_token"]}
end
- it "should authenticate with oauth2 auth header" do
- get '/',{},{"HTTP_AUTHORIZATION"=>"OAuth my_token"}
- last_response.should be_ok
- response = MultiJson.decode(last_response.body)
- response.should == {"oauth_token" => "my_token", "oauth_version"=>2, "strategies"=>["oauth20_token","token"]}
- end
+ describe "OAuth2" do
+ describe "token given through a HTTP Auth Header" do
+ context "authorized and non-invalidated token" do
+ it "authenticates" do
+ get '/', {}, { "HTTP_AUTHORIZATION" => "OAuth valid_token" }
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
+ end
+ end
+
+ context "non-authorized token" do
+ it "doesn't authenticate" do
+ get '/', {}, { "HTTP_AUTHORIZATION" => "OAuth not_authorized" }
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+
+ context "authorized and invalidated token" do
+ it "doesn't authenticate with an invalidated token" do
+ get '/', {}, { "HTTP_AUTHORIZATION" => "OAuth invalidated" }
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+ end
- it "should authenticate with pre draft 10 oauth2 auth header" do
- get '/',{},{"HTTP_AUTHORIZATION"=>"Token my_token"}
- last_response.should be_ok
- response = MultiJson.decode(last_response.body)
- response.should == {"oauth_token" => "my_token", "oauth_version"=>2, "strategies"=>["oauth20_token","token"]}
- end
+ describe "token given through a HTTP Auth Header following the OAuth2 pre draft" do
+ context "authorized and non-invalidated token" do
+ it "authenticates" do
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Token valid_token" }
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
+ end
+ end
+
+ context "non-authorized token" do
+ it "doesn't authenticate" do
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Token not_authorized" }
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+
+ context "authorized and invalidated token" do
+ it "doesn't authenticate with an invalidated token" do
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Token invalidated" }
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+ end
- it "should authenticate with oauth2 query parameter" do
- get '/?oauth_token=my_token'
- last_response.should be_ok
- response = MultiJson.decode(last_response.body)
- response.should == {"oauth_token" => "my_token", "oauth_version"=>2, "strategies"=>["oauth20_token","token"]}
- end
+ describe "token given through a query parameter" do
+ context "authorized and non-invalidated token" do
+ it "authenticates" do
+ get '/?oauth_token=valid_token'
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
+ end
+ end
+
+ context "non-authorized token" do
+ it "doesn't authenticate" do
+ get '/?oauth_token=not_authorized'
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+
+ context "authorized and invalidated token" do
+ it "doesn't authenticate with an invalidated token" do
+ get '/?oauth_token=invalidated'
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+ end
- it "should authenticate with oauth2 post parameter" do
- post '/', :oauth_token=>'my_token'
- last_response.should be_ok
- response = MultiJson.decode(last_response.body)
- response.should == {"oauth_token" => "my_token", "oauth_version"=>2, "strategies"=>["oauth20_token","token"]}
+ describe "token given through a post parameter" do
+ context "authorized and non-invalidated token" do
+ it "authenticates" do
+ post '/', :oauth_token => 'valid_token'
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
+ end
+ end
+
+ context "non-authorized token" do
+ it "doesn't authenticate" do
+ post '/', :oauth_token => 'not_authorized'
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+
+ context "authorized and invalidated token" do
+ it "doesn't authenticate with an invalidated token" do
+ post '/', :oauth_token => 'invalidated'
+ last_response.should be_ok
+ response = MultiJson.decode(last_response.body)
+ response.should == {}
+ end
+ end
+ end
end
@@ -108,8 +199,13 @@ def secret
class OauthToken
attr_accessor :token
- def self.find_by_token(token)
- OauthToken.new(token)
+ def self.find(conditions_hash)
+ case conditions_hash[:conditions].last
+ when "not_authorized", "invalidated"
+ nil
+ else
+ OauthToken.new(conditions_hash[:conditions].last)
+ end
end
def initialize(token)
@@ -132,5 +228,4 @@ def self.remember(nonce,timestamp)
end
end
-
end

0 comments on commit fa8c375

Please sign in to comment.