rack-oauth 0.1.2 → 0.1.3
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.
- data/README.rdoc +13 -10
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/examples/rails-example/app/controllers/application_controller.rb +6 -0
- data/examples/rails-example/app/controllers/welcome_controller.rb +1 -4
- data/examples/rails-example/config/environment.rb +3 -1
- data/examples/rails-example/config/environments/test.rb +1 -0
- data/examples/rails-example/log/development.log +76 -0
- data/examples/rails-example/log/test.log +159 -0
- data/examples/rails-example/spec/integration/login_spec.rb +2 -12
- data/examples/rails-example/spec/spec_helper.rb +4 -0
- data/examples/rails-example/tmp/webrat-1257219890.html +211 -0
- data/examples/rails-example/tmp/webrat-1257219947.html +213 -0
- data/examples/rails-example/tmp/webrat-1257219957.html +213 -0
- data/examples/sinatra-twitter.rb +5 -22
- data/lib/rack-oauth.rb +49 -110
- data/spec/sample_sinatra_app_spec.rb +11 -40
- metadata +25 -3
data/lib/rack-oauth.rb
CHANGED
@@ -30,6 +30,17 @@ module Rack #:nodoc:
|
|
30
30
|
# Helper methods intended to be included in your Rails controller or
|
31
31
|
# in your Sinatra helpers block
|
32
32
|
module Methods
|
33
|
+
|
34
|
+
# This is *the* method you want to call.
|
35
|
+
#
|
36
|
+
# After you're authorized and redirected back to your #redirect_to path,
|
37
|
+
# you should be able to call get_access_token to get and hold onto
|
38
|
+
# the access token for the user you've been authorized as.
|
39
|
+
#
|
40
|
+
# You can use the token to make GET/POST/etc requests
|
41
|
+
def get_access_token name = nil
|
42
|
+
oauth(name).get_access_token(oauth_request_env)
|
43
|
+
end
|
33
44
|
|
34
45
|
# [Internal] this method returns the Rack 'env' for the current request.
|
35
46
|
#
|
@@ -53,32 +64,6 @@ module Rack #:nodoc:
|
|
53
64
|
oauth
|
54
65
|
end
|
55
66
|
|
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
67
|
# Returns the path to rediret to for logging in via OAuth
|
83
68
|
def oauth_login_path name = nil
|
84
69
|
oauth(name).login_path
|
@@ -117,32 +102,9 @@ module Rack #:nodoc:
|
|
117
102
|
:login_path => '/oauth_login',
|
118
103
|
:callback_path => '/oauth_callback',
|
119
104
|
: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) }
|
105
|
+
:rack_session => 'rack.session'
|
124
106
|
}
|
125
107
|
|
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
108
|
# the URL that should initiate OAuth and redirect to the OAuth provider's login page
|
147
109
|
def login_path
|
148
110
|
::File.join *[@login_path.to_s, name_unless_default].compact
|
@@ -182,9 +144,6 @@ module Rack #:nodoc:
|
|
182
144
|
alias site consumer_site
|
183
145
|
alias site= consumer_site=
|
184
146
|
|
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
147
|
# an arbitrary name for this instance of Rack::OAuth
|
189
148
|
def name
|
190
149
|
@name.to_s
|
@@ -204,96 +163,76 @@ module Rack #:nodoc:
|
|
204
163
|
end
|
205
164
|
|
206
165
|
def call env
|
166
|
+
# put this instance of Rack::OAuth in the env
|
167
|
+
# so it's accessible from the application
|
207
168
|
env['rack.oauth'] ||= {}
|
208
169
|
env['rack.oauth'][name] = self
|
209
170
|
|
210
171
|
case env['PATH_INFO']
|
211
|
-
|
212
|
-
|
213
|
-
|
172
|
+
|
173
|
+
# find out where to redirect to authorize for this oauth provider
|
174
|
+
# and redirect there. when the authorization is finished,
|
175
|
+
# the provider will redirect back to our application's callback path
|
176
|
+
when login_path
|
177
|
+
do_login(env)
|
178
|
+
|
179
|
+
# the oauth provider has redirected back to us! we should have a
|
180
|
+
# verifier now that we can use, in combination with out token and
|
181
|
+
# secret, to get an access token for this user
|
182
|
+
when callback_path
|
183
|
+
do_callback(env)
|
184
|
+
|
185
|
+
else
|
186
|
+
@app.call(env)
|
214
187
|
end
|
215
188
|
end
|
216
189
|
|
217
190
|
def do_login env
|
218
|
-
|
219
191
|
if Rack::OAuth.test_mode?
|
220
|
-
|
221
|
-
session(env)[:secret] = "Secret"
|
222
|
-
set_access_token env, "AccessToken"
|
192
|
+
set_access_token env, OpenStruct.new(:params => { 'I am a' => 'fake token' })
|
223
193
|
return [ 302, { 'Content-Type' => 'text/html', 'Location' => redirect_to }, [] ]
|
224
194
|
end
|
225
195
|
|
196
|
+
# get request token and hold onto the token/secret (which we need later to get the access token)
|
226
197
|
request = consumer.get_request_token :oauth_callback => ::File.join("http://#{ env['HTTP_HOST'] }", callback_path)
|
227
198
|
session(env)[:token] = request.token
|
228
199
|
session(env)[:secret] = request.secret
|
200
|
+
|
201
|
+
# redirect to the oauth provider's authorize url to authorize the user
|
229
202
|
[ 302, { 'Content-Type' => 'text/html', 'Location' => request.authorize_url }, [] ]
|
230
203
|
end
|
231
204
|
|
232
205
|
def do_callback env
|
233
|
-
session
|
206
|
+
# get access token and persist it in the session in a way that we can get it back out later
|
234
207
|
request = ::OAuth::RequestToken.new consumer, session(env)[:token], session(env)[:secret]
|
235
|
-
|
208
|
+
set_access_token env, request.get_access_token(:oauth_verifier => Rack::Request.new(env).params['oauth_verifier'])
|
236
209
|
|
237
|
-
#
|
238
|
-
|
210
|
+
# clear out the session variables (won't need these anymore)
|
211
|
+
session(env).delete(:token)
|
212
|
+
session(env).delete(:secret)
|
239
213
|
|
214
|
+
# we have an access token now ... redirect back to the user's application
|
240
215
|
[ 302, { 'Content-Type' => 'text/html', 'Location' => redirect_to }, [] ]
|
241
216
|
end
|
242
217
|
|
243
|
-
#
|
244
|
-
|
245
|
-
|
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]
|
218
|
+
# Stores the access token in this env's session in a way that we can get it back out via #get_access_token(env)
|
219
|
+
def set_access_token env, token
|
220
|
+
session(env)[:access_token_params] = token.params
|
266
221
|
end
|
267
222
|
|
268
|
-
#
|
223
|
+
# See #set_access_token
|
269
224
|
def get_access_token env
|
270
|
-
|
271
|
-
|
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
|
225
|
+
params = session(env)[:access_token_params]
|
226
|
+
::OAuth::AccessToken.from_hash consumer, params if params
|
276
227
|
end
|
277
228
|
|
278
229
|
# Usage:
|
279
230
|
#
|
280
|
-
# request '/account/verify_credentials.json'
|
281
|
-
# request 'GET', '/account/verify_credentials.json'
|
282
|
-
# request :post, '/statuses/update.json', :status => params[:tweet]
|
231
|
+
# request @token, '/account/verify_credentials.json'
|
232
|
+
# request @token, 'GET', '/account/verify_credentials.json'
|
233
|
+
# request @token, :post, '/statuses/update.json', :status => params[:tweet]
|
283
234
|
#
|
284
|
-
def request
|
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
|
235
|
+
def request token, method, path = nil, *args
|
297
236
|
if method.to_s.start_with?('/')
|
298
237
|
path = method
|
299
238
|
method = :get
|
@@ -1,30 +1,26 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
+
require 'fakeweb'
|
4
|
+
FakeWeb.allow_net_connect = false
|
5
|
+
FakeWeb.register_uri :get, 'http://twitter.com/account/verify_credentials.json', :body => %{{"friends_count":190,"utc_offset":-28800,"profile_sidebar_border_color":"829D5E","status":{"in_reply_to_screen_name":null,"text":"Come on people, don't you realize that smoking isn't cool anymore? Try a healthier stimulant. Maybe one that doesn't irritate my sinuses?","in_reply_to_user_id":null,"in_reply_to_status_id":null,"source":"web","truncated":false,"favorited":false,"id":5177704516,"created_at":"Mon Oct 26 17:15:10 +0000 2009"},"notifications":false,"statuses_count":1689,"time_zone":"Pacific Time (US & Canada)","verified":false,"profile_text_color":"3E4415","profile_image_url":"http://a3.twimg.com/profile_images/54765389/remi-rock-on_bak_normal.png","profile_background_image_url":"http://s.twimg.com/a/1256577591/images/themes/theme5/bg.gif","location":"Phoenix, AZ","following":false,"favourites_count":0,"profile_link_color":"D02B55","screen_name":"THE_REAL_SHAQ","geo_enabled":false,"profile_background_tile":false,"protected":false,"profile_background_color":"352726","name":"THE_REAL_SHAQ","followers_count":255,"url":"http://remi.org","id":11043342,"created_at":"Tue Dec 11 09:13:43 +0000 2007","profile_sidebar_fill_color":"99CC33","description":"Beer goes in, Code comes out"}}
|
6
|
+
|
3
7
|
require 'json'
|
4
8
|
require 'sinatra/base'
|
5
9
|
class SampleSinatraApp < Sinatra::Base
|
6
10
|
|
7
|
-
# this is hardcore optional ... if you want to override where ALL tokens are persisted, you can do this ...
|
8
|
-
|
9
|
-
def self.get_token key, oauth
|
10
|
-
@tokens[key] if @tokens
|
11
|
-
end
|
12
|
-
def self.set_token key, token, oauth
|
13
|
-
@tokens ||= {}
|
14
|
-
@tokens[key] = token
|
15
|
-
end
|
16
|
-
|
17
11
|
use Rack::Session::Cookie
|
18
12
|
use Rack::OAuth, :site => 'http://twitter.com',
|
19
13
|
:key => '4JjFmhjfZyQ6rdbiql5A',
|
20
|
-
:secret => 'rv4ZaCgvxVPVjxHIDbMxTGFbIMxUa4KkIdPqL7HmaQo'
|
21
|
-
:get => method(:get_token),
|
22
|
-
:set => method(:set_token)
|
14
|
+
:secret => 'rv4ZaCgvxVPVjxHIDbMxTGFbIMxUa4KkIdPqL7HmaQo'
|
23
15
|
|
24
16
|
enable :raise_errors
|
25
17
|
|
26
18
|
helpers do
|
27
19
|
include Rack::OAuth::Methods
|
20
|
+
|
21
|
+
def logged_in?
|
22
|
+
get_access_token.present?
|
23
|
+
end
|
28
24
|
end
|
29
25
|
|
30
26
|
get '/' do
|
@@ -36,13 +32,12 @@ class SampleSinatraApp < Sinatra::Base
|
|
36
32
|
end
|
37
33
|
|
38
34
|
get '/oauth_complete' do
|
39
|
-
info = JSON.parse
|
35
|
+
info = JSON.parse get_access_token.get('/account/verify_credentials.json').body
|
40
36
|
name = info['screen_name']
|
41
|
-
$access_tokens[name] = oauth_access_token
|
42
37
|
end
|
43
38
|
|
44
39
|
get '/get_user_info' do
|
45
|
-
info = JSON.parse
|
40
|
+
info = JSON.parse get_access_token.get('/account/verify_credentials.json').body
|
46
41
|
end
|
47
42
|
end
|
48
43
|
|
@@ -78,28 +73,4 @@ describe SampleSinatraApp do
|
|
78
73
|
request('/').body.should include('Hello World')
|
79
74
|
end
|
80
75
|
|
81
|
-
it 'should be able to specify a mock response for an arbitrary authorized response' do
|
82
|
-
request('/oauth_login') # login
|
83
|
-
|
84
|
-
# if we don't mock the request, it should blow up
|
85
|
-
lambda { request('/get_user_info') }.should raise_error
|
86
|
-
|
87
|
-
Rack::OAuth.mock_request '/account/verify_credentials.json', example_json
|
88
|
-
|
89
|
-
request('/get_user_info').body.should include('remitaylor')
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'should be able to persist access token by some arbitrary value like twitter screen_name' do
|
93
|
-
$access_tokens ||= {}
|
94
|
-
request('/oauth_login').status.should == 302
|
95
|
-
|
96
|
-
# token should be nil
|
97
|
-
$access_tokens['remitaylor'].should be_nil
|
98
|
-
|
99
|
-
request('/oauth_complete')
|
100
|
-
|
101
|
-
# token should not be nil because the oauth_complete goes and gets and persists it
|
102
|
-
$access_tokens['remitaylor'].should_not be_nil
|
103
|
-
end
|
104
|
-
|
105
76
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-oauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- remi
|
@@ -11,8 +11,27 @@ cert_chain: []
|
|
11
11
|
|
12
12
|
date: 2009-11-02 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: oauth
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
16
35
|
description: Rack Middleware for OAuth Authorization
|
17
36
|
email: remi@remitaylor.com
|
18
37
|
executables: []
|
@@ -97,6 +116,9 @@ files:
|
|
97
116
|
- examples/rails-example/tmp/webrat-1257210581.html
|
98
117
|
- examples/rails-example/tmp/webrat-1257210600.html
|
99
118
|
- examples/rails-example/tmp/webrat-1257210608.html
|
119
|
+
- examples/rails-example/tmp/webrat-1257219890.html
|
120
|
+
- examples/rails-example/tmp/webrat-1257219947.html
|
121
|
+
- examples/rails-example/tmp/webrat-1257219957.html
|
100
122
|
- examples/sinatra-twitter.rb
|
101
123
|
- examples/sinatra-twitter.ru
|
102
124
|
- lib/rack-oauth.rb
|