omniauth-facebook 1.4.0 → 1.4.1
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.
Potentially problematic release.
This version of omniauth-facebook might be problematic. Click here for more details.
- data/Rakefile +5 -3
- data/example/Gemfile.lock +14 -9
- data/lib/omniauth/facebook/version.rb +1 -1
- data/lib/omniauth/strategies/facebook.rb +9 -1
- data/omniauth-facebook.gemspec +3 -2
- data/test/helper.rb +54 -0
- data/test/support/shared_examples.rb +85 -0
- data/test/test.rb +494 -0
- metadata +38 -17
- data/spec/omniauth/strategies/facebook_spec.rb +0 -507
- data/spec/spec_helper.rb +0 -6
- data/spec/support/shared_examples.rb +0 -42
data/Rakefile
CHANGED
data/example/Gemfile.lock
CHANGED
@@ -1,27 +1,32 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../
|
3
3
|
specs:
|
4
|
-
omniauth-facebook (1.
|
5
|
-
omniauth-oauth2 (~> 1.0
|
4
|
+
omniauth-facebook (1.4.0)
|
5
|
+
omniauth-oauth2 (~> 1.1.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
faraday (0.8.
|
10
|
+
faraday (0.8.1)
|
11
11
|
multipart-post (~> 1.1)
|
12
12
|
hashie (1.2.0)
|
13
13
|
httpauth (0.1)
|
14
|
-
|
14
|
+
json (1.7.3)
|
15
|
+
jwt (0.1.4)
|
16
|
+
json (>= 1.2.4)
|
17
|
+
multi_json (1.3.6)
|
15
18
|
multipart-post (1.1.5)
|
16
|
-
oauth2 (0.
|
17
|
-
faraday (~> 0.
|
19
|
+
oauth2 (0.8.0)
|
20
|
+
faraday (~> 0.8)
|
18
21
|
httpauth (~> 0.1)
|
19
|
-
|
22
|
+
jwt (~> 0.1.4)
|
23
|
+
multi_json (~> 1.0)
|
24
|
+
rack (~> 1.2)
|
20
25
|
omniauth (1.1.0)
|
21
26
|
hashie (~> 1.2)
|
22
27
|
rack
|
23
|
-
omniauth-oauth2 (1.0
|
24
|
-
oauth2 (~> 0.
|
28
|
+
omniauth-oauth2 (1.1.0)
|
29
|
+
oauth2 (~> 0.8.0)
|
25
30
|
omniauth (~> 1.0)
|
26
31
|
rack (1.4.1)
|
27
32
|
rack-protection (1.2.0)
|
@@ -120,7 +120,15 @@ module OmniAuth
|
|
120
120
|
#
|
121
121
|
def authorize_params
|
122
122
|
super.tap do |params|
|
123
|
-
%w[display state scope].each
|
123
|
+
%w[display state scope].each do |v|
|
124
|
+
if request.params[v]
|
125
|
+
params[v.to_sym] = request.params[v]
|
126
|
+
|
127
|
+
# to support omniauth-oauth2's auto csrf protection
|
128
|
+
session['omniauth.state'] = params[:state] if v == 'state'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
124
132
|
params[:scope] ||= DEFAULT_SCOPE
|
125
133
|
end
|
126
134
|
end
|
data/omniauth-facebook.gemspec
CHANGED
@@ -15,8 +15,9 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
16
16
|
s.require_paths = ['lib']
|
17
17
|
|
18
|
-
s.add_runtime_dependency 'omniauth-oauth2', '~> 1.0
|
18
|
+
s.add_runtime_dependency 'omniauth-oauth2', '~> 1.1.0'
|
19
19
|
|
20
|
-
s.add_development_dependency '
|
20
|
+
s.add_development_dependency 'minitest'
|
21
|
+
s.add_development_dependency 'mocha'
|
21
22
|
s.add_development_dependency 'rake'
|
22
23
|
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'mocha'
|
4
|
+
require 'omniauth/strategies/facebook'
|
5
|
+
|
6
|
+
OmniAuth.config.test_mode = true
|
7
|
+
|
8
|
+
module BlockTestHelper
|
9
|
+
def test(name, &blk)
|
10
|
+
method_name = "test_#{name.gsub(/\s+/, '_')}"
|
11
|
+
raise "Method already defined: #{method_name}" if instance_methods.include?(method_name.to_sym)
|
12
|
+
define_method method_name, &blk
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module CustomAssertions
|
17
|
+
def assert_has_key(key, hash, msg = nil)
|
18
|
+
msg = message(msg) { "Expected #{hash.inspect} to have key #{key.inspect}" }
|
19
|
+
assert hash.has_key?(key), msg
|
20
|
+
end
|
21
|
+
|
22
|
+
def refute_has_key(key, hash, msg = nil)
|
23
|
+
msg = message(msg) { "Expected #{hash.inspect} not to have key #{key.inspect}" }
|
24
|
+
refute hash.has_key?(key), msg
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class TestCase < MiniTest::Unit::TestCase
|
29
|
+
extend BlockTestHelper
|
30
|
+
include CustomAssertions
|
31
|
+
end
|
32
|
+
|
33
|
+
class StrategyTestCase < TestCase
|
34
|
+
def setup
|
35
|
+
@request = stub('Request')
|
36
|
+
@request.stubs(:params).returns({})
|
37
|
+
@request.stubs(:cookies).returns({})
|
38
|
+
@request.stubs(:env).returns({})
|
39
|
+
|
40
|
+
@client_id = '123'
|
41
|
+
@client_secret = '53cr3tz'
|
42
|
+
end
|
43
|
+
|
44
|
+
def strategy
|
45
|
+
@strategy ||= begin
|
46
|
+
args = [@client_id, @client_secret, @options].compact
|
47
|
+
OmniAuth::Strategies::Facebook.new(nil, *args).tap do |strategy|
|
48
|
+
strategy.stubs(:request).returns(@request)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Dir[File.expand_path('../support/**/*', __FILE__)].each &method(:require)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# NOTE it would be useful if this lived in omniauth-oauth2 eventually
|
2
|
+
module OAuth2StrategyTests
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
include ClientTests
|
6
|
+
include AuthorizeParamsTests
|
7
|
+
include CSRFAuthorizeParamsTests
|
8
|
+
include TokenParamsTests
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClientTests
|
13
|
+
extend BlockTestHelper
|
14
|
+
|
15
|
+
test 'should be initialized with symbolized client_options' do
|
16
|
+
@options = { :client_options => { 'authorize_url' => 'https://example.com' } }
|
17
|
+
assert_equal 'https://example.com', strategy.client.options[:authorize_url]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module AuthorizeParamsTests
|
22
|
+
extend BlockTestHelper
|
23
|
+
|
24
|
+
test 'should include any authorize params passed in the :authorize_params option' do
|
25
|
+
@options = { :authorize_params => { :foo => 'bar', :baz => 'zip' } }
|
26
|
+
assert_equal 'bar', strategy.authorize_params['foo']
|
27
|
+
assert_equal 'zip', strategy.authorize_params['baz']
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'should include top-level options that are marked as :authorize_options' do
|
31
|
+
@options = { :authorize_options => [:scope, :foo], :scope => 'bar', :foo => 'baz' }
|
32
|
+
assert_equal 'bar', strategy.authorize_params['scope']
|
33
|
+
assert_equal 'baz', strategy.authorize_params['foo']
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'should exclude top-level options that are not passed' do
|
37
|
+
@options = { :authorize_options => [:bar] }
|
38
|
+
refute_has_key :bar, strategy.authorize_params
|
39
|
+
refute_has_key 'bar', strategy.authorize_params
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module CSRFAuthorizeParamsTests
|
44
|
+
extend BlockTestHelper
|
45
|
+
|
46
|
+
test 'should store random state in the session when none is present in authorize or request params' do
|
47
|
+
assert_includes strategy.authorize_params.keys, 'state'
|
48
|
+
refute_empty strategy.authorize_params['state']
|
49
|
+
refute_empty strategy.session['omniauth.state']
|
50
|
+
assert_equal strategy.authorize_params['state'], strategy.session['omniauth.state']
|
51
|
+
end
|
52
|
+
|
53
|
+
test 'should store state in the session when present in authorize params vs. a random one' do
|
54
|
+
@options = { :authorize_params => { :state => 'bar' } }
|
55
|
+
refute_empty strategy.authorize_params['state']
|
56
|
+
assert_equal 'bar', strategy.authorize_params[:state]
|
57
|
+
refute_empty strategy.session['omniauth.state']
|
58
|
+
assert_equal 'bar', strategy.session['omniauth.state']
|
59
|
+
end
|
60
|
+
|
61
|
+
test 'should store state in the session when present in request params vs. a random one' do
|
62
|
+
@request.stubs(:params).returns({ 'state' => 'foo' })
|
63
|
+
refute_empty strategy.authorize_params['state']
|
64
|
+
assert_equal 'foo', strategy.authorize_params[:state]
|
65
|
+
refute_empty strategy.session['omniauth.state']
|
66
|
+
assert_equal 'foo', strategy.session['omniauth.state']
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module TokenParamsTests
|
71
|
+
extend BlockTestHelper
|
72
|
+
|
73
|
+
test 'should include any authorize params passed in the :token_params option' do
|
74
|
+
@options = { :token_params => { :foo => 'bar', :baz => 'zip' } }
|
75
|
+
assert_equal 'bar', strategy.token_params['foo']
|
76
|
+
assert_equal 'zip', strategy.token_params['baz']
|
77
|
+
end
|
78
|
+
|
79
|
+
test 'should include top-level options that are marked as :token_options' do
|
80
|
+
@options = { :token_options => [:scope, :foo], :scope => 'bar', :foo => 'baz' }
|
81
|
+
assert_equal 'bar', strategy.token_params['scope']
|
82
|
+
assert_equal 'baz', strategy.token_params['foo']
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/test/test.rb
ADDED
@@ -0,0 +1,494 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'omniauth-facebook'
|
3
|
+
require 'openssl'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
class StrategyTest < StrategyTestCase
|
7
|
+
include OAuth2StrategyTests
|
8
|
+
end
|
9
|
+
|
10
|
+
class ClientTest < StrategyTestCase
|
11
|
+
test 'has correct Facebook site' do
|
12
|
+
assert_equal 'https://graph.facebook.com', strategy.client.site
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'has correct authorize url' do
|
16
|
+
assert_equal '/oauth/authorize', strategy.client.options[:authorize_url]
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'has correct token url' do
|
20
|
+
assert_equal '/oauth/access_token', strategy.client.options[:token_url]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class CallbackUrlTest < StrategyTestCase
|
25
|
+
test "returns the default callback url" do
|
26
|
+
url_base = 'http://auth.request.com'
|
27
|
+
@request.stubs(:url).returns("#{url_base}/some/page")
|
28
|
+
strategy.stubs(:script_name).returns('') # as not to depend on Rack env
|
29
|
+
assert_equal "#{url_base}/auth/facebook/callback", strategy.callback_url
|
30
|
+
end
|
31
|
+
|
32
|
+
test "returns path from callback_path option" do
|
33
|
+
@options = { :callback_path => "/auth/FB/done"}
|
34
|
+
url_base = 'http://auth.request.com'
|
35
|
+
@request.stubs(:url).returns("#{url_base}/page/path")
|
36
|
+
strategy.stubs(:script_name).returns('') # as not to depend on Rack env
|
37
|
+
assert_equal "#{url_base}/auth/FB/done", strategy.callback_url
|
38
|
+
end
|
39
|
+
|
40
|
+
test "returns url from callback_url option" do
|
41
|
+
url = 'https://auth.myapp.com/auth/fb/callback'
|
42
|
+
@options = { :callback_url => url }
|
43
|
+
assert_equal url, strategy.callback_url
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class AuthorizeParamsTest < StrategyTestCase
|
48
|
+
test 'includes default scope for email' do
|
49
|
+
assert strategy.authorize_params.is_a?(Hash)
|
50
|
+
assert_equal 'email', strategy.authorize_params[:scope]
|
51
|
+
end
|
52
|
+
|
53
|
+
test 'includes display parameter from request when present' do
|
54
|
+
@request.stubs(:params).returns({ 'display' => 'touch' })
|
55
|
+
assert strategy.authorize_params.is_a?(Hash)
|
56
|
+
assert_equal 'touch', strategy.authorize_params[:display]
|
57
|
+
end
|
58
|
+
|
59
|
+
test 'includes state parameter from request when present' do
|
60
|
+
@request.stubs(:params).returns({ 'state' => 'some_state' })
|
61
|
+
assert strategy.authorize_params.is_a?(Hash)
|
62
|
+
assert_equal 'some_state', strategy.authorize_params[:state]
|
63
|
+
end
|
64
|
+
|
65
|
+
test 'overrides default scope with parameter passed from request' do
|
66
|
+
@request.stubs(:params).returns({ 'scope' => 'email' })
|
67
|
+
assert strategy.authorize_params.is_a?(Hash)
|
68
|
+
assert_equal 'email', strategy.authorize_params[:scope]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class TokeParamsTest < StrategyTestCase
|
73
|
+
test 'has correct parse strategy' do
|
74
|
+
assert_equal :query, strategy.token_params[:parse]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class AccessTokenOptionsTest < StrategyTestCase
|
79
|
+
test 'has correct param name by default' do
|
80
|
+
assert_equal 'access_token', strategy.access_token_options[:param_name]
|
81
|
+
end
|
82
|
+
|
83
|
+
test 'has correct header format by default' do
|
84
|
+
assert_equal 'OAuth %s', strategy.access_token_options[:header_format]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class UidTest < StrategyTestCase
|
89
|
+
def setup
|
90
|
+
super
|
91
|
+
strategy.stubs(:raw_info).returns({ 'id' => '123' })
|
92
|
+
end
|
93
|
+
|
94
|
+
test 'returns the id from raw_info' do
|
95
|
+
assert_equal '123', strategy.uid
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class InfoTest < StrategyTestCase
|
100
|
+
test 'returns the secure facebook avatar url when `secure_image_url` option is specified' do
|
101
|
+
@options = { :secure_image_url => true }
|
102
|
+
raw_info = { 'name' => 'Fred Smith', 'id' => '321' }
|
103
|
+
strategy.stubs(:raw_info).returns(raw_info)
|
104
|
+
assert_equal 'https://graph.facebook.com/321/picture?type=square', strategy.info['image']
|
105
|
+
end
|
106
|
+
|
107
|
+
test 'returns the image size specified in the `image_size` option' do
|
108
|
+
@options = { :image_size => 'normal' }
|
109
|
+
raw_info = { 'name' => 'Fred Smith', 'id' => '321' }
|
110
|
+
strategy.stubs(:raw_info).returns(raw_info)
|
111
|
+
assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class InfoTestOptionalDataPresent < StrategyTestCase
|
116
|
+
def setup
|
117
|
+
super
|
118
|
+
@raw_info ||= { 'name' => 'Fred Smith' }
|
119
|
+
strategy.stubs(:raw_info).returns(@raw_info)
|
120
|
+
end
|
121
|
+
|
122
|
+
test 'returns the name' do
|
123
|
+
assert_equal 'Fred Smith', strategy.info['name']
|
124
|
+
end
|
125
|
+
|
126
|
+
test 'returns the email' do
|
127
|
+
@raw_info['email'] = 'fred@smith.com'
|
128
|
+
assert_equal 'fred@smith.com', strategy.info['email']
|
129
|
+
end
|
130
|
+
|
131
|
+
test 'returns the username as nickname' do
|
132
|
+
@raw_info['username'] = 'fredsmith'
|
133
|
+
assert_equal 'fredsmith', strategy.info['nickname']
|
134
|
+
end
|
135
|
+
|
136
|
+
test 'returns the first name' do
|
137
|
+
@raw_info['first_name'] = 'Fred'
|
138
|
+
assert_equal 'Fred', strategy.info['first_name']
|
139
|
+
end
|
140
|
+
|
141
|
+
test 'returns the last name' do
|
142
|
+
@raw_info['last_name'] = 'Smith'
|
143
|
+
assert_equal 'Smith', strategy.info['last_name']
|
144
|
+
end
|
145
|
+
|
146
|
+
test 'returns the location name as location' do
|
147
|
+
@raw_info['location'] = { 'id' => '104022926303756', 'name' => 'Palo Alto, California' }
|
148
|
+
assert_equal 'Palo Alto, California', strategy.info['location']
|
149
|
+
end
|
150
|
+
|
151
|
+
test 'returns bio as description' do
|
152
|
+
@raw_info['bio'] = 'I am great'
|
153
|
+
assert_equal 'I am great', strategy.info['description']
|
154
|
+
end
|
155
|
+
|
156
|
+
test 'returns the square format facebook avatar url' do
|
157
|
+
@raw_info['id'] = '321'
|
158
|
+
assert_equal 'http://graph.facebook.com/321/picture?type=square', strategy.info['image']
|
159
|
+
end
|
160
|
+
|
161
|
+
test 'returns the Facebook link as the Facebook url' do
|
162
|
+
@raw_info['link'] = 'http://www.facebook.com/fredsmith'
|
163
|
+
assert_kind_of Hash, strategy.info['urls']
|
164
|
+
assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook']
|
165
|
+
end
|
166
|
+
|
167
|
+
test 'returns website url' do
|
168
|
+
@raw_info['website'] = 'https://my-wonderful-site.com'
|
169
|
+
assert_kind_of Hash, strategy.info['urls']
|
170
|
+
assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website']
|
171
|
+
end
|
172
|
+
|
173
|
+
test 'return both Facebook link and website urls' do
|
174
|
+
@raw_info['link'] = 'http://www.facebook.com/fredsmith'
|
175
|
+
@raw_info['website'] = 'https://my-wonderful-site.com'
|
176
|
+
assert_kind_of Hash, strategy.info['urls']
|
177
|
+
assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook']
|
178
|
+
assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website']
|
179
|
+
end
|
180
|
+
|
181
|
+
test 'returns the positive verified status' do
|
182
|
+
@raw_info['verified'] = true
|
183
|
+
assert strategy.info['verified']
|
184
|
+
end
|
185
|
+
|
186
|
+
test 'returns the negative verified status' do
|
187
|
+
@raw_info['verified'] = false
|
188
|
+
refute strategy.info['verified']
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class InfoTestOptionalDataNotPresent < StrategyTestCase
|
193
|
+
def setup
|
194
|
+
super
|
195
|
+
@raw_info ||= { 'name' => 'Fred Smith' }
|
196
|
+
strategy.stubs(:raw_info).returns(@raw_info)
|
197
|
+
end
|
198
|
+
|
199
|
+
test 'has no email key' do
|
200
|
+
refute_has_key 'email', strategy.info
|
201
|
+
end
|
202
|
+
|
203
|
+
test 'has no nickname key' do
|
204
|
+
refute_has_key 'nickname', strategy.info
|
205
|
+
end
|
206
|
+
|
207
|
+
test 'has no first name key' do
|
208
|
+
refute_has_key 'first_name', strategy.info
|
209
|
+
end
|
210
|
+
|
211
|
+
test 'has no last name key' do
|
212
|
+
refute_has_key 'last_name', strategy.info
|
213
|
+
end
|
214
|
+
|
215
|
+
test 'has no location key' do
|
216
|
+
refute_has_key 'location', strategy.info
|
217
|
+
end
|
218
|
+
|
219
|
+
test 'has no description key' do
|
220
|
+
refute_has_key 'description', strategy.info
|
221
|
+
end
|
222
|
+
|
223
|
+
test 'has no urls' do
|
224
|
+
refute_has_key 'urls', strategy.info
|
225
|
+
end
|
226
|
+
|
227
|
+
test 'has no verified key' do
|
228
|
+
refute_has_key 'verified', strategy.info
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class RawInfoTest < StrategyTestCase
|
233
|
+
def setup
|
234
|
+
super
|
235
|
+
@access_token = stub('OAuth2::AccessToken')
|
236
|
+
end
|
237
|
+
|
238
|
+
test 'performs a GET to https://graph.facebook.com/me' do
|
239
|
+
strategy.stubs(:access_token).returns(@access_token)
|
240
|
+
@access_token.expects(:get).with('/me').returns(stub_everything('OAuth2::Response'))
|
241
|
+
strategy.raw_info
|
242
|
+
end
|
243
|
+
|
244
|
+
test 'returns a Hash' do
|
245
|
+
strategy.stubs(:access_token).returns(@access_token)
|
246
|
+
raw_response = stub('Faraday::Response')
|
247
|
+
raw_response.stubs(:body).returns('{ "ohai": "thar" }')
|
248
|
+
raw_response.stubs(:status).returns(200)
|
249
|
+
raw_response.stubs(:headers).returns({'Content-Type' => 'application/json' })
|
250
|
+
oauth2_response = OAuth2::Response.new(raw_response)
|
251
|
+
@access_token.stubs(:get).with('/me').returns(oauth2_response)
|
252
|
+
assert_kind_of Hash, strategy.raw_info
|
253
|
+
assert_equal 'thar', strategy.raw_info['ohai']
|
254
|
+
end
|
255
|
+
|
256
|
+
test 'returns an empty hash when the response is false' do
|
257
|
+
strategy.stubs(:access_token).returns(@access_token)
|
258
|
+
oauth2_response = stub('OAuth2::Response', :parsed => false)
|
259
|
+
@access_token.stubs(:get).with('/me').returns(oauth2_response)
|
260
|
+
assert_kind_of Hash, strategy.raw_info
|
261
|
+
end
|
262
|
+
|
263
|
+
test 'should not include raw_info in extras hash when skip_info is specified' do
|
264
|
+
@options = { :skip_info => true }
|
265
|
+
strategy.stubs(:raw_info).returns({:foo => 'bar' })
|
266
|
+
refute_has_key 'raw_info', strategy.extra
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
class CredentialsTest < StrategyTestCase
|
271
|
+
def setup
|
272
|
+
super
|
273
|
+
@access_token = stub('OAuth2::AccessToken')
|
274
|
+
@access_token.stubs(:token)
|
275
|
+
@access_token.stubs(:expires?)
|
276
|
+
@access_token.stubs(:expires_at)
|
277
|
+
@access_token.stubs(:refresh_token)
|
278
|
+
strategy.stubs(:access_token).returns(@access_token)
|
279
|
+
end
|
280
|
+
|
281
|
+
test 'returns a Hash' do
|
282
|
+
assert_kind_of Hash, strategy.credentials
|
283
|
+
end
|
284
|
+
|
285
|
+
test 'returns the token' do
|
286
|
+
@access_token.stubs(:token).returns('123')
|
287
|
+
assert_equal '123', strategy.credentials['token']
|
288
|
+
end
|
289
|
+
|
290
|
+
test 'returns the expiry status' do
|
291
|
+
@access_token.stubs(:expires?).returns(true)
|
292
|
+
assert strategy.credentials['expires']
|
293
|
+
|
294
|
+
@access_token.stubs(:expires?).returns(false)
|
295
|
+
refute strategy.credentials['expires']
|
296
|
+
end
|
297
|
+
|
298
|
+
test 'returns the refresh token and expiry time when expiring' do
|
299
|
+
ten_mins_from_now = (Time.now + 600).to_i
|
300
|
+
@access_token.stubs(:expires?).returns(true)
|
301
|
+
@access_token.stubs(:refresh_token).returns('321')
|
302
|
+
@access_token.stubs(:expires_at).returns(ten_mins_from_now)
|
303
|
+
assert_equal '321', strategy.credentials['refresh_token']
|
304
|
+
assert_equal ten_mins_from_now, strategy.credentials['expires_at']
|
305
|
+
end
|
306
|
+
|
307
|
+
test 'does not return the refresh token when test is nil and expiring' do
|
308
|
+
@access_token.stubs(:expires?).returns(true)
|
309
|
+
@access_token.stubs(:refresh_token).returns(nil)
|
310
|
+
assert_nil strategy.credentials['refresh_token']
|
311
|
+
refute_has_key 'refresh_token', strategy.credentials
|
312
|
+
end
|
313
|
+
|
314
|
+
test 'does not return the refresh token when not expiring' do
|
315
|
+
@access_token.stubs(:expires?).returns(false)
|
316
|
+
@access_token.stubs(:refresh_token).returns('XXX')
|
317
|
+
assert_nil strategy.credentials['refresh_token']
|
318
|
+
refute_has_key 'refresh_token', strategy.credentials
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
class ExtraTest < StrategyTestCase
|
323
|
+
def setup
|
324
|
+
super
|
325
|
+
@raw_info = { 'name' => 'Fred Smith' }
|
326
|
+
strategy.stubs(:raw_info).returns(@raw_info)
|
327
|
+
end
|
328
|
+
|
329
|
+
test 'returns a Hash' do
|
330
|
+
assert_kind_of Hash, strategy.extra
|
331
|
+
end
|
332
|
+
|
333
|
+
test 'contains raw info' do
|
334
|
+
assert_equal({ 'raw_info' => @raw_info }, strategy.extra)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
module SignedRequestHelpers
|
339
|
+
def signed_request(payload, secret)
|
340
|
+
encoded_payload = base64_encode_url(MultiJson.encode(payload))
|
341
|
+
encoded_signature = base64_encode_url(signature(encoded_payload, secret))
|
342
|
+
[encoded_signature, encoded_payload].join('.')
|
343
|
+
end
|
344
|
+
|
345
|
+
def base64_encode_url(value)
|
346
|
+
Base64.encode64(value).tr('+/', '-_').gsub(/\n/, '')
|
347
|
+
end
|
348
|
+
|
349
|
+
def signature(payload, secret, algorithm = OpenSSL::Digest::SHA256.new)
|
350
|
+
OpenSSL::HMAC.digest(algorithm, secret, payload)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
module SignedRequestTests
|
355
|
+
class TestCase < StrategyTestCase
|
356
|
+
include SignedRequestHelpers
|
357
|
+
end
|
358
|
+
|
359
|
+
class CookieAndParamNotPresentTest < TestCase
|
360
|
+
test 'is nil' do
|
361
|
+
assert_nil strategy.send(:signed_request)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
class CookiePresentTest < TestCase
|
366
|
+
def setup
|
367
|
+
super
|
368
|
+
@payload = {
|
369
|
+
'algorithm' => 'HMAC-SHA256',
|
370
|
+
'code' => 'm4c0d3z',
|
371
|
+
'issued_at' => Time.now.to_i,
|
372
|
+
'user_id' => '123456'
|
373
|
+
}
|
374
|
+
|
375
|
+
@request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)})
|
376
|
+
end
|
377
|
+
|
378
|
+
test 'parses the access code out from the cookie' do
|
379
|
+
assert_equal @payload, strategy.send(:signed_request)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
class ParamPresentTest < TestCase
|
384
|
+
def setup
|
385
|
+
super
|
386
|
+
@payload = {
|
387
|
+
'algorithm' => 'HMAC-SHA256',
|
388
|
+
'oauth_token' => 'XXX',
|
389
|
+
'issued_at' => Time.now.to_i,
|
390
|
+
'user_id' => '123456'
|
391
|
+
}
|
392
|
+
|
393
|
+
@request.stubs(:params).returns({'signed_request' => signed_request(@payload, @client_secret)})
|
394
|
+
end
|
395
|
+
|
396
|
+
test 'parses the access code out from the param' do
|
397
|
+
assert_equal @payload, strategy.send(:signed_request)
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
class CookieAndParamPresentTest < TestCase
|
402
|
+
def setup
|
403
|
+
super
|
404
|
+
@payload_from_cookie = {
|
405
|
+
'algorithm' => 'HMAC-SHA256',
|
406
|
+
'from' => 'cookie'
|
407
|
+
}
|
408
|
+
|
409
|
+
@request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload_from_cookie, @client_secret)})
|
410
|
+
|
411
|
+
@payload_from_param = {
|
412
|
+
'algorithm' => 'HMAC-SHA256',
|
413
|
+
'from' => 'param'
|
414
|
+
}
|
415
|
+
|
416
|
+
@request.stubs(:params).returns({'signed_request' => signed_request(@payload_from_param, @client_secret)})
|
417
|
+
end
|
418
|
+
|
419
|
+
test 'picks param over cookie' do
|
420
|
+
assert_equal @payload_from_param, strategy.send(:signed_request)
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
class RequestPhaseWithSignedRequestTest < StrategyTestCase
|
426
|
+
include SignedRequestHelpers
|
427
|
+
|
428
|
+
def setup
|
429
|
+
super
|
430
|
+
|
431
|
+
payload = {
|
432
|
+
'algorithm' => 'HMAC-SHA256',
|
433
|
+
'oauth_token' => 'm4c0d3z'
|
434
|
+
}
|
435
|
+
@raw_signed_request = signed_request(payload, @client_secret)
|
436
|
+
@request.stubs(:params).returns("signed_request" => @raw_signed_request)
|
437
|
+
|
438
|
+
strategy.stubs(:callback_url).returns('/')
|
439
|
+
end
|
440
|
+
|
441
|
+
test 'redirects to callback passing along signed request' do
|
442
|
+
strategy.expects(:redirect).with("/?signed_request=#{Rack::Utils.escape(@raw_signed_request)}").once
|
443
|
+
strategy.request_phase
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
module BuildAccessTokenTests
|
448
|
+
class TestCase < StrategyTestCase
|
449
|
+
include SignedRequestHelpers
|
450
|
+
end
|
451
|
+
|
452
|
+
class ParamsContainSignedRequestWithAccessTokenTest < TestCase
|
453
|
+
def setup
|
454
|
+
super
|
455
|
+
|
456
|
+
@payload = {
|
457
|
+
'algorithm' => 'HMAC-SHA256',
|
458
|
+
'oauth_token' => 'm4c0d3z',
|
459
|
+
'expires' => Time.now.to_i
|
460
|
+
}
|
461
|
+
@raw_signed_request = signed_request(@payload, @client_secret)
|
462
|
+
@request.stubs(:params).returns({"signed_request" => @raw_signed_request})
|
463
|
+
|
464
|
+
strategy.stubs(:callback_url).returns('/')
|
465
|
+
end
|
466
|
+
|
467
|
+
test 'returns a new access token from the signed request' do
|
468
|
+
result = strategy.build_access_token
|
469
|
+
assert_kind_of ::OAuth2::AccessToken, result
|
470
|
+
assert_equal @payload['oauth_token'], result.token
|
471
|
+
end
|
472
|
+
|
473
|
+
test 'returns an access token with the correct expiry time' do
|
474
|
+
result = strategy.build_access_token
|
475
|
+
assert_equal @payload['expires'], result.expires_at
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
class ParamsContainAccessTokenStringTest < TestCase
|
480
|
+
def setup
|
481
|
+
super
|
482
|
+
|
483
|
+
@request.stubs(:params).returns({'access_token' => 'm4c0d3z'})
|
484
|
+
|
485
|
+
strategy.stubs(:callback_url).returns('/')
|
486
|
+
end
|
487
|
+
|
488
|
+
test 'returns a new access token' do
|
489
|
+
result = strategy.build_access_token
|
490
|
+
assert_kind_of ::OAuth2::AccessToken, result
|
491
|
+
assert_equal 'm4c0d3z', result.token
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|