authlogic-connect 0.0.3.4 → 0.0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +156 -43
- data/Rakefile +1 -1
- data/lib/authlogic-connect.rb +2 -71
- data/lib/authlogic_connect/authlogic_connect.rb +46 -0
- data/lib/authlogic_connect/callback_filter.rb +1 -1
- data/lib/authlogic_connect/common.rb +1 -1
- data/lib/authlogic_connect/common/state.rb +16 -0
- data/lib/authlogic_connect/common/user.rb +102 -34
- data/lib/authlogic_connect/common/variables.rb +68 -16
- data/lib/authlogic_connect/engine.rb +0 -1
- data/lib/authlogic_connect/{common/ext.rb → ext.rb} +1 -0
- data/lib/authlogic_connect/oauth.rb +3 -1
- data/lib/authlogic_connect/oauth/helper.rb +17 -13
- data/lib/authlogic_connect/oauth/process.rb +61 -76
- data/lib/authlogic_connect/oauth/session.rb +3 -14
- data/lib/authlogic_connect/oauth/state.rb +54 -0
- data/lib/authlogic_connect/oauth/tokens/google_token.rb +9 -1
- data/lib/authlogic_connect/oauth/tokens/oauth_token.rb +67 -2
- data/lib/authlogic_connect/oauth/tokens/twitter_token.rb +2 -0
- data/lib/authlogic_connect/oauth/user.rb +57 -74
- data/lib/authlogic_connect/oauth/variables.rb +52 -27
- data/lib/authlogic_connect/openid.rb +3 -0
- data/lib/authlogic_connect/openid/process.rb +30 -0
- data/lib/authlogic_connect/openid/session.rb +6 -53
- data/lib/authlogic_connect/openid/state.rb +47 -0
- data/lib/authlogic_connect/openid/tokens/my_openid_token.rb +3 -0
- data/lib/authlogic_connect/openid/tokens/openid_token.rb +6 -0
- data/lib/authlogic_connect/openid/user.rb +38 -68
- data/lib/authlogic_connect/openid/variables.rb +17 -3
- data/lib/authlogic_connect/token.rb +0 -1
- data/lib/open_id_authentication.rb +0 -1
- data/rails/init.rb +1 -1
- data/test/controllers/test_users_controller.rb +21 -0
- data/test/libs/database.rb +48 -0
- data/test/libs/user.rb +3 -0
- data/test/libs/user_session.rb +2 -0
- data/test/old.rb +53 -0
- data/test/test_authlogic_connect.rb +1 -1
- data/test/test_helper.rb +142 -42
- data/test/test_user.rb +255 -0
- metadata +15 -4
@@ -1,21 +1,73 @@
|
|
1
|
-
module AuthlogicConnect::Common
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
module AuthlogicConnect::Common::Variables
|
2
|
+
include AuthlogicConnect::Common::State
|
3
|
+
|
4
|
+
def auth_controller
|
5
|
+
is_auth_session? ? controller : session_class.controller
|
6
|
+
end
|
7
|
+
|
8
|
+
def auth_session
|
9
|
+
auth_controller.session.symbolize_keys!
|
10
|
+
auth_controller.session.keys.each do |key|
|
11
|
+
auth_controller.session[key.to_s] = auth_controller.session.delete(key) if key.to_s =~ /^OpenID/
|
10
12
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
auth_controller.session
|
14
|
+
end
|
15
|
+
|
16
|
+
def auth_params
|
17
|
+
auth_controller.params.symbolize_keys!
|
18
|
+
auth_controller.params.keys.each do |key|
|
19
|
+
auth_controller.params[key.to_s] = auth_controller.params.delete(key) if key.to_s =~ /^OpenID/
|
14
20
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
21
|
+
auth_controller.params
|
22
|
+
end
|
23
|
+
|
24
|
+
def auth_callback_url(options = {})
|
25
|
+
auth_controller.url_for({:controller => auth_controller.controller_name, :action => auth_controller.action_name}.merge(options))
|
26
|
+
end
|
27
|
+
|
28
|
+
# if we've said it's a "user" (registration), or a "session" (login)
|
29
|
+
def auth_type
|
30
|
+
from_session_or_params(:authentication_type)
|
31
|
+
end
|
32
|
+
|
33
|
+
# auth_params and auth_session attributes are all String!
|
34
|
+
def from_session_or_params(by)
|
35
|
+
key = by.is_a?(Symbol) ? by : by.to_sym
|
36
|
+
result = auth_params[key] if (auth_params && auth_params[key])
|
37
|
+
result = auth_session[key] if result.blank? # might be null here too
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
# because user and session are so closely tied together, I am still
|
42
|
+
# uncertain as to how they are saved. So this makes sure if we are
|
43
|
+
# logging in, it must be saving the session, otherwise the user.
|
44
|
+
def correct_request_class?
|
45
|
+
if is_auth_session?
|
46
|
+
auth_type.to_s == "session"
|
47
|
+
else
|
48
|
+
auth_type.to_s == "user"
|
18
49
|
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_session_key(key, value)
|
19
53
|
|
20
54
|
end
|
21
|
-
|
55
|
+
|
56
|
+
# because we may need to store 6+ session variables, all with pretty lengthy names,
|
57
|
+
# might as well just tinify them.
|
58
|
+
# just an idea
|
59
|
+
def optimized_session_key(key)
|
60
|
+
@optimized_session_keys ||= {
|
61
|
+
:auth_request_class => :authcl,
|
62
|
+
:authentication_method => :authme,
|
63
|
+
:authentication_type => :authty,
|
64
|
+
:oauth_provider => :authpr,
|
65
|
+
:auth_callback_method => :authcb,
|
66
|
+
:oauth_request_token => :authtk,
|
67
|
+
:oauth_request_token_secret => :authsc,
|
68
|
+
:auth_attributes => :authat
|
69
|
+
}
|
70
|
+
@optimized_session_keys[key]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module AuthlogicConnect::Oauth
|
2
2
|
end
|
3
3
|
|
4
|
+
require File.dirname(__FILE__) + "/oauth/state"
|
4
5
|
require File.dirname(__FILE__) + "/oauth/variables"
|
5
6
|
require File.dirname(__FILE__) + "/oauth/process"
|
6
7
|
require File.dirname(__FILE__) + "/oauth/user"
|
@@ -9,4 +10,5 @@ require File.dirname(__FILE__) + "/oauth/helper"
|
|
9
10
|
|
10
11
|
ActiveRecord::Base.send(:include, AuthlogicConnect::Oauth::User)
|
11
12
|
Authlogic::Session::Base.send(:include, AuthlogicConnect::Oauth::Session)
|
12
|
-
ActionController::Base.helper AuthlogicConnect::Oauth::Helper
|
13
|
+
ActionController::Base.helper AuthlogicConnect::Oauth::Helper
|
14
|
+
ActionView::Helpers::FormBuilder.send(:include, AuthlogicConnect::Oauth::FormHelper)
|
@@ -1,16 +1,20 @@
|
|
1
|
-
module AuthlogicConnect::Oauth
|
2
|
-
module Helper
|
3
|
-
def oauth_register_button(options = {})
|
4
|
-
oauth_button('register_with_oauth', options)
|
5
|
-
end
|
6
|
-
|
7
|
-
def oauth_login_button(options = {})
|
8
|
-
oauth_button('login_with_oauth', options)
|
9
|
-
end
|
1
|
+
module AuthlogicConnect::Oauth::Helper
|
10
2
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
3
|
+
# options include "name"
|
4
|
+
def oauth_register_hidden_input
|
5
|
+
oauth_input(:type => "user")
|
15
6
|
end
|
7
|
+
|
8
|
+
def oauth_login_hidden_input
|
9
|
+
oauth_input(:type => "session")
|
10
|
+
end
|
11
|
+
|
12
|
+
def oauth_input(options = {})
|
13
|
+
tag(:input, {:type => "hidden", :name => "authentication_type", :value => options[:type]})
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
module AuthlogicConnect::Oauth::FormHelper
|
19
|
+
|
16
20
|
end
|
@@ -1,83 +1,68 @@
|
|
1
|
-
module AuthlogicConnect::Oauth
|
2
|
-
module Process
|
1
|
+
module AuthlogicConnect::Oauth::Process
|
3
2
|
|
4
|
-
|
5
|
-
include AuthlogicConnect::Oauth::Variables
|
3
|
+
include AuthlogicConnect::Oauth::Variables
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
authenticate_with_oauth
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def redirecting_to_oauth_server?
|
18
|
-
authenticating_with_oauth? && oauth_response.blank?
|
19
|
-
end
|
20
|
-
|
21
|
-
def redirect_to_oauth
|
22
|
-
save_oauth_callback
|
23
|
-
|
24
|
-
if oauth_version == 1.0
|
25
|
-
request = oauth_token.get_request_token(oauth_callback_url)
|
26
|
-
save_auth_session(request)
|
27
|
-
auth_controller.redirect_to request.authorize_url
|
28
|
-
else
|
29
|
-
auth_controller.redirect_to oauth_consumer.web_server.authorize_url(
|
30
|
-
:redirect_uri => oauth_callback_url,
|
31
|
-
:scope => oauth_token.config[:scope]
|
32
|
-
)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def save_oauth_callback
|
37
|
-
puts "save_oauth_callback"
|
38
|
-
# Store the class which is redirecting, so we can ensure other classes
|
39
|
-
# don't get confused and attempt to use the response
|
40
|
-
auth_session[:oauth_request_class] = self.class.name
|
41
|
-
auth_session[:oauth_provider] = auth_params[:oauth_provider]
|
42
|
-
|
43
|
-
# Tell our rack callback filter what method the current request is using
|
44
|
-
auth_session[:auth_callback_method] = auth_controller.request.method
|
45
|
-
end
|
46
|
-
|
47
|
-
def save_auth_session(request)
|
48
|
-
# store token and secret
|
49
|
-
auth_session[:oauth_request_token] = request.token
|
50
|
-
auth_session[:oauth_request_token_secret] = request.secret
|
51
|
-
end
|
52
|
-
|
53
|
-
def oauth_callback_url
|
54
|
-
auth_controller.url_for :controller => auth_controller.controller_name, :action => auth_controller.action_name
|
5
|
+
# Step 2: after save is called, it runs this method for validation
|
6
|
+
def validate_by_oauth
|
7
|
+
validate_email_field = false
|
8
|
+
unless new_oauth_request? # shouldn't be validating if it's redirecting...
|
9
|
+
restore_attributes
|
10
|
+
complete_oauth_transaction
|
55
11
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
def oauth_key_and_secret
|
64
|
-
if oauth_version == 1.0
|
65
|
-
result = request_token.get_access_token(:oauth_verifier => auth_params[:oauth_verifier])
|
66
|
-
result = {:key => result.token, :secret => result.secret}
|
67
|
-
else
|
68
|
-
result = oauth_consumer.web_server.get_access_token(oauth_key, :redirect_uri => oauth_callback_url)
|
69
|
-
result = {:key => result.token, :secret => oauth_key}
|
70
|
-
end
|
71
|
-
result
|
72
|
-
end
|
73
|
-
|
74
|
-
def generate_access_token
|
75
|
-
if oauth_version == 1.0
|
76
|
-
request_token.get_access_token(:oauth_verifier => auth_params[:oauth_verifier])
|
77
|
-
else
|
78
|
-
oauth_consumer.web_server.get_access_token(oauth_key, :redirect_uri => oauth_callback_url)
|
79
|
-
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Step 3: if new_oauth_request?, redirect to oauth provider
|
15
|
+
def redirect_to_oauth
|
16
|
+
save_oauth_session
|
17
|
+
authorize_url = token_class.authorize_url(auth_callback_url) do |request_token|
|
18
|
+
save_auth_session_token(request_token) # only for oauth version 1
|
80
19
|
end
|
20
|
+
auth_controller.redirect_to authorize_url
|
21
|
+
end
|
22
|
+
|
23
|
+
# Step 3a: save our passed-parameters into the session,
|
24
|
+
# so we can retrieve them after the redirect calls back
|
25
|
+
def save_oauth_session
|
26
|
+
# Store the class which is redirecting, so we can ensure other classes
|
27
|
+
# don't get confused and attempt to use the response
|
28
|
+
auth_session[:auth_request_class] = self.class.name
|
29
|
+
|
30
|
+
auth_session[:authentication_type] = auth_params[:authentication_type]
|
31
|
+
auth_session[:oauth_provider] = auth_params[:oauth_provider]
|
32
|
+
auth_session[:auth_method] = "oauth"
|
81
33
|
|
34
|
+
# Tell our rack callback filter what method the current request is using
|
35
|
+
auth_session[:auth_callback_method] = auth_controller.request.method
|
36
|
+
end
|
37
|
+
|
38
|
+
# Step 3b (if version 1.0 of oauth)
|
39
|
+
def save_auth_session_token(request)
|
40
|
+
# store token and secret
|
41
|
+
auth_session[:oauth_request_token] = request.token
|
42
|
+
auth_session[:oauth_request_token_secret] = request.secret
|
43
|
+
end
|
44
|
+
|
45
|
+
def restore_attributes
|
82
46
|
end
|
47
|
+
|
48
|
+
# Step 4: on callback, run this method
|
49
|
+
def authenticate_with_oauth
|
50
|
+
# implemented in User and Session Oauth modules
|
51
|
+
end
|
52
|
+
|
53
|
+
# Step last, after the response
|
54
|
+
# having lots of trouble testing logging and out multiple times,
|
55
|
+
# so there needs to be a solid way to know when a user has messed up loggin in.
|
56
|
+
def cleanup_oauth_session
|
57
|
+
[:auth_request_class,
|
58
|
+
:authentication_type,
|
59
|
+
:auth_method,
|
60
|
+
:auth_attributes,
|
61
|
+
:oauth_provider,
|
62
|
+
:auth_callback_method,
|
63
|
+
:oauth_request_token,
|
64
|
+
:oauth_request_token_secret
|
65
|
+
].each {|key| auth_session.delete(key)}
|
66
|
+
end
|
67
|
+
|
83
68
|
end
|
@@ -37,26 +37,15 @@ module AuthlogicConnect::Oauth
|
|
37
37
|
return block.nil?
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
return false unless oauth_provider
|
42
|
-
|
43
|
-
# Initial request when user presses one of the button helpers
|
44
|
-
initial_request = (controller.params && !controller.params[:login_with_oauth].blank?)
|
45
|
-
# When the oauth provider responds and we made the initial request
|
46
|
-
initial_response = (oauth_response && auth_session && auth_session[:oauth_request_class] == self.class.name)
|
47
|
-
|
48
|
-
return initial_request || initial_response
|
49
|
-
end
|
50
|
-
|
51
|
-
def authenticate_with_oauth
|
40
|
+
def complete_oauth_transaction
|
52
41
|
if @record
|
53
42
|
self.attempted_record = record
|
54
43
|
else
|
55
44
|
# this generated token is always the same for a user!
|
56
45
|
# this is searching with User.find ...
|
57
46
|
# attempted_record is part of AuthLogic
|
58
|
-
|
59
|
-
token =
|
47
|
+
hash = oauth_token_and_secret
|
48
|
+
token = token_class.find_by_key_or_token(hash[:key], hash[:token], :include => [:user]) # some weird error if I leave out the include)
|
60
49
|
self.attempted_record = token.user
|
61
50
|
end
|
62
51
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# all these methods must return true or false
|
2
|
+
module AuthlogicConnect::Oauth::State
|
3
|
+
|
4
|
+
# 1. to call
|
5
|
+
# checks that we just passed parameters to it,
|
6
|
+
# and that the parameters say 'authentication_method' == 'oauth'
|
7
|
+
def oauth_request?
|
8
|
+
!auth_params.nil? && oauth_provider?
|
9
|
+
end
|
10
|
+
|
11
|
+
# 2. from call
|
12
|
+
# checks that the correct session variables are there
|
13
|
+
def oauth_response?
|
14
|
+
!oauth_response.nil? && !auth_session.nil? && auth_session[:auth_request_class] == self.class.name && auth_session[:auth_method] == "oauth"
|
15
|
+
end
|
16
|
+
alias_method :oauth_complete?, :oauth_response?
|
17
|
+
|
18
|
+
# 3. either to or from call
|
19
|
+
def using_oauth?
|
20
|
+
oauth_request? || oauth_response?
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_oauth_request?
|
24
|
+
oauth_response.blank?
|
25
|
+
end
|
26
|
+
|
27
|
+
def oauth_provider?
|
28
|
+
!oauth_provider.nil? && !oauth_provider.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
# main method we call on validation
|
32
|
+
def authenticating_with_oauth?
|
33
|
+
correct_request_class? && using_oauth?
|
34
|
+
end
|
35
|
+
|
36
|
+
def allow_oauth_redirect?
|
37
|
+
authenticating_with_oauth? && !oauth_complete?
|
38
|
+
end
|
39
|
+
|
40
|
+
# both checks if it can redirect, and does the redirect.
|
41
|
+
# is there a more concise way to do this?
|
42
|
+
def redirecting_to_oauth_server?
|
43
|
+
if allow_oauth_redirect?
|
44
|
+
redirect_to_oauth
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_password_with_oauth?
|
51
|
+
!using_oauth? && require_password?
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# http://code.google.com/apis/accounts/docs/OAuth_ref.html
|
2
|
+
# http://code.google.com/apis/accounts/docs/OpenID.html#settingup
|
1
3
|
# http://code.google.com/apis/accounts/docs/OAuth.html
|
2
4
|
# http://code.google.com/apis/accounts/docs/RegistrationForWebAppsAuto.html
|
5
|
+
# http://www.manu-j.com/blog/add-google-oauth-ruby-on-rails-sites/214/
|
3
6
|
# http://googlecodesamples.com/oauth_playground/
|
4
7
|
# Scopes:
|
5
8
|
# Analytics https://www.google.com/analytics/feeds/
|
@@ -30,4 +33,9 @@ class GoogleToken < OauthToken
|
|
30
33
|
:access_token_path => "/accounts/OAuthGetAccessToken",
|
31
34
|
:scope => "https://www.google.com/m8/feeds/"
|
32
35
|
|
33
|
-
|
36
|
+
key do |access_token|
|
37
|
+
body = JSON.parse(access_token.get("https://www.google.com/m8/feeds/contacts/default/full?alt=json&max-results=0").body)
|
38
|
+
email = body["feed"]["author"].first["email"]["$t"] # $t is some weird google json thing
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -3,9 +3,9 @@ class OauthToken < Token
|
|
3
3
|
def client
|
4
4
|
unless @client
|
5
5
|
if oauth_version == 1.0
|
6
|
-
@client = OAuth::AccessToken.new(self.consumer, self.
|
6
|
+
@client = OAuth::AccessToken.new(self.consumer, self.token, self.secret)
|
7
7
|
else
|
8
|
-
@client = OAuth2::AccessToken.new(self.consumer, self.
|
8
|
+
@client = OAuth2::AccessToken.new(self.consumer, self.token)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -22,6 +22,7 @@ class OauthToken < Token
|
|
22
22
|
|
23
23
|
class << self
|
24
24
|
|
25
|
+
# oauth version, 1.0 or 2.0
|
25
26
|
def version(value)
|
26
27
|
@oauth_version = value
|
27
28
|
end
|
@@ -30,6 +31,22 @@ class OauthToken < Token
|
|
30
31
|
@oauth_version ||= 1.0
|
31
32
|
end
|
32
33
|
|
34
|
+
# unique key that we will use from the AccessToken response
|
35
|
+
# to identify the user by.
|
36
|
+
# in Twitter, its "user_id". Twitter has "screen_name", but that's
|
37
|
+
# more subject to change than user_id. Pick whatever is least likely to change
|
38
|
+
def key(value = nil, &block)
|
39
|
+
if block_given?
|
40
|
+
@oauth_key = block
|
41
|
+
else
|
42
|
+
@oauth_key = value.is_a?(Symbol) ? value : value.to_sym
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def oauth_key
|
47
|
+
@oauth_key
|
48
|
+
end
|
49
|
+
|
33
50
|
def consumer
|
34
51
|
unless @consumer
|
35
52
|
if oauth_version == 1.0
|
@@ -42,6 +59,54 @@ class OauthToken < Token
|
|
42
59
|
@consumer
|
43
60
|
end
|
44
61
|
|
62
|
+
# if we're lucky we can find it by the token.
|
63
|
+
def find_by_key_or_token(key, token, options = {})
|
64
|
+
result = self.find_by_key(key, options) unless key.nil?
|
65
|
+
unless result
|
66
|
+
result = self.find_by_token(token, options) unless token.nil?
|
67
|
+
end
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
# this is a wrapper around oauth 1 and 2.
|
72
|
+
# it looks obscure, but from the api point of view
|
73
|
+
# you won't have to worry about it's implementation.
|
74
|
+
# in oauth 1.0, key = oauth_token, secret = oauth_secret
|
75
|
+
# in oauth 2.0, key = code, secret = access_token
|
76
|
+
def get_token_and_secret(options = {})
|
77
|
+
oauth_verifier = options[:oauth_verifier]
|
78
|
+
redirect_uri = options[:redirect_uri]
|
79
|
+
token = options[:token]
|
80
|
+
secret = options[:secret]
|
81
|
+
if oauth_version == 1.0
|
82
|
+
access = request_token(token, secret).get_access_token(:oauth_verifier => oauth_verifier)
|
83
|
+
result = {:token => access.token, :secret => access.secret, :key => nil}
|
84
|
+
if self.oauth_key
|
85
|
+
if oauth_key.is_a?(Proc)
|
86
|
+
result[:key] = oauth_key.call(access)
|
87
|
+
else
|
88
|
+
result[:key] = access.params[self.oauth_key] || access.params[self.oauth_key.to_s] # try both
|
89
|
+
end
|
90
|
+
end
|
91
|
+
else
|
92
|
+
access = consumer.web_server.get_access_token(secret, :redirect_uri => redirect_uri)
|
93
|
+
result = {:token => access.token, :secret => secret, :key => nil}
|
94
|
+
end
|
95
|
+
result
|
96
|
+
end
|
97
|
+
|
98
|
+
# this is a cleaner method so we can access the authorize_url
|
99
|
+
# from oauth 1 or 2
|
100
|
+
def authorize_url(callback_url, &block)
|
101
|
+
if oauth_version == 1.0
|
102
|
+
request = get_request_token(callback_url)
|
103
|
+
yield request if block_given?
|
104
|
+
return request.authorize_url
|
105
|
+
else
|
106
|
+
return consumer.web_server.authorize_url(:redirect_uri => callback_url, :scope => self.config[:scope])
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
45
110
|
def request_token(token, secret)
|
46
111
|
OAuth::RequestToken.new(consumer, token, secret)
|
47
112
|
end
|