rack-oauth 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +49 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/examples/rails-example/README +243 -0
- data/examples/rails-example/Rakefile +10 -0
- data/examples/rails-example/app/controllers/application_controller.rb +12 -0
- data/examples/rails-example/app/controllers/welcome_controller.rb +26 -0
- data/examples/rails-example/app/helpers/application_helper.rb +3 -0
- data/examples/rails-example/app/helpers/welcome_helper.rb +2 -0
- data/examples/rails-example/app/views/welcome/index.html.erb +2 -0
- data/examples/rails-example/config/boot.rb +110 -0
- data/examples/rails-example/config/database.yml +22 -0
- data/examples/rails-example/config/environment.rb +14 -0
- data/examples/rails-example/config/environments/development.rb +17 -0
- data/examples/rails-example/config/environments/production.rb +28 -0
- data/examples/rails-example/config/environments/test.rb +32 -0
- data/examples/rails-example/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails-example/config/initializers/inflections.rb +10 -0
- data/examples/rails-example/config/initializers/mime_types.rb +5 -0
- data/examples/rails-example/config/initializers/new_rails_defaults.rb +21 -0
- data/examples/rails-example/config/initializers/session_store.rb +15 -0
- data/examples/rails-example/config/locales/en.yml +5 -0
- data/examples/rails-example/config/routes.rb +6 -0
- data/examples/rails-example/db/development.sqlite3 +1 -0
- data/examples/rails-example/db/seeds.rb +7 -0
- data/examples/rails-example/db/test.sqlite3 +1 -0
- data/examples/rails-example/doc/README_FOR_APP +2 -0
- data/examples/rails-example/lib/tasks/rspec.rake +182 -0
- data/examples/rails-example/log/development.log +165 -0
- data/examples/rails-example/log/production.log +0 -0
- data/examples/rails-example/log/server.log +0 -0
- data/examples/rails-example/log/test.log +1591 -0
- data/examples/rails-example/public/404.html +30 -0
- data/examples/rails-example/public/422.html +30 -0
- data/examples/rails-example/public/500.html +30 -0
- data/examples/rails-example/public/favicon.ico +0 -0
- data/examples/rails-example/public/images/rails.png +0 -0
- data/examples/rails-example/public/javascripts/application.js +2 -0
- data/examples/rails-example/public/javascripts/controls.js +963 -0
- data/examples/rails-example/public/javascripts/dragdrop.js +973 -0
- data/examples/rails-example/public/javascripts/effects.js +1128 -0
- data/examples/rails-example/public/javascripts/prototype.js +4320 -0
- data/examples/rails-example/public/robots.txt +5 -0
- data/examples/rails-example/script/about +4 -0
- data/examples/rails-example/script/autospec +6 -0
- data/examples/rails-example/script/console +3 -0
- data/examples/rails-example/script/dbconsole +3 -0
- data/examples/rails-example/script/destroy +3 -0
- data/examples/rails-example/script/generate +3 -0
- data/examples/rails-example/script/performance/benchmarker +3 -0
- data/examples/rails-example/script/performance/profiler +3 -0
- data/examples/rails-example/script/plugin +3 -0
- data/examples/rails-example/script/runner +3 -0
- data/examples/rails-example/script/server +3 -0
- data/examples/rails-example/script/spec +10 -0
- data/examples/rails-example/script/spec_server +9 -0
- data/examples/rails-example/spec/integration/login_spec.rb +27 -0
- data/examples/rails-example/spec/rcov.opts +2 -0
- data/examples/rails-example/spec/spec.opts +4 -0
- data/examples/rails-example/spec/spec_helper.rb +12 -0
- data/examples/rails-example/tmp/webrat-1257205170.html +202 -0
- data/examples/rails-example/tmp/webrat-1257205276.html +31 -0
- data/examples/rails-example/tmp/webrat-1257205315.html +211 -0
- data/examples/rails-example/tmp/webrat-1257205333.html +31 -0
- data/examples/rails-example/tmp/webrat-1257205380.html +211 -0
- data/examples/rails-example/tmp/webrat-1257205757.html +211 -0
- data/examples/rails-example/tmp/webrat-1257210107.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210160.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210488.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210501.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210545.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210564.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210581.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210600.html +32 -0
- data/examples/rails-example/tmp/webrat-1257210608.html +32 -0
- data/examples/sinatra-twitter.rb +47 -0
- data/examples/sinatra-twitter.ru +2 -0
- data/lib/rack/oauth.rb +1 -0
- data/lib/rack-oauth.rb +378 -0
- data/spec/data/authorized_access_token.yml +58 -0
- data/spec/data/authorized_oauth_verifier.yml +1 -0
- data/spec/data/authorized_request_secret.yml +1 -0
- data/spec/data/authorized_request_token.yml +1 -0
- data/spec/data/unauthorized_request_token.yml +56 -0
- data/spec/rack_oauth_middleware_spec.rb +156 -0
- data/spec/sample_sinatra_app_spec.rb +105 -0
- data/spec/spec_helper.rb +24 -0
- metadata +162 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
2
|
+
<head>
|
3
|
+
<title>Action Controller: Exception caught</title>
|
4
|
+
<style>
|
5
|
+
body { background-color: #fff; color: #333; }
|
6
|
+
|
7
|
+
body, p, ol, ul, td {
|
8
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
9
|
+
font-size: 13px;
|
10
|
+
line-height: 18px;
|
11
|
+
}
|
12
|
+
|
13
|
+
pre {
|
14
|
+
background-color: #eee;
|
15
|
+
padding: 10px;
|
16
|
+
font-size: 11px;
|
17
|
+
}
|
18
|
+
|
19
|
+
a { color: #000; }
|
20
|
+
a:visited { color: #666; }
|
21
|
+
a:hover { color: #fff; background-color:#000; }
|
22
|
+
</style>
|
23
|
+
</head>
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<h1>Routing Error</h1>
|
27
|
+
<p><pre>No route matches "/foo/bar" with {:method=>:get}</pre></p>
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
</body>
|
32
|
+
</html>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
2
|
+
<head>
|
3
|
+
<title>Action Controller: Exception caught</title>
|
4
|
+
<style>
|
5
|
+
body { background-color: #fff; color: #333; }
|
6
|
+
|
7
|
+
body, p, ol, ul, td {
|
8
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
9
|
+
font-size: 13px;
|
10
|
+
line-height: 18px;
|
11
|
+
}
|
12
|
+
|
13
|
+
pre {
|
14
|
+
background-color: #eee;
|
15
|
+
padding: 10px;
|
16
|
+
font-size: 11px;
|
17
|
+
}
|
18
|
+
|
19
|
+
a { color: #000; }
|
20
|
+
a:visited { color: #666; }
|
21
|
+
a:hover { color: #fff; background-color:#000; }
|
22
|
+
</style>
|
23
|
+
</head>
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<h1>Routing Error</h1>
|
27
|
+
<p><pre>No route matches "/foo/bar" with {:method=>:get}</pre></p>
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
</body>
|
32
|
+
</html>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
2
|
+
<head>
|
3
|
+
<title>Action Controller: Exception caught</title>
|
4
|
+
<style>
|
5
|
+
body { background-color: #fff; color: #333; }
|
6
|
+
|
7
|
+
body, p, ol, ul, td {
|
8
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
9
|
+
font-size: 13px;
|
10
|
+
line-height: 18px;
|
11
|
+
}
|
12
|
+
|
13
|
+
pre {
|
14
|
+
background-color: #eee;
|
15
|
+
padding: 10px;
|
16
|
+
font-size: 11px;
|
17
|
+
}
|
18
|
+
|
19
|
+
a { color: #000; }
|
20
|
+
a:visited { color: #666; }
|
21
|
+
a:hover { color: #fff; background-color:#000; }
|
22
|
+
</style>
|
23
|
+
</head>
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<h1>Routing Error</h1>
|
27
|
+
<p><pre>No route matches "/foo/bar" with {:method=>:get}</pre></p>
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
</body>
|
32
|
+
</html>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
2
|
+
<head>
|
3
|
+
<title>Action Controller: Exception caught</title>
|
4
|
+
<style>
|
5
|
+
body { background-color: #fff; color: #333; }
|
6
|
+
|
7
|
+
body, p, ol, ul, td {
|
8
|
+
font-family: verdana, arial, helvetica, sans-serif;
|
9
|
+
font-size: 13px;
|
10
|
+
line-height: 18px;
|
11
|
+
}
|
12
|
+
|
13
|
+
pre {
|
14
|
+
background-color: #eee;
|
15
|
+
padding: 10px;
|
16
|
+
font-size: 11px;
|
17
|
+
}
|
18
|
+
|
19
|
+
a { color: #000; }
|
20
|
+
a:visited { color: #666; }
|
21
|
+
a:hover { color: #fff; background-color:#000; }
|
22
|
+
</style>
|
23
|
+
</head>
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<h1>Routing Error</h1>
|
27
|
+
<p><pre>No route matches "/foo/bar" with {:method=>:get}</pre></p>
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
</body>
|
32
|
+
</html>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
%w( rubygems sinatra haml ).each {|lib| require lib }
|
3
|
+
require File.dirname(__FILE__) + '/../lib/rack-oauth'
|
4
|
+
|
5
|
+
use Rack::Session::Cookie
|
6
|
+
|
7
|
+
use Rack::OAuth, :site => 'http://twitter.com', :key => '4JjFmhjfZyQ6rdbiql5A',
|
8
|
+
:secret => 'rv4ZaCgvxVPVjxHIDbMxTGFbIMxUa4KkIdPqL7HmaQo'
|
9
|
+
|
10
|
+
helpers do
|
11
|
+
|
12
|
+
# todo ... make wrapper that handles ENV?
|
13
|
+
def oauth
|
14
|
+
Rack::OAuth.get(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
get '/' do
|
20
|
+
haml :index
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/creds' do
|
24
|
+
@user = oauth.request(env, '/account/verify_credentials.json') if oauth.verified?(env)
|
25
|
+
haml :index
|
26
|
+
end
|
27
|
+
|
28
|
+
get '/oauth_complete' do
|
29
|
+
redirect '/'
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/logout' do
|
33
|
+
session.clear
|
34
|
+
redirect '/'
|
35
|
+
end
|
36
|
+
|
37
|
+
__END__
|
38
|
+
|
39
|
+
@@ index
|
40
|
+
|
41
|
+
%h1 Twitter OAuth Example
|
42
|
+
|
43
|
+
- if @user
|
44
|
+
%p User:
|
45
|
+
%pre~ @user.to_yaml
|
46
|
+
|
47
|
+
%pre~ session.to_yaml
|
data/lib/rack/oauth.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rack-oauth'
|
data/lib/rack-oauth.rb
ADDED
@@ -0,0 +1,378 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rack'
|
3
|
+
require 'oauth'
|
4
|
+
|
5
|
+
# For some reason, getting the location our of a HeaderHash doesn't always work!
|
6
|
+
#
|
7
|
+
# sometimes you can see the header key/value in the HeaderHash, but you can't get it out!
|
8
|
+
class Rack::Utils::HeaderHash
|
9
|
+
def [] key
|
10
|
+
if not has_key?(key)
|
11
|
+
hash = to_hash
|
12
|
+
hash.keys.each do |hash_key|
|
13
|
+
if hash_key.downcase == key.downcase
|
14
|
+
return hash[hash_key]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Rack #:nodoc:
|
23
|
+
|
24
|
+
# Rack Middleware for integrating OAuth into your application
|
25
|
+
#
|
26
|
+
# Note: this *requires* that a Rack::Session middleware be enabled
|
27
|
+
#
|
28
|
+
class OAuth
|
29
|
+
|
30
|
+
# Helper methods intended to be included in your Rails controller or
|
31
|
+
# in your Sinatra helpers block
|
32
|
+
module Methods
|
33
|
+
|
34
|
+
# [Internal] this method returns the Rack 'env' for the current request.
|
35
|
+
#
|
36
|
+
# This looks for #env or #request.env by default. If these don't return
|
37
|
+
# something, then we raise an exception and you should override this method
|
38
|
+
# so it returns the Rack env that we need.
|
39
|
+
def oauth_request_env
|
40
|
+
if respond_to?(:env)
|
41
|
+
env
|
42
|
+
elsif respond_to?(:request) and request.respond_to?(:env)
|
43
|
+
request.env
|
44
|
+
else
|
45
|
+
raise "Couldn't find 'env' ... please override #oauth_request_env"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the instance of Rack::OAuth given a name (defaults to the default Rack::OAuth name)
|
50
|
+
def oauth name = nil
|
51
|
+
oauth = Rack::OAuth.get(oauth_request_env, nil)
|
52
|
+
raise "Couldn't find Rack::OAuth instance with name #{ name }" unless oauth
|
53
|
+
oauth
|
54
|
+
end
|
55
|
+
|
56
|
+
# Makes a request using the stored access token for the current session.
|
57
|
+
#
|
58
|
+
# Without a user logged in to an OAuth provider in the current session, this won't work.
|
59
|
+
#
|
60
|
+
# This is *not* the method to use to fire off requests for saved access tokens.
|
61
|
+
def oauth_request *args
|
62
|
+
oauth.request oauth_request_env, *args
|
63
|
+
end
|
64
|
+
|
65
|
+
def oauth_request_with_access_token token, *args
|
66
|
+
oauth.request_with_access_token token, *args
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get the access token object for the currently authorized session
|
70
|
+
def oauth_access_token name = nil
|
71
|
+
oauth(name).get_access_token(oauth_request_env)
|
72
|
+
end
|
73
|
+
|
74
|
+
# If Rack::OAuth#get_access_token is nil given the #oauth_request_env available
|
75
|
+
# (inotherwords, it's nil in our user's current session), then we didn't
|
76
|
+
# log in. If we have an access token for this particular session, then
|
77
|
+
# we are logged in.
|
78
|
+
def logged_in? name = nil
|
79
|
+
!! oauth_access_token(name)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the path to rediret to for logging in via OAuth
|
83
|
+
def oauth_login_path name = nil
|
84
|
+
oauth(name).login_path
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
class << self
|
90
|
+
|
91
|
+
# The name we use for Rack::OAuth instances when a name is not given.
|
92
|
+
#
|
93
|
+
# This is 'default' by default
|
94
|
+
attr_accessor :default_instance_name
|
95
|
+
|
96
|
+
# Set this equal to true to enable 'test mode'
|
97
|
+
attr_accessor :test_mode_enabled
|
98
|
+
def enable_test_mode() self.test_mode_enabled = true end
|
99
|
+
def disable_test_mode() self.test_mode_enabled = false end
|
100
|
+
def test_mode?() test_mode_enabled == true end
|
101
|
+
end
|
102
|
+
|
103
|
+
@default_instance_name = 'default'
|
104
|
+
|
105
|
+
# Returns all of the Rack::OAuth instances found in this Rack 'env' Hash
|
106
|
+
def self.all env
|
107
|
+
env['rack.oauth']
|
108
|
+
end
|
109
|
+
|
110
|
+
# Simple helper to get an instance of Rack::OAuth by name found in this Rack 'env' Hash
|
111
|
+
def self.get env, name = nil
|
112
|
+
name = Rack::OAuth.default_instance_name if name.nil?
|
113
|
+
all(env)[name.to_s]
|
114
|
+
end
|
115
|
+
|
116
|
+
DEFAULT_OPTIONS = {
|
117
|
+
:login_path => '/oauth_login',
|
118
|
+
:callback_path => '/oauth_callback',
|
119
|
+
:redirect_to => '/oauth_complete',
|
120
|
+
:rack_session => 'rack.session',
|
121
|
+
:json_parser => lambda {|json_string| require 'json'; JSON.parse(json_string); },
|
122
|
+
:access_token_getter => lambda {|key, oauth| oauth.get_access_token_via_instance_variable(key) },
|
123
|
+
:access_token_setter => lambda {|key, token, oauth| oauth.set_access_token_via_instance_variable(key, token) }
|
124
|
+
}
|
125
|
+
|
126
|
+
# A proc that accepts an argument for the KEY we're using to get an access token
|
127
|
+
# that should return the actual access token object.
|
128
|
+
#
|
129
|
+
# A second parameter is passed to your block with the Rack::OAuth instance
|
130
|
+
#
|
131
|
+
# This allows you to override how access tokens are persisted
|
132
|
+
attr_accessor :access_token_getter
|
133
|
+
alias get access_token_getter
|
134
|
+
alias get= access_token_getter=
|
135
|
+
|
136
|
+
# A proc that accepts an argument for the KEY we're using to set an access token
|
137
|
+
# and a second argument with the actual access token object.
|
138
|
+
#
|
139
|
+
# A third parameter is passed to your block with the Rack::OAuth instance
|
140
|
+
#
|
141
|
+
# This allows you to override how access tokens are persisted
|
142
|
+
attr_accessor :access_token_setter
|
143
|
+
alias set access_token_setter
|
144
|
+
alias set= access_token_setter=
|
145
|
+
|
146
|
+
# the URL that should initiate OAuth and redirect to the OAuth provider's login page
|
147
|
+
def login_path
|
148
|
+
::File.join *[@login_path.to_s, name_unless_default].compact
|
149
|
+
end
|
150
|
+
attr_writer :login_path
|
151
|
+
alias login login_path
|
152
|
+
alias login= login_path=
|
153
|
+
|
154
|
+
# the URL that the OAuth provider should callback to after OAuth login is complete
|
155
|
+
def callback_path
|
156
|
+
::File.join *[@callback_path.to_s, name_unless_default].compact
|
157
|
+
end
|
158
|
+
attr_writer :callback_path
|
159
|
+
alias callback callback_path
|
160
|
+
alias callback= callback_path=
|
161
|
+
|
162
|
+
# the URL that Rack::OAuth should redirect to after the OAuth has been completed (part of your app)
|
163
|
+
attr_accessor :redirect_to
|
164
|
+
alias redirect redirect_to
|
165
|
+
alias redirect= redirect_to=
|
166
|
+
|
167
|
+
# the name of the Rack env variable used for the session
|
168
|
+
attr_accessor :rack_session
|
169
|
+
|
170
|
+
# [required] Your OAuth consumer key
|
171
|
+
attr_accessor :consumer_key
|
172
|
+
alias key consumer_key
|
173
|
+
alias key= consumer_key=
|
174
|
+
|
175
|
+
# [required] Your OAuth consumer secret
|
176
|
+
attr_accessor :consumer_secret
|
177
|
+
alias secret consumer_secret
|
178
|
+
alias secret= consumer_secret=
|
179
|
+
|
180
|
+
# [required] The site you want to request OAuth for, eg. 'http://twitter.com'
|
181
|
+
attr_accessor :consumer_site
|
182
|
+
alias site consumer_site
|
183
|
+
alias site= consumer_site=
|
184
|
+
|
185
|
+
# a Proc that accepts a JSON string and returns a Ruby object. Defaults to using the 'json' gem, if available.
|
186
|
+
attr_accessor :json_parser
|
187
|
+
|
188
|
+
# an arbitrary name for this instance of Rack::OAuth
|
189
|
+
def name
|
190
|
+
@name.to_s
|
191
|
+
end
|
192
|
+
attr_writer :name
|
193
|
+
|
194
|
+
def initialize app, *args
|
195
|
+
@app = app
|
196
|
+
|
197
|
+
options = args.pop
|
198
|
+
@name = args.first || Rack::OAuth.default_instance_name
|
199
|
+
|
200
|
+
DEFAULT_OPTIONS.each {|name, value| send "#{name}=", value }
|
201
|
+
options.each {|name, value| send "#{name}=", value } if options
|
202
|
+
|
203
|
+
raise_validation_exception unless valid?
|
204
|
+
end
|
205
|
+
|
206
|
+
def call env
|
207
|
+
env['rack.oauth'] ||= {}
|
208
|
+
env['rack.oauth'][name] = self
|
209
|
+
|
210
|
+
case env['PATH_INFO']
|
211
|
+
when login_path; do_login env
|
212
|
+
when callback_path; do_callback env
|
213
|
+
else; @app.call env
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def do_login env
|
218
|
+
|
219
|
+
if Rack::OAuth.test_mode?
|
220
|
+
session(env)[:token] = "Token"
|
221
|
+
session(env)[:secret] = "Secret"
|
222
|
+
set_access_token env, "AccessToken"
|
223
|
+
return [ 302, { 'Content-Type' => 'text/html', 'Location' => redirect_to }, [] ]
|
224
|
+
end
|
225
|
+
|
226
|
+
request = consumer.get_request_token :oauth_callback => ::File.join("http://#{ env['HTTP_HOST'] }", callback_path)
|
227
|
+
session(env)[:token] = request.token
|
228
|
+
session(env)[:secret] = request.secret
|
229
|
+
[ 302, { 'Content-Type' => 'text/html', 'Location' => request.authorize_url }, [] ]
|
230
|
+
end
|
231
|
+
|
232
|
+
def do_callback env
|
233
|
+
session(env)[:verifier] = Rack::Request.new(env).params['oauth_verifier']
|
234
|
+
request = ::OAuth::RequestToken.new consumer, session(env)[:token], session(env)[:secret]
|
235
|
+
access = request.get_access_token :oauth_verifier => session(env)[:verifier]
|
236
|
+
|
237
|
+
# hold onto the access token
|
238
|
+
set_access_token env, access
|
239
|
+
|
240
|
+
[ 302, { 'Content-Type' => 'text/html', 'Location' => redirect_to }, [] ]
|
241
|
+
end
|
242
|
+
|
243
|
+
# Default implementation of access_token_getter
|
244
|
+
#
|
245
|
+
# Keeps tokens in an instance variable
|
246
|
+
def get_access_token_via_instance_variable key
|
247
|
+
@tokens[key] if @tokens
|
248
|
+
end
|
249
|
+
|
250
|
+
# Default implementation of access_token_setter
|
251
|
+
#
|
252
|
+
# Keeps tokens in an instance variable
|
253
|
+
def set_access_token_via_instance_variable key, token
|
254
|
+
@tokens ||= {}
|
255
|
+
@tokens[key] = token
|
256
|
+
end
|
257
|
+
|
258
|
+
# Returns the key to use (for this particular session) to get or set an
|
259
|
+
# access token for this Rack env
|
260
|
+
#
|
261
|
+
# TODO this will very likely change as we want to be able to get or set
|
262
|
+
# access tokens using useful data like a user's name in the future
|
263
|
+
def key_for_env env
|
264
|
+
val = session(env)[:token] + session(env)[:secret] if session(env)[:token] and session(env)[:secret]
|
265
|
+
session(env)[:token] + session(env)[:secret] if session(env)[:token] and session(env)[:secret]
|
266
|
+
end
|
267
|
+
|
268
|
+
# Gets an Access Token by key using access_token_getter (for this specific ENV)
|
269
|
+
def get_access_token env
|
270
|
+
access_token_getter.call key_for_env(env), self
|
271
|
+
end
|
272
|
+
|
273
|
+
# Sets an Access Token by key and value using access_token_setter (for this specific ENV)
|
274
|
+
def set_access_token env, token
|
275
|
+
access_token_setter.call key_for_env(env), token, self
|
276
|
+
end
|
277
|
+
|
278
|
+
# Usage:
|
279
|
+
#
|
280
|
+
# request '/account/verify_credentials.json'
|
281
|
+
# request 'GET', '/account/verify_credentials.json'
|
282
|
+
# request :post, '/statuses/update.json', :status => params[:tweet]
|
283
|
+
#
|
284
|
+
def request env, method, path = nil, *args
|
285
|
+
if method.to_s.start_with?('/')
|
286
|
+
path = method
|
287
|
+
method = :get
|
288
|
+
end
|
289
|
+
|
290
|
+
return Rack::OAuth.mock_response_for(method, path) if Rack::OAuth.test_mode?
|
291
|
+
|
292
|
+
consumer.request method.to_s.downcase.to_sym, path, get_access_token(env), *args
|
293
|
+
end
|
294
|
+
|
295
|
+
# Same as #request but you can manually pass your own request token
|
296
|
+
def request_with_access_token token, method, path = nil, *args
|
297
|
+
if method.to_s.start_with?('/')
|
298
|
+
path = method
|
299
|
+
method = :get
|
300
|
+
end
|
301
|
+
|
302
|
+
return Rack::OAuth.mock_response_for(method, path) if Rack::OAuth.test_mode?
|
303
|
+
|
304
|
+
consumer.request method.to_s.downcase.to_sym, path, token, *args
|
305
|
+
end
|
306
|
+
|
307
|
+
# Returns the mock response, if one has been set via #mock_request, for a method and path.
|
308
|
+
#
|
309
|
+
# Raises an exception if the response doesn't exist because we never want the test environment
|
310
|
+
# to *actually* make real requests!
|
311
|
+
def self.mock_response_for method, path
|
312
|
+
unless @mock_responses and @mock_responses[path] and @mock_responses[path][method]
|
313
|
+
raise "No mock response created for #{ method.inspect } #{ path.inspect }"
|
314
|
+
else
|
315
|
+
return @mock_responses[path][method]
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# Set the response that should be returned when a particular method and path are called.
|
320
|
+
#
|
321
|
+
# This is used when Rack::OAuth::test_mode? is true
|
322
|
+
def self.mock_request method, path, response = nil
|
323
|
+
if method.to_s.start_with?('/')
|
324
|
+
response = path
|
325
|
+
path = method
|
326
|
+
method = :get
|
327
|
+
end
|
328
|
+
|
329
|
+
@mock_responses ||= {}
|
330
|
+
@mock_responses[path] ||= {}
|
331
|
+
@mock_responses[path][method] = response
|
332
|
+
end
|
333
|
+
|
334
|
+
def verified? env
|
335
|
+
[ :token, :secret, :verifier ].all? { |required_session_key| session(env)[required_session_key] }
|
336
|
+
end
|
337
|
+
|
338
|
+
def consumer
|
339
|
+
@consumer ||= ::OAuth::Consumer.new consumer_key, consumer_secret, :site => consumer_site
|
340
|
+
end
|
341
|
+
|
342
|
+
def valid?
|
343
|
+
@errors = []
|
344
|
+
@errors << ":consumer_key option is required" unless consumer_key
|
345
|
+
@errors << ":consumer_secret option is required" unless consumer_secret
|
346
|
+
@errors << ":consumer_site option is required" unless consumer_site
|
347
|
+
@errors.empty?
|
348
|
+
end
|
349
|
+
|
350
|
+
def raise_validation_exception
|
351
|
+
raise @errors.join(', ')
|
352
|
+
end
|
353
|
+
|
354
|
+
# Returns a hash of session variables, specific to this instance of Rack::OAuth and the end-user
|
355
|
+
#
|
356
|
+
# All user-specific variables are stored in the session.
|
357
|
+
#
|
358
|
+
# The variables we currently keep track of are:
|
359
|
+
# - token
|
360
|
+
# - secret
|
361
|
+
# - verifier
|
362
|
+
#
|
363
|
+
# With all three of these, we can make arbitrary requests to our OAuth provider for this user.
|
364
|
+
def session env
|
365
|
+
raise "Rack env['rack.session'] is nil ... has a Rack::Session middleware be enabled? " +
|
366
|
+
"use :rack_session for custom key" if env[rack_session].nil?
|
367
|
+
env[rack_session]['rack.oauth'] ||= {}
|
368
|
+
env[rack_session]['rack.oauth'][name] ||= {}
|
369
|
+
end
|
370
|
+
|
371
|
+
# Returns the #name of this Rack::OAuth unless the name is 'default', in which case it returns nil
|
372
|
+
def name_unless_default
|
373
|
+
name == Rack::OAuth.default_instance_name ? nil : name
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:OAuth::AccessToken
|
2
|
+
consumer: !ruby/object:OAuth::Consumer
|
3
|
+
http: !ruby/object:Net::HTTP
|
4
|
+
address: twitter.com
|
5
|
+
close_on_empty_response: false
|
6
|
+
curr_http_version: "1.1"
|
7
|
+
debug_output:
|
8
|
+
newimpl: true
|
9
|
+
open_timeout:
|
10
|
+
port: 80
|
11
|
+
read_timeout: 60
|
12
|
+
seems_1_0_server: false
|
13
|
+
socket:
|
14
|
+
ssl_context: !ruby/object:OpenSSL::SSL::SSLContext
|
15
|
+
ca_file: /etc/ssl/certs/ca-certificates.crt
|
16
|
+
ca_path:
|
17
|
+
cert:
|
18
|
+
cert_store:
|
19
|
+
client_ca:
|
20
|
+
client_cert_cb:
|
21
|
+
extra_chain_cert:
|
22
|
+
key:
|
23
|
+
options:
|
24
|
+
session_get_cb:
|
25
|
+
session_id_context:
|
26
|
+
session_new_cb:
|
27
|
+
session_remove_cb:
|
28
|
+
timeout:
|
29
|
+
tmp_dh_callback:
|
30
|
+
verify_callback:
|
31
|
+
verify_depth: 5
|
32
|
+
verify_mode: 1
|
33
|
+
started: false
|
34
|
+
use_ssl: false
|
35
|
+
http_method: :post
|
36
|
+
key: 4JjFmhjfZyQ6rdbiql5A
|
37
|
+
options:
|
38
|
+
:http_method: :post
|
39
|
+
:scheme: :header
|
40
|
+
:oauth_version: "1.0"
|
41
|
+
:proxy:
|
42
|
+
:request_token_path: /oauth/request_token
|
43
|
+
:authorize_path: /oauth/authorize
|
44
|
+
:site: http://twitter.com
|
45
|
+
:signature_method: HMAC-SHA1
|
46
|
+
:access_token_path: /oauth/access_token
|
47
|
+
secret: rv4ZaCgvxVPVjxHIDbMxTGFbIMxUa4KkIdPqL7HmaQo
|
48
|
+
params:
|
49
|
+
oauth_token_secret: K7Z5LHyweHKd3rPaaiHMUCaYQyAC0suWQcOPGfM
|
50
|
+
:user_id: "11043342"
|
51
|
+
user_id: "11043342"
|
52
|
+
:oauth_token_secret: K7Z5LHyweHKd3rPaaiHMUCaYQyAC0suWQcOPGfM
|
53
|
+
:screen_name: remitaylor
|
54
|
+
oauth_token: 11043342-rH2Rdn9AcLzVBIL3cnQqCJ96mb0Zp2XC56Qx4bsMB
|
55
|
+
:oauth_token: 11043342-rH2Rdn9AcLzVBIL3cnQqCJ96mb0Zp2XC56Qx4bsMB
|
56
|
+
screen_name: remitaylor
|
57
|
+
secret: K7Z5LHyweHKd3rPaaiHMUCaYQyAC0suWQcOPGfM
|
58
|
+
token: 11043342-rH2Rdn9AcLzVBIL3cnQqCJ96mb0Zp2XC56Qx4bsMB
|
@@ -0,0 +1 @@
|
|
1
|
+
--- sCJz6SHIaQAUtAj4FOmTwwwpruV3fsGAWsrH3ynqQ
|
@@ -0,0 +1 @@
|
|
1
|
+
--- XnS8UEe2l4iKAYqPBFhQ0wfI0s3i2nLE1RjnC1CbA
|
@@ -0,0 +1 @@
|
|
1
|
+
--- 6dhuchM6Wzh9PpNv0KGB0h3AxzHLZ2Vy9erSJsOAv4
|
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:OAuth::RequestToken
|
2
|
+
consumer: !ruby/object:OAuth::Consumer
|
3
|
+
http: !ruby/object:Net::HTTP
|
4
|
+
address: twitter.com
|
5
|
+
close_on_empty_response: false
|
6
|
+
curr_http_version: "1.1"
|
7
|
+
debug_output:
|
8
|
+
newimpl: true
|
9
|
+
open_timeout:
|
10
|
+
port: 80
|
11
|
+
read_timeout: 60
|
12
|
+
seems_1_0_server: false
|
13
|
+
socket:
|
14
|
+
ssl_context: !ruby/object:OpenSSL::SSL::SSLContext
|
15
|
+
ca_file: /etc/ssl/certs/ca-certificates.crt
|
16
|
+
ca_path:
|
17
|
+
cert:
|
18
|
+
cert_store:
|
19
|
+
client_ca:
|
20
|
+
client_cert_cb:
|
21
|
+
extra_chain_cert:
|
22
|
+
key:
|
23
|
+
options:
|
24
|
+
session_get_cb:
|
25
|
+
session_id_context:
|
26
|
+
session_new_cb:
|
27
|
+
session_remove_cb:
|
28
|
+
timeout:
|
29
|
+
tmp_dh_callback:
|
30
|
+
verify_callback:
|
31
|
+
verify_depth: 5
|
32
|
+
verify_mode: 1
|
33
|
+
started: false
|
34
|
+
use_ssl: false
|
35
|
+
http_method: :post
|
36
|
+
key: 4JjFmhjfZyQ6rdbiql5A
|
37
|
+
options:
|
38
|
+
:http_method: :post
|
39
|
+
:scheme: :header
|
40
|
+
:oauth_version: "1.0"
|
41
|
+
:proxy:
|
42
|
+
:request_token_path: /oauth/request_token
|
43
|
+
:authorize_path: AUTH_PATH
|
44
|
+
:site: http://twitter.com
|
45
|
+
:signature_method: HMAC-SHA1
|
46
|
+
:access_token_path: /oauth/access_token
|
47
|
+
secret: rv4ZaCgvxVPVjxHIDbMxTGFbIMxUa4KkIdPqL7HmaQo
|
48
|
+
params:
|
49
|
+
oauth_callback_confirmed: "true"
|
50
|
+
oauth_token_secret: XnS8UEe2l4iKAYqPBFhQ0wfI0s3i2nLE1RjnC1CbA
|
51
|
+
:oauth_callback_confirmed: "true"
|
52
|
+
:oauth_token_secret: XnS8UEe2l4iKAYqPBFhQ0wfI0s3i2nLE1RjnC1CbA
|
53
|
+
oauth_token: 6dhuchM6Wzh9PpNv0KGB0h3AxzHLZ2Vy9erSJsOAv4
|
54
|
+
:oauth_token: 6dhuchM6Wzh9PpNv0KGB0h3AxzHLZ2Vy9erSJsOAv4
|
55
|
+
secret: XnS8UEe2l4iKAYqPBFhQ0wfI0s3i2nLE1RjnC1CbA
|
56
|
+
token: 6dhuchM6Wzh9PpNv0KGB0h3AxzHLZ2Vy9erSJsOAv4
|