omniauth-facebook 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of omniauth-facebook might be problematic. Click here for more details.

data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
2
+ require 'rake/testtask'
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ Rake::TestTask.new do |task|
5
+ task.libs << 'test'
6
+ end
5
7
 
6
- task :default => :spec
8
+ task :default => :test
@@ -1,27 +1,32 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- omniauth-facebook (1.3.0)
5
- omniauth-oauth2 (~> 1.0.2)
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.0)
10
+ faraday (0.8.1)
11
11
  multipart-post (~> 1.1)
12
12
  hashie (1.2.0)
13
13
  httpauth (0.1)
14
- multi_json (1.3.4)
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.6.1)
17
- faraday (~> 0.7)
19
+ oauth2 (0.8.0)
20
+ faraday (~> 0.8)
18
21
  httpauth (~> 0.1)
19
- multi_json (~> 1.3)
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.2)
24
- oauth2 (~> 0.6.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)
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Facebook
3
- VERSION = "1.4.0"
3
+ VERSION = "1.4.1"
4
4
  end
5
5
  end
@@ -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 { |v| params[v.to_sym] = request.params[v] if request.params[v] }
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
@@ -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.2'
18
+ s.add_runtime_dependency 'omniauth-oauth2', '~> 1.1.0'
19
19
 
20
- s.add_development_dependency 'rspec', '~> 2'
20
+ s.add_development_dependency 'minitest'
21
+ s.add_development_dependency 'mocha'
21
22
  s.add_development_dependency 'rake'
22
23
  end
@@ -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
@@ -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