oauth_consumer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/CHANGELOG +2 -0
- data/Gemfile +2 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1 -0
- data/Rakefile +2 -0
- data/generators/oauth_consumer/USAGE +10 -0
- data/generators/oauth_consumer/oauth_consumer_generator.rb +52 -0
- data/generators/oauth_consumer/templates/consumer_token.rb +11 -0
- data/generators/oauth_consumer/templates/controller.rb +27 -0
- data/generators/oauth_consumer/templates/index.html.erb +29 -0
- data/generators/oauth_consumer/templates/index.html.haml +18 -0
- data/generators/oauth_consumer/templates/index.html.slim +15 -0
- data/generators/oauth_consumer/templates/migration.rb +23 -0
- data/generators/oauth_consumer/templates/oauth_config.rb +73 -0
- data/generators/oauth_consumer/templates/show.html.erb +7 -0
- data/generators/oauth_consumer/templates/show.html.haml +8 -0
- data/generators/oauth_consumer/templates/show.html.slim +8 -0
- data/init.rb +1 -0
- data/lib/generators/active_record/oauth_consumer_generator.rb +33 -0
- data/lib/generators/active_record/oauth_consumer_templates/consumer_token.rb +11 -0
- data/lib/generators/active_record/oauth_consumer_templates/migration.rb +20 -0
- data/lib/generators/erb/oauth_consumer_generator.rb +14 -0
- data/lib/generators/erb/oauth_consumer_templates/index.html.erb +29 -0
- data/lib/generators/erb/oauth_consumer_templates/show.html.erb +7 -0
- data/lib/generators/haml/oauth_consumer_generator.rb +21 -0
- data/lib/generators/haml/oauth_consumer_templates/index.html.haml +18 -0
- data/lib/generators/haml/oauth_consumer_templates/show.html.haml +8 -0
- data/lib/generators/mongoid/oauth_consumer_generator.rb +15 -0
- data/lib/generators/mongoid/oauth_consumer_templates/consumer_token.rb +41 -0
- data/lib/generators/oauth_consumer/USAGE +11 -0
- data/lib/generators/oauth_consumer/oauth_consumer_generator.rb +31 -0
- data/lib/generators/oauth_consumer/templates/controller.rb +59 -0
- data/lib/generators/oauth_consumer/templates/oauth_config.rb +68 -0
- data/lib/generators/oauth_inflections.rb +6 -0
- data/lib/generators/oauth_plugin.rb +0 -0
- data/lib/oauth/controllers/consumer_controller.rb +152 -0
- data/lib/oauth/models/consumers/service_loader.rb +28 -0
- data/lib/oauth/models/consumers/services/oauth2_token.rb +50 -0
- data/lib/oauth/models/consumers/services/twitter_token.rb +24 -0
- data/lib/oauth/models/consumers/simple_client.rb +50 -0
- data/lib/oauth/models/consumers/token.rb +121 -0
- data/lib/oauth_consumer/version.rb +3 -0
- data/lib/oauth_consumer.rb +2 -0
- data/oauth_consumer.gemspec +24 -0
- data/rails/init.rb +1 -0
- data/spec/spec_helper.rb +3 -0
- data/tasks/oauth_tasks.rake +4 -0
- metadata +148 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'oauth/controllers/consumer_controller'
|
2
|
+
class OauthConsumersController < ApplicationController
|
3
|
+
include Oauth::Controllers::ConsumerController
|
4
|
+
# Replace this with the equivalent for your authentication framework
|
5
|
+
# Eg. for devise
|
6
|
+
#
|
7
|
+
# before_filter :authenticate_user!, :only=>:index
|
8
|
+
before_filter :login_required, :only=>:index
|
9
|
+
|
10
|
+
def index
|
11
|
+
@consumer_tokens=ConsumerToken.all :conditions=>{:user_id=>current_user.id}
|
12
|
+
@services=OAUTH_CREDENTIALS.keys-@consumer_tokens.collect{|c| c.class.service_name}
|
13
|
+
end
|
14
|
+
|
15
|
+
def callback
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def client
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
# Change this to decide where you want to redirect user to after callback is finished.
|
27
|
+
# params[:id] holds the service name so you could use this to redirect to various parts
|
28
|
+
# of your application depending on what service you're connecting to.
|
29
|
+
def go_back
|
30
|
+
redirect_to root_url
|
31
|
+
end
|
32
|
+
|
33
|
+
# The plugin requires logged_in? to return true or false if the user is logged in. Uncomment and
|
34
|
+
# call your auth frameworks equivalent below if different. eg. for devise:
|
35
|
+
#
|
36
|
+
# def logged_in?
|
37
|
+
# user_signed_in?
|
38
|
+
# end
|
39
|
+
|
40
|
+
# The plugin requires current_user to return the current logged in user. Uncomment and
|
41
|
+
# call your auth frameworks equivalent below if different.
|
42
|
+
# def current_user
|
43
|
+
# current_person
|
44
|
+
# end
|
45
|
+
|
46
|
+
# The plugin requires a way to log a user in. Call your auth frameworks equivalent below
|
47
|
+
# if different. eg. for devise:
|
48
|
+
#
|
49
|
+
# def current_user=(user)
|
50
|
+
# sign_in(user)
|
51
|
+
# end
|
52
|
+
|
53
|
+
# Override this to deny the user or redirect to a login screen depending on your framework and app
|
54
|
+
# if different. eg. for devise:
|
55
|
+
#
|
56
|
+
# def deny_access!
|
57
|
+
# raise Acl9::AccessDenied
|
58
|
+
# end
|
59
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# edit this file to contain credentials for the OAuth services you support.
|
2
|
+
# each entry needs a corresponding token model.
|
3
|
+
#
|
4
|
+
# eg. :twitter => TwitterToken, :hour_feed => HourFeedToken etc.
|
5
|
+
#
|
6
|
+
# OAUTH_CREDENTIALS={
|
7
|
+
# :twitter=>{
|
8
|
+
# :key=>"",
|
9
|
+
# :secret=>"",
|
10
|
+
# :client=>:twitter_gem, # :twitter_gem or :oauth_gem (defaults to :twitter_gem)
|
11
|
+
# :expose => false, # expose client at /oauth_consumers/twitter/client see docs
|
12
|
+
# :allow_login => true # Use :allow_login => true to allow user to login to account
|
13
|
+
# },
|
14
|
+
# :google=>{
|
15
|
+
# :key=>"",
|
16
|
+
# :secret=>"",
|
17
|
+
# :expose => false, # expose client at /oauth_consumers/google/client see docs
|
18
|
+
# :scope=>"" # see http://code.google.com/apis/gdata/faq.html#AuthScopes
|
19
|
+
# },
|
20
|
+
# :github=>{
|
21
|
+
# :key => "",
|
22
|
+
# :secret => "",
|
23
|
+
# :expose => false, # expose client at /oauth_consumers/twitter/client see docs
|
24
|
+
#
|
25
|
+
# },
|
26
|
+
# :facebook=>{
|
27
|
+
# :key => "",
|
28
|
+
# :secret => ""
|
29
|
+
# },
|
30
|
+
# :agree2=>{
|
31
|
+
# :key=>"",
|
32
|
+
# :secret=>""
|
33
|
+
# },
|
34
|
+
# :fireeagle=>{
|
35
|
+
# :key=>"",
|
36
|
+
# :secret=>""
|
37
|
+
# },
|
38
|
+
# :oauth2_server => {
|
39
|
+
# :key=>"",
|
40
|
+
# :secret=>"",
|
41
|
+
# :oauth_version => 2
|
42
|
+
# :options=>{ # OAuth::Consumer options
|
43
|
+
# :site=>"http://hourfeed.com" # Remember to add a site for a generic OAuth site
|
44
|
+
# }
|
45
|
+
# },
|
46
|
+
# :hour_feed=>{
|
47
|
+
# :key=>"",
|
48
|
+
# :secret=>"",
|
49
|
+
# :options=>{ # OAuth::Consumer options
|
50
|
+
# :site=>"http://hourfeed.com" # Remember to add a site for a generic OAuth site
|
51
|
+
# }
|
52
|
+
# },
|
53
|
+
# :nu_bux=>{
|
54
|
+
# :key=>"",
|
55
|
+
# :secret=>"",
|
56
|
+
# :super_class=>"OpenTransactToken", # if a OAuth service follows a particular standard
|
57
|
+
# # with a token implementation you can set the superclass
|
58
|
+
# # to use
|
59
|
+
# :options=>{ # OAuth::Consumer options
|
60
|
+
# :site=>"http://nubux.heroku.com"
|
61
|
+
# }
|
62
|
+
# }
|
63
|
+
# }
|
64
|
+
#
|
65
|
+
OAUTH_CREDENTIALS={
|
66
|
+
} unless defined? OAUTH_CREDENTIALS
|
67
|
+
|
68
|
+
load 'oauth/models/consumers/service_loader.rb'
|
File without changes
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module Oauth
|
2
|
+
module Controllers
|
3
|
+
module ConsumerController
|
4
|
+
def self.included(controller)
|
5
|
+
controller.class_eval do
|
6
|
+
before_filter :load_consumer, :except=>:index
|
7
|
+
skip_before_filter :verify_authenticity_token,:only=>:callback
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def index
|
12
|
+
@consumer_tokens=ConsumerToken.all :conditions=>{:user_id=>current_user.id}
|
13
|
+
# The services the user hasn't already connected to
|
14
|
+
@services=OAUTH_CREDENTIALS.keys-@consumer_tokens.collect{|c| c.class.service_name}
|
15
|
+
end
|
16
|
+
|
17
|
+
# If the user has no token or <tt>force</tt> is set as a param, creates request token and
|
18
|
+
# redirects on to oauth provider's auth page. Otherwise it displays a page with an option
|
19
|
+
# to disconnect and redo
|
20
|
+
def show
|
21
|
+
if @token && params[:force]
|
22
|
+
@token.destroy
|
23
|
+
@token = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
unless @token
|
27
|
+
if @consumer.ancestors.include?(Oauth2Token)
|
28
|
+
request_url = callback2_oauth_consumer_url + callback2_querystring
|
29
|
+
redirect_to @consumer.authorize_url(request_url)
|
30
|
+
else
|
31
|
+
request_url = callback_oauth_consumer_url(params[:id]) + callback2_querystring
|
32
|
+
@request_token = @consumer.get_request_token(request_url)
|
33
|
+
session[@request_token.token]=@request_token.secret
|
34
|
+
if @request_token.callback_confirmed?
|
35
|
+
redirect_to @request_token.authorize_url
|
36
|
+
else
|
37
|
+
redirect_to(@request_token.authorize_url + "&oauth_callback=#{callback_oauth_consumer_url(params[:id])}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def callback2_querystring
|
44
|
+
request.query_string.blank? ? '' : '?' + request.query_string
|
45
|
+
end
|
46
|
+
|
47
|
+
def callback2
|
48
|
+
@token = @consumer.access_token(current_user, params[:code], callback2_oauth_consumer_url)
|
49
|
+
if @token
|
50
|
+
# Log user in
|
51
|
+
if logged_in?
|
52
|
+
flash[:notice] = "#{params[:id].humanize} was successfully connected to your account"
|
53
|
+
else
|
54
|
+
self.current_user = @token.user
|
55
|
+
flash[:notice] = "You logged in with #{params[:id].humanize}"
|
56
|
+
end
|
57
|
+
go_back
|
58
|
+
else
|
59
|
+
flash[:error] = "An error happened, please try connecting again"
|
60
|
+
redirect_to oauth_consumer_url(params[:id])
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def callback
|
66
|
+
@request_token_secret=session[params[:oauth_token]]
|
67
|
+
if @request_token_secret
|
68
|
+
@token=@consumer.find_or_create_from_request_token(current_user,params[:oauth_token],@request_token_secret,params[:oauth_verifier])
|
69
|
+
session[params[:oauth_token]] = nil
|
70
|
+
if @token
|
71
|
+
# Log user in
|
72
|
+
if logged_in?
|
73
|
+
flash[:notice] = "#{params[:id].humanize} was successfully connected to your account"
|
74
|
+
else
|
75
|
+
self.current_user = @token.user
|
76
|
+
flash[:notice] = "You logged in with #{params[:id].humanize}"
|
77
|
+
end
|
78
|
+
go_back
|
79
|
+
else
|
80
|
+
flash[:error] = "An error happened, please try connecting again"
|
81
|
+
redirect_to oauth_consumer_url(params[:id])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def client
|
88
|
+
method = request.method.downcase.to_sym
|
89
|
+
path = "/#{params[:endpoint]}?#{request.query_string}"
|
90
|
+
if consumer_credentials[:expose]
|
91
|
+
if @token
|
92
|
+
oauth_response = @token.client.send(method, path)
|
93
|
+
if oauth_response.is_a? Net::HTTPRedirection
|
94
|
+
# follow redirect
|
95
|
+
oauth_response = @token.client.send(method, oauth_response['Location'])
|
96
|
+
end
|
97
|
+
|
98
|
+
render :text => oauth_response.body
|
99
|
+
else
|
100
|
+
render :text => "Token needed.", :status => 403
|
101
|
+
end
|
102
|
+
else
|
103
|
+
render :text => "Not allowed", :status => 403
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def destroy
|
108
|
+
throw RecordNotFound unless @token
|
109
|
+
@token.destroy
|
110
|
+
if params[:commit]=="Reconnect"
|
111
|
+
redirect_to oauth_consumer_url(params[:id])
|
112
|
+
else
|
113
|
+
flash[:notice] = "#{params[:id].humanize} was successfully disconnected from your account"
|
114
|
+
|
115
|
+
go_back
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def callback2_oauth_consumer_url
|
120
|
+
@consumer.consumer.options[:redirect_uri]
|
121
|
+
end
|
122
|
+
|
123
|
+
protected
|
124
|
+
|
125
|
+
# Override this in your controller to decide where you want to redirect user to after callback is finished.
|
126
|
+
def go_back
|
127
|
+
redirect_to root_url
|
128
|
+
end
|
129
|
+
|
130
|
+
def consumer_credentials
|
131
|
+
OAUTH_CREDENTIALS[consumer_key]
|
132
|
+
end
|
133
|
+
|
134
|
+
def consumer_key
|
135
|
+
@consumer_key ||= params[:id].to_sym
|
136
|
+
end
|
137
|
+
|
138
|
+
def load_consumer
|
139
|
+
throw RecordNotFound unless OAUTH_CREDENTIALS.include?(consumer_key)
|
140
|
+
deny_access! unless logged_in? || consumer_credentials[:allow_login]
|
141
|
+
@consumer = "#{consumer_key.to_s.camelcase}Token".constantize
|
142
|
+
@token = @consumer.where(user_id: current_user.id.to_s).first
|
143
|
+
end
|
144
|
+
|
145
|
+
# Override this in you controller to deny user or redirect to login screen.
|
146
|
+
def deny_access!
|
147
|
+
head 401
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'oauth/controllers/consumer_controller'
|
2
|
+
|
3
|
+
# Goes through the entries in your OAUTH_CREDENTIALS and either loads the class required
|
4
|
+
# or subclasses ConsumerToken with the name.
|
5
|
+
#
|
6
|
+
# So an entry called "my_service" will create a class MyServiceToken which you can
|
7
|
+
# connect with has_one to your user model.
|
8
|
+
if defined? ConsumerToken && defined? OAUTH_CREDENTIALS
|
9
|
+
require File.join(File.dirname(__FILE__), 'services', 'oauth2_token')
|
10
|
+
|
11
|
+
OAUTH_CREDENTIALS.each do |key, value|
|
12
|
+
class_name=value[:class_name]||"#{key.to_s.classify}Token"
|
13
|
+
unless Object.const_defined?(class_name.to_sym)
|
14
|
+
if File.exists?(File.join(File.dirname(__FILE__), "services","#{key.to_s}_token.rb"))
|
15
|
+
Rails.logger.info File.join(File.dirname(__FILE__), "services","#{key.to_s}_token")
|
16
|
+
require File.join(File.dirname(__FILE__), "services","#{key.to_s}_token")
|
17
|
+
else
|
18
|
+
begin
|
19
|
+
# Let Rails auto-load from the models folder
|
20
|
+
eval class_name
|
21
|
+
rescue NameError
|
22
|
+
super_class = value[:super_class]||value[:oauth_version].to_i>=2 ? "Oauth2Token" : "ConsumerToken"
|
23
|
+
eval "class #{class_name} < #{super_class} ;end"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
class Oauth2Token < ConsumerToken
|
3
|
+
after_initialize :ensure_access, if: :expired_and_existing?
|
4
|
+
|
5
|
+
def self.consumer
|
6
|
+
@consumer ||= create_consumer
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create_consumer(options={})
|
10
|
+
OAuth2::Client.new(credentials[:key], credentials[:secret], credentials[:options])
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.authorize_url(callback_url)
|
14
|
+
options = { redirect_uri: callback_url }
|
15
|
+
options[:scope] = credentials[:scope] if credentials[:scope].present?
|
16
|
+
options[:access_type] = credentials[:access_type] if credentials[:access_type].present?
|
17
|
+
consumer.auth_code.authorize_url(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.access_token(user, code, redirect_uri)
|
21
|
+
access_token = consumer.auth_code.get_token(code, { :redirect_uri => redirect_uri, :token_method => :post })
|
22
|
+
find_or_create_from_access_token user, access_token
|
23
|
+
end
|
24
|
+
|
25
|
+
def client
|
26
|
+
@client ||= OAuth2::AccessToken.new(self.class.consumer, token, { refresh_token: refresh_token, expires_at: expires_at, expires_in: expires_in })
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [Boolean] Is the access token expired and does the record exist in the datastore?
|
30
|
+
def expired_and_existing?
|
31
|
+
return true if !self.new_record? and Time.now.to_i >= self.expires_at.to_i
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
# Refreshes the access token to ensure access
|
36
|
+
def ensure_access
|
37
|
+
self.class.find_or_create_from_access_token user, self, client.refresh!
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the expiration date (expires_in, expires_at)
|
41
|
+
#
|
42
|
+
# @return [String, String] Expires_in and expires_at, respectively
|
43
|
+
# @note It will return the default expiration time as defined in the OAuth 2.0 spec when no options are set
|
44
|
+
def expiration_date(token)
|
45
|
+
return token.expires_in, token.expires_at if !token.expires_in.nil? and !token.expires_at.nil?
|
46
|
+
return token.expires_in, (Time.now.to_i + token.expires_in.to_i) if token.expires_at.nil? and !token.expires_in.nil?
|
47
|
+
return (token.expires_at.to_i - Time.now.to_i), token.expires_at if token.expires_in.nil? and !token.expires_at.nil?
|
48
|
+
return "3600", (Time.now.to_i + 3600)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class TwitterToken < ConsumerToken
|
2
|
+
TWITTER_SETTINGS={
|
3
|
+
:site => "https://api.twitter.com",
|
4
|
+
:request_token_path => "/oauth/request_token",
|
5
|
+
:authorize_path => "/oauth/authorize",
|
6
|
+
:access_token_path => "/oauth/access_token",
|
7
|
+
}
|
8
|
+
|
9
|
+
def self.consumer(options={})
|
10
|
+
@consumer ||= OAuth::Consumer.new(credentials[:key], credentials[:secret], TWITTER_SETTINGS.merge(options))
|
11
|
+
end
|
12
|
+
|
13
|
+
def client
|
14
|
+
@client ||= begin
|
15
|
+
if self.class.credentials[:client].to_sym == :oauth_gem
|
16
|
+
super
|
17
|
+
else
|
18
|
+
require 'twitter'
|
19
|
+
Twitter::Client.new(:consumer_key => self.class.consumer.key, :consumer_secret => self.class.consumer.secret)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'json'
|
2
|
+
module Oauth
|
3
|
+
module Models
|
4
|
+
module Consumers
|
5
|
+
# This is just a simple
|
6
|
+
class SimpleClient
|
7
|
+
attr_reader :token
|
8
|
+
|
9
|
+
def initialize(token)
|
10
|
+
@token = token
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def put(path,params={})
|
15
|
+
parse(token.put(path,params, {'Accept' => 'application/json'}))
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete(path)
|
19
|
+
parse(token.delete(path, {'Accept' => 'application/json'}))
|
20
|
+
end
|
21
|
+
|
22
|
+
def post(path,params={})
|
23
|
+
parse(token.post(path,params, {'Accept' => 'application/json'}))
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(path)
|
27
|
+
parse(token.get(path, {'Accept' => 'application/json'}))
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def parse(response)
|
33
|
+
return false unless response
|
34
|
+
if ["200","201"].include? response.code
|
35
|
+
unless response.body.blank?
|
36
|
+
JSON.parse(response.body)
|
37
|
+
else
|
38
|
+
true
|
39
|
+
end
|
40
|
+
else
|
41
|
+
logger.debug "Got Response code: #{response.code}"
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'oauth/consumer'
|
2
|
+
require File.join(File.dirname(__FILE__), 'simple_client')
|
3
|
+
|
4
|
+
module Oauth
|
5
|
+
module Models
|
6
|
+
module Consumers
|
7
|
+
module Token
|
8
|
+
def self.included(model)
|
9
|
+
model.class_eval do
|
10
|
+
validates_presence_of :user, :token
|
11
|
+
end
|
12
|
+
|
13
|
+
model.send(:include, InstanceMethods)
|
14
|
+
model.send(:extend, ClassMethods)
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
|
20
|
+
def service_name
|
21
|
+
@service_name||=self.to_s.underscore.scan(/^(.*?)(_token)?$/)[0][0].to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def consumer
|
25
|
+
options = credentials[:options] || {}
|
26
|
+
@consumer||=OAuth::Consumer.new credentials[:key],credentials[:secret],options
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_request_token(callback_url)
|
30
|
+
consumer.get_request_token(:oauth_callback=>callback_url)
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_or_create_from_request_token(user,token,secret,oauth_verifier)
|
34
|
+
request_token=OAuth::RequestToken.new consumer,token,secret
|
35
|
+
options={}
|
36
|
+
options[:oauth_verifier]=oauth_verifier if oauth_verifier
|
37
|
+
access_token=request_token.get_access_token options
|
38
|
+
find_or_create_from_access_token user, access_token
|
39
|
+
end
|
40
|
+
|
41
|
+
# Finds, creates or updates a ConsumerToken by finding the token
|
42
|
+
# or taking it when it's given. It then updates the attributes and saves the changes/new record to a datastore.
|
43
|
+
# @param user [User] The user to which the access token should belong to
|
44
|
+
# @param access_token [AccessToken || Oauth2Token] Either a request token taken from the service or a ConsumerToken
|
45
|
+
# @param new_token [AccessToken] A new access token, used for refreshing the access token with OAuth 2.
|
46
|
+
#
|
47
|
+
# Usage example:
|
48
|
+
# find_or_create_from_access_token(current_user, access_token) <-- Find or create a new access token
|
49
|
+
# find_or_create_from_access-token(current_user, Oauth2Token.last, client.refresh!) <-- Edits existing record with new refreshed information
|
50
|
+
def find_or_create_from_access_token(user, access_token, new_token = nil)
|
51
|
+
if access_token.class.ancestors.include?(Oauth2Token)
|
52
|
+
token = access_token
|
53
|
+
else
|
54
|
+
if user
|
55
|
+
token = self.find_or_initialize_by_user_id_and_token(user.id, access_token.token)
|
56
|
+
else
|
57
|
+
token = self.find_or_initialize_by_token(access_token.token)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
token = if new_token then set_details(new_token, access_token) else set_details(access_token, token) end
|
62
|
+
|
63
|
+
token.save! if token.new_record? or token.changed?
|
64
|
+
|
65
|
+
token
|
66
|
+
end
|
67
|
+
|
68
|
+
# Set the details such as the secret, refresh token and expiration time to an instance of ConsumerToken
|
69
|
+
# @return [ConsumerToken] A ConsumerToken
|
70
|
+
def set_details(access_token, token)
|
71
|
+
secret = access_token.respond_to?(:secret) ? access_token.secret : nil
|
72
|
+
refresh_token = access_token.respond_to?(:refresh_token) ? access_token.refresh_token : nil
|
73
|
+
expires_in, expires_at = token.expiration_date(access_token) if token.class.ancestors.include?(Oauth2Token)
|
74
|
+
|
75
|
+
token.token = access_token.token
|
76
|
+
token.refresh_token = refresh_token
|
77
|
+
token.secret = secret
|
78
|
+
token.expires_at = expires_at
|
79
|
+
token.expires_in = expires_in
|
80
|
+
|
81
|
+
token
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_user_from_token
|
85
|
+
end
|
86
|
+
|
87
|
+
def credentials
|
88
|
+
@credentials ||= OAUTH_CREDENTIALS[service_name]
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
module InstanceMethods
|
94
|
+
|
95
|
+
# Main client for interfacing with remote service. Override this to use
|
96
|
+
# preexisting library eg. Twitter gem.
|
97
|
+
def client
|
98
|
+
@client||=OAuth::AccessToken.new(self.class.consumer, token, secret)
|
99
|
+
end
|
100
|
+
|
101
|
+
def simple_client
|
102
|
+
@simple_client ||= SimpleClient.new(client)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Override this to return user data from service
|
106
|
+
def params_for_user
|
107
|
+
{}
|
108
|
+
end
|
109
|
+
|
110
|
+
def create_user
|
111
|
+
self.user ||= begin
|
112
|
+
User.new params_for_user
|
113
|
+
user.save(:validate=>false)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "oauth_consumer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{oauth_consumer}
|
7
|
+
s.summary = %q{OAuth 1 & 2 helpers for Rails 3+}
|
8
|
+
s.description = %q{OAuth 1 & 2 and token management in Rails 3+}
|
9
|
+
s.homepage = %q{https://github.com/mgomes/oauth_consumer}
|
10
|
+
s.version = OauthConsumer::VERSION
|
11
|
+
s.authors = ["Mauricio Gomes", "Pelle Braendgaard"]
|
12
|
+
s.email = "mauricio@edge14.com"
|
13
|
+
|
14
|
+
s.add_dependency("oauth", ["~> 0.4.4"])
|
15
|
+
s.add_dependency("oauth2", '>= 0.5.0')
|
16
|
+
s.add_dependency("oj", '>= 2.1.7')
|
17
|
+
s.add_dependency("nokogiri", '>= 1.5.0')
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
24
|
+
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'oauth_consumer'
|
data/spec/spec_helper.rb
ADDED