Skip to content
This repository
Browse code

OAuth2 support in Rack Filter. First step to refactoring to rack. Specs.

  • Loading branch information...
commit 62eaa5c61dd1d8bc602705902547af9e10e32c14 1 parent f805e8c
Pelle Braendgaard authored
2  .gitignore
@@ -6,3 +6,5 @@ pkg
6 6 *.gem
7 7 .bundle
8 8 .swp
  9 +.idea
  10 +.rvmrc
85 Gemfile.lock
... ... @@ -0,0 +1,85 @@
  1 +PATH
  2 + remote: .
  3 + specs:
  4 + oauth-plugin (0.4.0.pre4)
  5 + multi_json
  6 + oauth (~> 0.4.4)
  7 + rack
  8 +
  9 +GEM
  10 + remote: http://rubygems.org/
  11 + specs:
  12 + addressable (2.2.2)
  13 + configuration (1.2.0)
  14 + diff-lcs (1.1.2)
  15 + fakeweb (1.3.0)
  16 + faraday (0.5.4)
  17 + addressable (~> 2.2.2)
  18 + multipart-post (~> 1.1.0)
  19 + rack (>= 1.1.0, < 2)
  20 + faraday_middleware (0.3.1)
  21 + faraday (~> 0.5.3)
  22 + fuubar (0.0.3)
  23 + rspec (~> 2.0)
  24 + rspec-instafail (~> 0.1.4)
  25 + ruby-progressbar (~> 0.0.9)
  26 + growl (1.0.3)
  27 + guard (0.2.2)
  28 + open_gem (~> 1.4.2)
  29 + thor (~> 0.14.3)
  30 + guard-rspec (0.1.9)
  31 + guard (>= 0.2.2)
  32 + hashie (0.4.0)
  33 + launchy (0.3.7)
  34 + configuration (>= 0.0.5)
  35 + rake (>= 0.8.1)
  36 + multi_json (0.0.5)
  37 + multi_xml (0.2.0)
  38 + multipart-post (1.1.0)
  39 + oauth (0.4.4)
  40 + open_gem (1.4.2)
  41 + launchy (~> 0.3.5)
  42 + opentransact (0.1.0)
  43 + multi_json
  44 + multi_xml
  45 + oauth (~> 0.4.4)
  46 + rack (1.2.1)
  47 + rack-test (0.5.6)
  48 + rack (>= 1.0)
  49 + rake (0.8.7)
  50 + rspec (2.4.0)
  51 + rspec-core (~> 2.4.0)
  52 + rspec-expectations (~> 2.4.0)
  53 + rspec-mocks (~> 2.4.0)
  54 + rspec-core (2.4.0)
  55 + rspec-expectations (2.4.0)
  56 + diff-lcs (~> 1.1.2)
  57 + rspec-instafail (0.1.5)
  58 + rspec-mocks (2.4.0)
  59 + ruby-progressbar (0.0.9)
  60 + simple_oauth (0.1.3)
  61 + thor (0.14.6)
  62 + twitter (1.1.0)
  63 + faraday (~> 0.5.3)
  64 + faraday_middleware (~> 0.3.1)
  65 + hashie (~> 0.4.0)
  66 + multi_json (~> 0.0.5)
  67 + multi_xml (~> 0.2.0)
  68 + simple_oauth (~> 0.1.3)
  69 +
  70 +PLATFORMS
  71 + ruby
  72 +
  73 +DEPENDENCIES
  74 + fakeweb
  75 + fuubar
  76 + growl
  77 + guard-rspec
  78 + multi_json
  79 + oauth (~> 0.4.4)
  80 + oauth-plugin!
  81 + opentransact
  82 + rack
  83 + rack-test
  84 + rspec (~> 2.4.0)
  85 + twitter
8 Guardfile
... ... @@ -0,0 +1,8 @@
  1 +# A sample Guardfile
  2 +# More info at http://github.com/guard/guard#readme
  3 +
  4 +guard 'rspec', :version => 2 do
  5 + watch('^spec/(.*)_spec.rb')
  6 + watch('^lib/oauth/(.*)\.rb') { |m| "spec/#{m[1]}_spec.rb" }
  7 + watch('^spec/spec_helper.rb') { "spec" }
  8 +end
27 lib/oauth/controllers/application_controller_methods.rb
@@ -39,6 +39,7 @@ class Authenticator
39 39 def initialize(controller,strategies)
40 40 @controller = controller
41 41 @strategies = strategies
  42 + controller.send :oauth_authenticator=, self
42 43 end
43 44
44 45 def params
@@ -180,11 +181,11 @@ def token_and_options
180 181 protected
181 182
182 183 def current_token
183   - @current_token
  184 + @oauth_authenticator.try(:token)
184 185 end
185 186
186 187 def current_client_application
187   - @current_client_application
  188 + @oauth_authenticator.try(:client_application)
188 189 end
189 190
190 191 def oauth?
@@ -213,26 +214,8 @@ def access_denied
213 214
214 215 private
215 216
216   - def current_token=(token)
217   - @current_token=token
218   - if @current_token
219   - @current_user=@current_token.user
220   - @current_client_application=@current_token.client_application
221   - else
222   - @current_user = nil
223   - @current_client_application = nil
224   - end
225   - @current_token
226   - end
227   -
228   - def current_client_application=(app)
229   - if app
230   - @current_client_application = app
231   - @current_user = app.user
232   - else
233   - @current_client_application = nil
234   - @current_user = nil
235   - end
  217 + def oauth_authenticator=(auth)
  218 + @oauth_authenticator = auth
236 219 end
237 220 end
238 221 end
51 lib/oauth/rack/oauth_filter.rb
... ... @@ -1,6 +1,8 @@
1 1 require "rack"
2 2 require "rack/request"
3   -require "oauth/signature"
  3 +require "oauth"
  4 +require "oauth/request_proxy/rack_request"
  5 +
4 6 module OAuth
5 7 module Rack
6 8
@@ -22,29 +24,56 @@ def initialize(app)
22 24 def call(env)
23 25 request = ::Rack::Request.new(env)
24 26 env["oauth_plugin"]=true
25   - if ClientApplication.verify_request(request) do |request_proxy|
  27 + if token_string = oauth2_token(request)
  28 + token = Oauth2Token.find_by_token(token_string) if token_string
  29 + if token
  30 + env["oauth.token"] = token
  31 + env["oauth.version"] = 2
  32 + end
  33 +
  34 + elsif oauth1_verify(request) do |request_proxy|
26 35 client_application = ClientApplication.find_by_key(request_proxy.consumer_key)
27   - env["oauth.client_application_candidate"] = client_application
  36 + env["oauth.client_application_candidate"] = client_application
28 37 # Store this temporarily in client_application object for use in request token generation
29 38 client_application.token_callback_url=request_proxy.oauth_callback if request_proxy.oauth_callback
30 39
31   - oauth_token = client_application.tokens.first(:conditions=>{:token => request_proxy.token})
32   - if oauth_token.respond_to?(:provided_oauth_verifier=)
33   - oauth_token.provided_oauth_verifier=request_proxy.oauth_verifier
  40 + oauth_token = nil
  41 +
  42 + if request_proxy.token
  43 + oauth_token = client_application.tokens.first(:conditions=>{:token => request_proxy.token})
  44 + if oauth_token.respond_to?(:provided_oauth_verifier=)
  45 + oauth_token.provided_oauth_verifier=request_proxy.oauth_verifier
  46 + end
  47 + env["oauth.token_candidate"] = oauth_token
34 48 end
35   - env["oauth.token_candidate"] = oauth_token
36 49 # return the token secret and the consumer secret
37 50 [(oauth_token.nil? ? nil : oauth_token.secret), (client_application.nil? ? nil : client_application.secret)]
38 51 end
39 52 env["oauth.token"] = env["oauth.token_candidate"]
40 53 env["oauth.client_application"] = env["oauth.client_application_candidate"]
41   -# Rails.logger.info "oauth.token = #{env["oauth.token"].inspect}"
  54 + env["oauth.version"] = 1
42 55 end
43 56 env["oauth.client_application_candidate"] = nil
44 57 env["oauth.token_candidate"] = nil
45   - response = @app.call(env)
  58 + @app.call(env)
46 59 end
47   - end
48   -
  60 +
  61 + def oauth1_verify(request, options = {}, &block)
  62 + begin
  63 + signature = OAuth::Signature.build(request, options, &block)
  64 + return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
  65 + value = signature.verify
  66 + value
  67 + rescue OAuth::Signature::UnknownSignatureMethod => e
  68 + false
  69 + end
  70 + end
  71 +
  72 + def oauth2_token(request)
  73 + request.params["oauth_token"] ||
  74 + request.env["HTTP_AUTHORIZATION"] &&
  75 + request.env["HTTP_AUTHORIZATION"][/^(OAuth|Token) ([^\s]*)$/] && $2
  76 + end
  77 + end
49 78 end
50 79 end
11 oauth-plugin.gemspec
@@ -25,7 +25,14 @@ Gem::Specification.new do |s|
25 25 s.summary = %q{Ruby on Rails Plugin for OAuth Provider and Consumer}
26 26 s.add_development_dependency "twitter"
27 27 s.add_development_dependency "opentransact"
28   -
29   - s.add_dependency(%q<oauth>, [">= 0.4.4"])
  28 + s.add_development_dependency "rspec", "~> 2.4.0"
  29 + s.add_development_dependency "fakeweb"
  30 + s.add_development_dependency "fuubar"
  31 + s.add_development_dependency "guard-rspec"
  32 + s.add_development_dependency "growl"
  33 + s.add_development_dependency "rack-test"
  34 + s.add_dependency "multi_json"
  35 + s.add_dependency("oauth", ["~> 0.4.4"])
  36 + s.add_dependency("rack")
30 37 end
31 38
109 spec/rack/oauth_filter_spec.rb
... ... @@ -0,0 +1,109 @@
  1 +require 'spec_helper'
  2 +require 'rack/test'
  3 +require 'oauth/rack/oauth_filter'
  4 +require 'multi_json'
  5 +require 'forwardable'
  6 +class OAuthEcho
  7 + def call(env)
  8 + response = {}
  9 + response[:oauth_token] = env["oauth.token"].token if env["oauth.token"]
  10 + response[:client_application] = env["oauth.client_application"].key if env["oauth.client_application"]
  11 + response[:oauth_version] = env["oauth.version"] if env["oauth.version"]
  12 + [200 ,{"Accept"=>"application/json"}, [MultiJson.encode(response)] ]
  13 + end
  14 +end
  15 +
  16 +# Dummy implementation
  17 +class ClientApplication
  18 + attr_accessor :key
  19 +
  20 + def self.find_by_key(key)
  21 + ClientApplication.new(key)
  22 + end
  23 +
  24 + def initialize(key)
  25 + @key = key
  26 + end
  27 +
  28 + def secret
  29 + "secret"
  30 + end
  31 +end
  32 +
  33 +class OauthToken
  34 + attr_accessor :token
  35 +
  36 + def self.find_by_token(token)
  37 + OauthToken.new(token)
  38 + end
  39 +
  40 + def initialize(token)
  41 + @token = token
  42 + end
  43 +
  44 + def secret
  45 + "secret"
  46 + end
  47 +end
  48 +
  49 +class Oauth2Token < OauthToken ; end
  50 +
  51 +class OauthNonce
  52 + # Always remember
  53 + def self.remember(nonce,timestamp)
  54 + true
  55 + end
  56 +end
  57 +
  58 +describe OAuth::Rack::OAuthFilter do
  59 + include Rack::Test::Methods
  60 +
  61 + def app
  62 + @app ||= OAuth::Rack::OAuthFilter.new(OAuthEcho.new)
  63 + end
  64 +
  65 + it "should pass through without oauth" do
  66 + get '/'
  67 + last_response.should be_ok
  68 + response = MultiJson.decode(last_response.body)
  69 + response.should == {}
  70 + end
  71 +
  72 +# it "should sign with consumer" do
  73 +# consumer = "consumer"
  74 +# get '/'
  75 +# last_response.should be_ok
  76 +# response = MultiJson.decode(last_response.body)
  77 +# response.should == {"client_application" => consumer}
  78 +# end
  79 +
  80 + it "should authenticate with oauth2 auth header" do
  81 + get '/',{},{"HTTP_AUTHORIZATION"=>"OAuth my_token"}
  82 + last_response.should be_ok
  83 + response = MultiJson.decode(last_response.body)
  84 + response.should == {"oauth_token" => "my_token", "oauth_version"=>2}
  85 + end
  86 +
  87 + it "should authenticate with pre draft 10 oauth2 auth header" do
  88 + get '/',{},{"HTTP_AUTHORIZATION"=>"Token my_token"}
  89 + last_response.should be_ok
  90 + response = MultiJson.decode(last_response.body)
  91 + response.should == {"oauth_token" => "my_token", "oauth_version"=>2}
  92 + end
  93 +
  94 + it "should authenticate with oauth2 query parameter" do
  95 + get '/?oauth_token=my_token'
  96 + last_response.should be_ok
  97 + response = MultiJson.decode(last_response.body)
  98 + response.should == {"oauth_token" => "my_token", "oauth_version"=>2}
  99 + end
  100 +
  101 + it "should authenticate with oauth2 post parameter" do
  102 + post '/', :oauth_token=>'my_token'
  103 + last_response.should be_ok
  104 + response = MultiJson.decode(last_response.body)
  105 + response.should == {"oauth_token" => "my_token", "oauth_version"=>2}
  106 + end
  107 +
  108 +
  109 +end
3  spec/spec_helper.rb
... ... @@ -0,0 +1,3 @@
  1 +$LOAD_PATH.unshift(File.dirname(__FILE__))
  2 +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
  3 +require 'rspec'

0 comments on commit 62eaa5c

Please sign in to comment.
Something went wrong with that request. Please try again.