Skip to content

Commit

Permalink
OAuth2 support in Rack Filter. First step to refactoring to rack. Specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
pelle committed Jan 14, 2011
1 parent f805e8c commit 62eaa5c
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ pkg
*.gem
.bundle
.swp
.idea
.rvmrc
85 changes: 85 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
PATH
remote: .
specs:
oauth-plugin (0.4.0.pre4)
multi_json
oauth (~> 0.4.4)
rack

GEM
remote: http://rubygems.org/
specs:
addressable (2.2.2)
configuration (1.2.0)
diff-lcs (1.1.2)
fakeweb (1.3.0)
faraday (0.5.4)
addressable (~> 2.2.2)
multipart-post (~> 1.1.0)
rack (>= 1.1.0, < 2)
faraday_middleware (0.3.1)
faraday (~> 0.5.3)
fuubar (0.0.3)
rspec (~> 2.0)
rspec-instafail (~> 0.1.4)
ruby-progressbar (~> 0.0.9)
growl (1.0.3)
guard (0.2.2)
open_gem (~> 1.4.2)
thor (~> 0.14.3)
guard-rspec (0.1.9)
guard (>= 0.2.2)
hashie (0.4.0)
launchy (0.3.7)
configuration (>= 0.0.5)
rake (>= 0.8.1)
multi_json (0.0.5)
multi_xml (0.2.0)
multipart-post (1.1.0)
oauth (0.4.4)
open_gem (1.4.2)
launchy (~> 0.3.5)
opentransact (0.1.0)
multi_json
multi_xml
oauth (~> 0.4.4)
rack (1.2.1)
rack-test (0.5.6)
rack (>= 1.0)
rake (0.8.7)
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.5)
rspec-mocks (2.4.0)
ruby-progressbar (0.0.9)
simple_oauth (0.1.3)
thor (0.14.6)
twitter (1.1.0)
faraday (~> 0.5.3)
faraday_middleware (~> 0.3.1)
hashie (~> 0.4.0)
multi_json (~> 0.0.5)
multi_xml (~> 0.2.0)
simple_oauth (~> 0.1.3)

PLATFORMS
ruby

DEPENDENCIES
fakeweb
fuubar
growl
guard-rspec
multi_json
oauth (~> 0.4.4)
oauth-plugin!
opentransact
rack
rack-test
rspec (~> 2.4.0)
twitter
8 changes: 8 additions & 0 deletions Guardfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# A sample Guardfile
# 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" }
end
27 changes: 5 additions & 22 deletions lib/oauth/controllers/application_controller_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Authenticator
def initialize(controller,strategies)
@controller = controller
@strategies = strategies
controller.send :oauth_authenticator=, self
end

def params
Expand Down Expand Up @@ -180,11 +181,11 @@ def token_and_options
protected

def current_token
@current_token
@oauth_authenticator.try(:token)
end

def current_client_application
@current_client_application
@oauth_authenticator.try(:client_application)
end

def oauth?
Expand Down Expand Up @@ -213,26 +214,8 @@ def access_denied

private

def current_token=(token)
@current_token=token
if @current_token
@current_user=@current_token.user
@current_client_application=@current_token.client_application
else
@current_user = nil
@current_client_application = nil
end
@current_token
end

def current_client_application=(app)
if app
@current_client_application = app
@current_user = app.user
else
@current_client_application = nil
@current_user = nil
end
def oauth_authenticator=(auth)
@oauth_authenticator = auth
end
end
end
Expand Down
51 changes: 40 additions & 11 deletions lib/oauth/rack/oauth_filter.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require "rack"
require "rack/request"
require "oauth/signature"
require "oauth"
require "oauth/request_proxy/rack_request"

module OAuth
module Rack

Expand All @@ -22,29 +24,56 @@ def initialize(app)
def call(env)
request = ::Rack::Request.new(env)
env["oauth_plugin"]=true
if ClientApplication.verify_request(request) do |request_proxy|
if token_string = oauth2_token(request)
token = Oauth2Token.find_by_token(token_string) if token_string
if token
env["oauth.token"] = token
env["oauth.version"] = 2
end

elsif oauth1_verify(request) do |request_proxy|
client_application = ClientApplication.find_by_key(request_proxy.consumer_key)
env["oauth.client_application_candidate"] = client_application
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

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 = nil

if 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
end
env["oauth.token_candidate"] = oauth_token
end
env["oauth.token_candidate"] = oauth_token
# return the token secret and the consumer secret
[(oauth_token.nil? ? nil : oauth_token.secret), (client_application.nil? ? nil : client_application.secret)]
end
env["oauth.token"] = env["oauth.token_candidate"]
env["oauth.client_application"] = env["oauth.client_application_candidate"]
# Rails.logger.info "oauth.token = #{env["oauth.token"].inspect}"
env["oauth.version"] = 1
end
env["oauth.client_application_candidate"] = nil
env["oauth.token_candidate"] = nil
response = @app.call(env)
@app.call(env)
end
end


def oauth1_verify(request, options = {}, &block)
begin
signature = OAuth::Signature.build(request, options, &block)
return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
value = signature.verify
value
rescue OAuth::Signature::UnknownSignatureMethod => e
false
end
end

def oauth2_token(request)
request.params["oauth_token"] ||
request.env["HTTP_AUTHORIZATION"] &&
request.env["HTTP_AUTHORIZATION"][/^(OAuth|Token) ([^\s]*)$/] && $2
end
end
end
end
11 changes: 9 additions & 2 deletions oauth-plugin.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ Gem::Specification.new do |s|
s.summary = %q{Ruby on Rails Plugin for OAuth Provider and Consumer}
s.add_development_dependency "twitter"
s.add_development_dependency "opentransact"

s.add_dependency(%q<oauth>, [">= 0.4.4"])
s.add_development_dependency "rspec", "~> 2.4.0"
s.add_development_dependency "fakeweb"
s.add_development_dependency "fuubar"
s.add_development_dependency "guard-rspec"
s.add_development_dependency "growl"
s.add_development_dependency "rack-test"
s.add_dependency "multi_json"
s.add_dependency("oauth", ["~> 0.4.4"])
s.add_dependency("rack")
end

109 changes: 109 additions & 0 deletions spec/rack/oauth_filter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require 'spec_helper'
require 'rack/test'
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[:client_application] = env["oauth.client_application"].key if env["oauth.client_application"]
response[:oauth_version] = env["oauth.version"] if env["oauth.version"]
[200 ,{"Accept"=>"application/json"}, [MultiJson.encode(response)] ]
end
end

# Dummy implementation
class ClientApplication
attr_accessor :key

def self.find_by_key(key)
ClientApplication.new(key)
end

def initialize(key)
@key = key
end

def secret
"secret"
end
end

class OauthToken
attr_accessor :token

def self.find_by_token(token)
OauthToken.new(token)
end

def initialize(token)
@token = token
end

def secret
"secret"
end
end

class Oauth2Token < OauthToken ; end

class OauthNonce
# Always remember
def self.remember(nonce,timestamp)
true
end
end

describe OAuth::Rack::OAuthFilter do
include Rack::Test::Methods

def app
@app ||= OAuth::Rack::OAuthFilter.new(OAuthEcho.new)
end

it "should pass through without oauth" do
get '/'
last_response.should be_ok
response = MultiJson.decode(last_response.body)
response.should == {}
end

# it "should sign with consumer" do
# consumer = "consumer"
# get '/'
# last_response.should be_ok
# response = MultiJson.decode(last_response.body)
# response.should == {"client_application" => consumer}
# 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}
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}
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}
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}
end


end
3 changes: 3 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require 'rspec'

0 comments on commit 62eaa5c

Please sign in to comment.