Skip to content

Commit

Permalink
Properly use explicit hosts for each step of the OAuth Dance
Browse files Browse the repository at this point in the history
* Fixes issue http://github.com/episod/oauth-dancer/issues#issue/1 reported by Paul Lindner
  • Loading branch information
episod committed Apr 19, 2010
1 parent 6b58af4 commit 008233f
Show file tree
Hide file tree
Showing 5 changed files with 717 additions and 41 deletions.
42 changes: 23 additions & 19 deletions app/controllers/the_dance_controller.rb
@@ -1,14 +1,14 @@
class TheDanceController < ApplicationController
before_filter :clear_ghost_trap, :only => [ :index, :get_request_token ]

def index
@service_providers = ServiceProvider.find(:all, :include => [ :access_tokens ], :order => :label )
end

def xauth_collect
@service_provider = ServiceProvider.find(params[:service_provider_id])
end

def get_request_token
@service_provider = ServiceProvider.find(params[:service_provider_id])
callback_url = ""
Expand All @@ -18,25 +18,25 @@ def get_request_token
callback_url = url_for(:controller => "the_dance", :action => "process_callback", :service_provider_id => @service_provider.id)
end
GhostTrap.trap! :oauth_callback, callback_url
@consumer = @service_provider.to_oauth_consumer

@consumer = @service_provider.to_oauth_consumer({ :context => :request_token })
headers = { } # optional headers to attach to the request
@request_token = @consumer.get_request_token({:oauth_callback => callback_url}, nil, headers)
@request_token = @consumer.get_request_token({:oauth_callback => callback_url}, nil, headers)

GhostTrap.trap! :request_token, @request_token.token
GhostTrap.trap! :request_token_secret, @request_token.secret

# temporarily store the request_token in the session
session[@request_token.token] = @request_token.secret

# We'll be picking up this flow later in out of band requests.
if @service_provider.use_out_of_band?
GhostTrap.trap! :out_of_band, "Setup session for out of band processing."
session[:out_of_band] = { :request_token => @request_token.token,
session[:out_of_band] = { :request_token => @request_token.token,
:request_token_secret => @request_token.secret,
:service_provider_id => @service_provider.id}
:service_provider_id => @service_provider.id}
end

if @request_token.callback_confirmed?
GhostTrap.trap! :callback_confirmed, "The service provider confirmed the oauth_callback"
else
Expand All @@ -61,34 +61,38 @@ def process_callback
flash[:error] = "There was a problem securing an access token for #{@service_provider.label}. Check the GhostTrap."
GhostTrap.trap! :access_token_error, e.inspect
end

else
flash[:error] = "There was a problem securing an access token for #{@service_provider.label}"
GhostTrap.trap! :access_token_error, "No request token secret from the service provider."
redirect_to :action => "index"
end
end
end

def process_out_of_band
# TODO: Process OOB flow
end

def send_to_authorization(request_token)
# make sure to use the specific authorize URL specified by the app.
url = request_token.authorize_url
uri = URI.parse(url)
uri.host = @service_provider.authorize_host
url = uri.to_s
GhostTrap.trap! :authorize_url, "Redirecting to #{url}"
redirect_to url
end

def get_access_token(service_provider, request_token, oauth_verifier)
consumer = service_provider.to_oauth_consumer
consumer = service_provider.to_oauth_consumer(:context => :access_token)
access_token = consumer.get_access_token(request_token, { :oauth_verifier => oauth_verifier})
store_access_token(service_provider, access_token)
end

def get_access_token_with_xauth
GhostTrap.trap! :xauth_mode, "using xAuth to sign in"
@service_provider = ServiceProvider.find(params[:service_provider_id])
consumer = @service_provider.to_oauth_consumer
consumer = @service_provider.to_oauth_consumer(:context => :access_token)
options = {}
options[:x_auth_username] = params[:login]
options[:x_auth_password] = params[:password]
Expand All @@ -98,7 +102,7 @@ def get_access_token_with_xauth
@access_token = OAuth::AccessToken.from_hash(consumer, response)
store_access_token(@service_provider, @access_token)
end

def store_access_token(service_provider, access_token)
token_model = service_provider.access_tokens.find(:first, :conditions => { :oauth_token => access_token.token })
unless token_model
Expand Down
55 changes: 33 additions & 22 deletions app/models/service_provider.rb
Expand Up @@ -3,77 +3,87 @@ class ServiceProvider < ActiveRecord::Base
validates_uniqueness_of :label, :on => :create, :message => "must be unique"
validates_presence_of :label, :on => :create, :message => "can't be blank"
validates_presence_of :consumer_key, :on => :create, :message => "can't be blank"

def uri_objects
{
:request_token_uri => URI.parse(self.request_token_url),
:request_token_uri => URI.parse(self.request_token_url),
:access_token_uri => URI.parse(self.access_token_url),
:authorize_uri => URI.parse(self.authorize_url)
}
end

def base_host
host = uri_objects[:request_token_uri].scheme + "://" + uri_objects[:request_token_uri].host
unless [80, 443].include?(uri_objects[:request_token_uri].port)
host = host + ":" + uri_objects[:request_token_uri].port.to_s

def base_host(context_for_base_host = :request_token)
uri_ref = :request_token_uri
case context_for_base_host
when :request_token
uri_ref = :request_token_uri
when :access_token
uri_ref = :access_token_uri
when :authorize
uri_ref = :access_token_uri
end

host = uri_objects[uri_ref].scheme + "://" + uri_objects[uri_ref].host
unless [80, 443].include?(uri_objects[uri_ref].port)
host = host + ":" + uri_objects[uri_ref].port.to_s
end
host
end

def request_token_host
uri_objects[:request_token_uri].host
end

def request_token_path
uri_objects[:request_token_uri].path
end

def authorize_host
uri_objects[:authorize_uri].host
end

def authorize_path
uri_objects[:authorize_uri].path
end

def access_token_host
uri_objects[:access_token_uri].host
end

def access_token_path
uri_objects[:access_token_uri].path
end

def to_oauth_consumer(options = {})
OAuth::Consumer.new(self.consumer_key, self.consumer_secret, self.options_for_consumer(options))
end

def get_request_token(oauth_callback, options = {})
consumer = self.to_oauth_consumer(options)
request_token = consumer.get_request_token({:oauth_callback => oauth_callback})
return request_token
end

def exchange_request_token_for_access_token(request_token, oauth_verifier)
access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
return access_token
end

def to_two_legged_token(consumer = nil)
if !consumer
consumer = self.to_oauth_consumer
end
OAuth::TwoLeggedMockToken.new(consumer)
end

def autentication_http_method
if self.use_post_for_authentication_steps?
return :post
else
return :get
end
end

def authentication_scheme
scheme = self.oauth_scheme
if scheme
Expand All @@ -82,11 +92,12 @@ def authentication_scheme
return :header
end
end

def options_for_consumer(override_options = {})
context_for_base_host = override_options.delete(:context) || :request_token
{
:signature_method => 'HMAC-SHA1',
:site => self.base_host,
:site => self.base_host(context_for_base_host),
:request_token_path => self.request_token_path,
:authorize_path => self.authorize_path,
:access_token_path => self.access_token_path,
Expand All @@ -95,7 +106,7 @@ def options_for_consumer(override_options = {})
:oauth_version => self.oauth_version || "1.0"
}.merge(override_options)
end

end


Expand Down
63 changes: 63 additions & 0 deletions vendor/gems/http_configuration-1.0.2/.specification
@@ -0,0 +1,63 @@
--- !ruby/object:Gem::Specification
name: http_configuration
version: !ruby/object:Gem::Version
prerelease: false
segments:
- 1
- 0
- 2
version: 1.0.2
platform: ruby
authors: []

autorequire:
bindir: bin
cert_chain: []

date: 2010-04-19 00:00:00 -07:00
default_executable:
dependencies: []

description:
email:
executables: []

extensions: []

extra_rdoc_files: []

files:
- lib
- lib/http_configuration.rb
has_rdoc: true
homepage:
licenses: []

post_install_message:
rdoc_options: []

require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
requirements: []

rubyforge_project:
rubygems_version: 1.3.6
signing_key:
specification_version: 3
summary:
test_files: []

0 comments on commit 008233f

Please sign in to comment.