Navigation Menu

Skip to content

Commit

Permalink
Allow access to token parameters and raw Response.
Browse files Browse the repository at this point in the history
Additionally adds the ability to include arbitrary parameters to
generated authorization urls.

Includes new tests for RequestToken and AccessToken.
  • Loading branch information
rares authored and mojodna committed Feb 13, 2009
1 parent a12f205 commit de77954
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 10 deletions.
37 changes: 27 additions & 10 deletions lib/oauth/token.rb
Expand Up @@ -27,7 +27,14 @@ def initialize

# Superclass for tokens used by OAuth Clients
class ConsumerToken < Token
attr_accessor :consumer
attr_accessor :consumer, :params
attr_reader :response

def self.from_hash(consumer, hash)
token = self.new(consumer, hash[:oauth_token], hash[:oauth_token_secret])
token.params = hash
token
end

def initialize(consumer, token="", secret="")
super(token, secret)
Expand All @@ -40,7 +47,7 @@ def initialize(consumer, token="", secret="")
# @token.request(:post, '/people', @person.to_xml, { 'Content-Type' => 'application/xml' })
#
def request(http_method, path, *arguments)
response = consumer.request(http_method, path, self, {}, *arguments)
@response = consumer.request(http_method, path, self, {}, *arguments)
end

# Sign a request generated elsewhere using Net:HTTP::Post.new or friends
Expand All @@ -53,33 +60,43 @@ def sign!(request, options = {})
# This is normally created by the Consumer object.
class RequestToken < ConsumerToken

# Returns the authorization url that you need to use for redirecting the user
def authorize_url
consumer.authorize_url + "?oauth_token=" + CGI.escape(token)
# Generate an authorization URL for user authorization
def authorize_url(params = nil)
params = (params || {}).merge(:oauth_token => self.token)
build_authorize_url(consumer.authorize_url, params)
end

# exchange for AccessToken on server
def get_access_token(options = {})
response = consumer.token_request(consumer.http_method, (consumer.access_token_url? ? consumer.access_token_url : consumer.access_token_path), self, options)
OAuth::AccessToken.new(consumer, response[:oauth_token], response[:oauth_token_secret])
OAuth::AccessToken.from_hash(consumer, response)
end

protected

# construct an authorization url
def build_authorize_url(base_url, params)
uri = URI.parse(base_url.to_s)
# TODO doesn't handle array values correctly
uri.query = params.map { |k,v| [k, CGI.escape(v)] * "=" } * "&"
uri.to_s
end
end

# The Access Token is used for the actual "real" web service calls thatyou perform against the server
# The Access Token is used for the actual "real" web service calls that you perform against the server
class AccessToken < ConsumerToken

# The less intrusive way. Otherwise, if we are to do it correctly inside consumer,
# we need to restructure and touch more methods: request(), sign!(), etc.
def request(http_method, path, *arguments)
request_uri = URI.parse(path)
site_uri = consumer.uri
is_service_uri_different = (request_uri.absolute? && request_uri != site_uri)
consumer.uri(request_uri) if is_service_uri_different
resp = super(http_method, path, *arguments)
@response = super(http_method, path, *arguments)
# NOTE: reset for wholesomeness? meaning that we admit only AccessToken service calls may use different URIs?
# so reset in case consumer is still used for other token-management tasks subsequently?
consumer.uri(site_uri) if is_service_uri_different
resp
@response
end

# Make a regular GET request using AccessToken
Expand Down
28 changes: 28 additions & 0 deletions test/test_access_token.rb
@@ -0,0 +1,28 @@
require File.dirname(__FILE__) + '/test_helper.rb'
require 'oauth/token'
require 'oauth/consumer'

class TestAccessToken < Test::Unit::TestCase
def setup
@fake_response = {
:user_id => 5734758743895,
:oauth_token => "key",
:oauth_token_secret => "secret"
}
# setup a fake req. token. mocking Consumer would be more appropriate...
@access_token = OAuth::AccessToken.from_hash(
OAuth::Consumer.new("key", "secret", {}),
@fake_response
)
end

def test_provides_response_parameters
assert @access_token
assert_respond_to @access_token, :params
end

def test_access_token_makes_non_oauth_response_params_available
assert_not_nil @access_token.params[:user_id]
assert_equal 5734758743895, @access_token.params[:user_id]
end
end
53 changes: 53 additions & 0 deletions test/test_request_token.rb
@@ -0,0 +1,53 @@
require File.dirname(__FILE__) + '/test_helper.rb'
require 'oauth/token'
require 'oauth/consumer'

class StubbedToken < OAuth::RequestToken
define_method :build_authorize_url_promoted do |root_domain, params|
build_authorize_url root_domain, params
end
end

class TestRequestToken < Test::Unit::TestCase
def setup
# setup a fake req. token. mocking Consumer would be more appropriate...
@request_token = OAuth::RequestToken.new(
OAuth::Consumer.new("key", "secret", {}),
"key",
"secret"
)
end

def test_request_token_builds_authorize_url_connectly_with_additional_params
auth_url = @request_token.authorize_url({:oauth_callback => "github.com"})
assert_not_nil auth_url
assert_match(/oauth_token/, auth_url)
assert_match(/oauth_callback/, auth_url)
end

def test_request_token_builds_authorize_url_connectly_with_no_or_nil_params
# we should only have 1 key in the url returned if we didn't pass anything.
# this is the only required param to authenticate the client.
auth_url = @request_token.authorize_url(nil)
assert_not_nil auth_url
assert_match(/\?oauth_token=/, auth_url)

auth_url = @request_token.authorize_url
assert_not_nil auth_url
assert_match(/\?oauth_token=/, auth_url)
end

#TODO: mock out the Consumer to test the Consumer/AccessToken interaction.
def test_get_access_token
end

def test_build_authorize_url
@stubbed_token = StubbedToken.new(nil, nil, nil)
assert_respond_to @stubbed_token, :build_authorize_url_promoted
url = @stubbed_token.build_authorize_url_promoted(
"http://github.com/oauth/authorize",
{:foo => "bar bar"})
assert url
assert_equal "http://github.com/oauth/authorize?foo=bar+bar", url
end
end

0 comments on commit de77954

Please sign in to comment.