Refactor SignedRequest class.
Josef Šimánek
9 years ago
2 | 2 | |
3 | 3 | Rake::TestTask.new do |task| |
4 | 4 | task.libs << 'test' |
5 | task.test_files = FileList['test/*_test.rb'] | |
5 | 6 | end |
6 | 7 | |
7 | 8 | task :default => :test |
0 | require 'base64' | |
1 | 0 | require 'openssl' |
2 | 1 | |
3 | 2 | module OmniAuth |
4 | 3 | module Facebook |
5 | 4 | class SignedRequest |
6 | 5 | class UnknownSignatureAlgorithmError < NotImplementedError; end |
7 | ||
8 | 6 | SUPPORTED_ALGORITHM = 'HMAC-SHA256' |
9 | 7 | |
10 | def self.parse_signed_request(value, secret) | |
8 | attr_reader :value, :secret | |
9 | ||
10 | def self.parse(value, secret) | |
11 | new(value, secret).payload | |
12 | end | |
13 | ||
14 | def initialize(value, secret) | |
15 | @value = value | |
16 | @secret = secret | |
17 | end | |
18 | ||
19 | def payload | |
20 | @payload ||= parse_signed_request | |
21 | end | |
22 | ||
23 | private | |
24 | ||
25 | def parse_signed_request | |
11 | 26 | signature, encoded_payload = value.split('.') |
12 | 27 | return if signature.nil? |
13 | 28 | |
18 | 33 | raise UnknownSignatureAlgorithmError, "unknown algorithm: #{decoded_payload['algorithm']}" |
19 | 34 | end |
20 | 35 | |
21 | if valid_signature?(secret, decoded_hex_signature, encoded_payload) | |
36 | if valid_signature?(decoded_hex_signature, encoded_payload) | |
22 | 37 | decoded_payload |
23 | 38 | end |
24 | 39 | end |
25 | 40 | |
26 | def self.valid_signature?(secret, signature, payload, algorithm = OpenSSL::Digest::SHA256.new) | |
41 | def valid_signature?(signature, payload, algorithm = OpenSSL::Digest::SHA256.new) | |
27 | 42 | OpenSSL::HMAC.digest(algorithm, secret, payload) == signature |
28 | 43 | end |
29 | 44 | |
30 | def self.base64_decode_url(value) | |
45 | def base64_decode_url(value) | |
31 | 46 | value += '=' * (4 - value.size.modulo(4)) |
32 | 47 | Base64.decode64(value.tr('-_', '+/')) |
33 | 48 | end |
117 | 117 | private |
118 | 118 | |
119 | 119 | def signed_request_from_cookie |
120 | @signed_request_from_cookie ||= raw_signed_request_from_cookie && OmniAuth::Facebook::SignedRequest.parse_signed_request(raw_signed_request_from_cookie, client.secret) | |
120 | @signed_request_from_cookie ||= raw_signed_request_from_cookie && OmniAuth::Facebook::SignedRequest.parse(raw_signed_request_from_cookie, client.secret) | |
121 | 121 | end |
122 | 122 | |
123 | 123 | def raw_signed_request_from_cookie |
0 | { | |
1 | "algorithm": "HMAC-SHA256", | |
2 | "expires": 1308988800, | |
3 | "issued_at": 1308985018, | |
4 | "oauth_token": "111111111111111|2.AQBAttRlLVnwqNPZ.3600.1111111111.1-111111111111111|T49w3BqoZUegypru51Gra70hED8", | |
5 | "user": | |
6 | { | |
7 | "country": "de", | |
8 | "locale": "en_US", | |
9 | "age": | |
10 | { | |
11 | "min": 21 | |
12 | } | |
13 | }, | |
14 | "user_id": "111111111111111" | |
15 | } |
0 | 53umfudisP7mKhsi9nZboBg15yMZKhfQAARL9UoZtSE.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDg5ODg4MDAsImlzc3VlZF9hdCI6MTMwODk4NTAxOCwib2F1dGhfdG9rZW4iOiIxMTExMTExMTExMTExMTF8Mi5BUUJBdHRSbExWbndxTlBaLjM2MDAuMTExMTExMTExMS4xLTExMTExMTExMTExMTExMXxUNDl3M0Jxb1pVZWd5cHJ1NTFHcmE3MGhFRDgiLCJ1c2VyIjp7ImNvdW50cnkiOiJkZSIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjExMTExMTExMTExMTExMSJ9 |
0 | require 'helper' | |
1 | require 'omniauth/facebook/signed_request' | |
2 | ||
3 | class SignedRequestTest < Minitest::Test | |
4 | def setup | |
5 | @value = fixture('signed_request.txt').strip | |
6 | @secret = "897z956a2z7zzzzz5783z458zz3z7556" | |
7 | @expected_payload = MultiJson.decode(fixture('payload.json')) | |
8 | end | |
9 | ||
10 | def test_signed_request_payload | |
11 | signed_request = OmniAuth::Facebook::SignedRequest.new(@value, @secret) | |
12 | assert_equal @expected_payload, signed_request.payload | |
13 | end | |
14 | ||
15 | def test_signed_request_parse | |
16 | payload = OmniAuth::Facebook::SignedRequest.parse(@value, @secret) | |
17 | assert_equal @expected_payload, payload | |
18 | end | |
19 | ||
20 | private | |
21 | ||
22 | def fixture(name) | |
23 | File.read(File.expand_path("fixtures/#{name}", File.dirname(__FILE__))) | |
24 | end | |
25 | end |
0 | require 'helper' | |
1 | require 'omniauth-facebook' | |
2 | require 'openssl' | |
3 | require 'base64' | |
4 | ||
5 | class StrategyTest < StrategyTestCase | |
6 | include OAuth2StrategyTests | |
7 | end | |
8 | ||
9 | class ClientTest < StrategyTestCase | |
10 | test 'has correct Facebook site' do | |
11 | assert_equal 'https://graph.facebook.com', strategy.client.site | |
12 | end | |
13 | ||
14 | test 'has correct authorize url' do | |
15 | assert_equal 'https://www.facebook.com/dialog/oauth', strategy.client.options[:authorize_url] | |
16 | end | |
17 | ||
18 | test 'has correct token url with versioning' do | |
19 | @options = {:client_options => {:site => 'https://graph.facebook.net/v2.2'}} | |
20 | assert_equal 'oauth/access_token', strategy.client.options[:token_url] | |
21 | assert_equal 'https://graph.facebook.net/v2.2/oauth/access_token', strategy.client.token_url | |
22 | end | |
23 | end | |
24 | ||
25 | class CallbackUrlTest < StrategyTestCase | |
26 | test "returns the default callback url" do | |
27 | url_base = 'http://auth.request.com' | |
28 | @request.stubs(:url).returns("#{url_base}/some/page") | |
29 | strategy.stubs(:script_name).returns('') # as not to depend on Rack env | |
30 | assert_equal "#{url_base}/auth/facebook/callback", strategy.callback_url | |
31 | end | |
32 | ||
33 | test "returns path from callback_path option" do | |
34 | @options = { :callback_path => "/auth/FB/done"} | |
35 | url_base = 'http://auth.request.com' | |
36 | @request.stubs(:url).returns("#{url_base}/page/path") | |
37 | strategy.stubs(:script_name).returns('') # as not to depend on Rack env | |
38 | assert_equal "#{url_base}/auth/FB/done", strategy.callback_url | |
39 | end | |
40 | ||
41 | test "returns url from callback_url option" do | |
42 | url = 'https://auth.myapp.com/auth/fb/callback' | |
43 | @options = { :callback_url => url } | |
44 | assert_equal url, strategy.callback_url | |
45 | end | |
46 | end | |
47 | ||
48 | class AuthorizeParamsTest < StrategyTestCase | |
49 | test 'includes default scope for email' do | |
50 | assert strategy.authorize_params.is_a?(Hash) | |
51 | assert_equal 'email', strategy.authorize_params[:scope] | |
52 | end | |
53 | ||
54 | test 'includes display parameter from request when present' do | |
55 | @request.stubs(:params).returns({ 'display' => 'touch' }) | |
56 | assert strategy.authorize_params.is_a?(Hash) | |
57 | assert_equal 'touch', strategy.authorize_params[:display] | |
58 | end | |
59 | ||
60 | test 'includes auth_type parameter from request when present' do | |
61 | @request.stubs(:params).returns({ 'auth_type' => 'reauthenticate' }) | |
62 | assert strategy.authorize_params.is_a?(Hash) | |
63 | assert_equal 'reauthenticate', strategy.authorize_params[:auth_type] | |
64 | end | |
65 | ||
66 | test 'overrides default scope with parameter passed from request' do | |
67 | @request.stubs(:params).returns({ 'scope' => 'email' }) | |
68 | assert strategy.authorize_params.is_a?(Hash) | |
69 | assert_equal 'email', strategy.authorize_params[:scope] | |
70 | end | |
71 | end | |
72 | ||
73 | class TokeParamsTest < StrategyTestCase | |
74 | test 'has correct parse strategy' do | |
75 | assert_equal :query, strategy.token_params[:parse] | |
76 | end | |
77 | end | |
78 | ||
79 | class AccessTokenOptionsTest < StrategyTestCase | |
80 | test 'has correct param name by default' do | |
81 | assert_equal 'access_token', strategy.access_token_options[:param_name] | |
82 | end | |
83 | ||
84 | test 'has correct header format by default' do | |
85 | assert_equal 'OAuth %s', strategy.access_token_options[:header_format] | |
86 | end | |
87 | end | |
88 | ||
89 | class UidTest < StrategyTestCase | |
90 | def setup | |
91 | super | |
92 | strategy.stubs(:raw_info).returns({ 'id' => '123' }) | |
93 | end | |
94 | ||
95 | test 'returns the id from raw_info' do | |
96 | assert_equal '123', strategy.uid | |
97 | end | |
98 | end | |
99 | ||
100 | class InfoTest < StrategyTestCase | |
101 | test 'returns the secure facebook avatar url when `secure_image_url` option is specified' do | |
102 | @options = { :secure_image_url => true } | |
103 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
104 | strategy.stubs(:raw_info).returns(raw_info) | |
105 | assert_equal 'https://graph.facebook.com/321/picture', strategy.info['image'] | |
106 | end | |
107 | ||
108 | test 'returns the image_url based of the client site' do | |
109 | @options = { :secure_image_url => true, :client_options => {:site => "https://blah.facebook.com/v2.2"}} | |
110 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
111 | strategy.stubs(:raw_info).returns(raw_info) | |
112 | assert_equal 'https://blah.facebook.com/v2.2/321/picture', strategy.info['image'] | |
113 | end | |
114 | ||
115 | test 'returns the image with size specified in the `image_size` option' do | |
116 | @options = { :image_size => 'normal' } | |
117 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
118 | strategy.stubs(:raw_info).returns(raw_info) | |
119 | assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image'] | |
120 | end | |
121 | ||
122 | test 'returns the image with size specified as a symbol in the `image_size` option' do | |
123 | @options = { :image_size => :normal } | |
124 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
125 | strategy.stubs(:raw_info).returns(raw_info) | |
126 | assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image'] | |
127 | end | |
128 | ||
129 | test 'returns the image with width and height specified in the `image_size` option' do | |
130 | @options = { :image_size => { :width => 123, :height => 987 } } | |
131 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
132 | strategy.stubs(:raw_info).returns(raw_info) | |
133 | assert_match 'width=123', strategy.info['image'] | |
134 | assert_match 'height=987', strategy.info['image'] | |
135 | assert_match 'http://graph.facebook.com/321/picture?', strategy.info['image'] | |
136 | end | |
137 | end | |
138 | ||
139 | class InfoTestOptionalDataPresent < StrategyTestCase | |
140 | def setup | |
141 | super | |
142 | @raw_info ||= { 'name' => 'Fred Smith' } | |
143 | strategy.stubs(:raw_info).returns(@raw_info) | |
144 | end | |
145 | ||
146 | test 'returns the name' do | |
147 | assert_equal 'Fred Smith', strategy.info['name'] | |
148 | end | |
149 | ||
150 | test 'returns the email' do | |
151 | @raw_info['email'] = 'fred@smith.com' | |
152 | assert_equal 'fred@smith.com', strategy.info['email'] | |
153 | end | |
154 | ||
155 | test 'returns the username as nickname' do | |
156 | @raw_info['username'] = 'fredsmith' | |
157 | assert_equal 'fredsmith', strategy.info['nickname'] | |
158 | end | |
159 | ||
160 | test 'returns the first name' do | |
161 | @raw_info['first_name'] = 'Fred' | |
162 | assert_equal 'Fred', strategy.info['first_name'] | |
163 | end | |
164 | ||
165 | test 'returns the last name' do | |
166 | @raw_info['last_name'] = 'Smith' | |
167 | assert_equal 'Smith', strategy.info['last_name'] | |
168 | end | |
169 | ||
170 | test 'returns the location name as location' do | |
171 | @raw_info['location'] = { 'id' => '104022926303756', 'name' => 'Palo Alto, California' } | |
172 | assert_equal 'Palo Alto, California', strategy.info['location'] | |
173 | end | |
174 | ||
175 | test 'returns bio as description' do | |
176 | @raw_info['bio'] = 'I am great' | |
177 | assert_equal 'I am great', strategy.info['description'] | |
178 | end | |
179 | ||
180 | test 'returns the facebook avatar url' do | |
181 | @raw_info['id'] = '321' | |
182 | assert_equal 'http://graph.facebook.com/321/picture', strategy.info['image'] | |
183 | end | |
184 | ||
185 | test 'returns the Facebook link as the Facebook url' do | |
186 | @raw_info['link'] = 'http://www.facebook.com/fredsmith' | |
187 | assert_kind_of Hash, strategy.info['urls'] | |
188 | assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook'] | |
189 | end | |
190 | ||
191 | test 'returns website url' do | |
192 | @raw_info['website'] = 'https://my-wonderful-site.com' | |
193 | assert_kind_of Hash, strategy.info['urls'] | |
194 | assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website'] | |
195 | end | |
196 | ||
197 | test 'return both Facebook link and website urls' do | |
198 | @raw_info['link'] = 'http://www.facebook.com/fredsmith' | |
199 | @raw_info['website'] = 'https://my-wonderful-site.com' | |
200 | assert_kind_of Hash, strategy.info['urls'] | |
201 | assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook'] | |
202 | assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website'] | |
203 | end | |
204 | ||
205 | test 'returns the positive verified status' do | |
206 | @raw_info['verified'] = true | |
207 | assert strategy.info['verified'] | |
208 | end | |
209 | ||
210 | test 'returns the negative verified status' do | |
211 | @raw_info['verified'] = false | |
212 | refute strategy.info['verified'] | |
213 | end | |
214 | end | |
215 | ||
216 | class InfoTestOptionalDataNotPresent < StrategyTestCase | |
217 | def setup | |
218 | super | |
219 | @raw_info ||= { 'name' => 'Fred Smith' } | |
220 | strategy.stubs(:raw_info).returns(@raw_info) | |
221 | end | |
222 | ||
223 | test 'has no email key' do | |
224 | refute_has_key 'email', strategy.info | |
225 | end | |
226 | ||
227 | test 'has no nickname key' do | |
228 | refute_has_key 'nickname', strategy.info | |
229 | end | |
230 | ||
231 | test 'has no first name key' do | |
232 | refute_has_key 'first_name', strategy.info | |
233 | end | |
234 | ||
235 | test 'has no last name key' do | |
236 | refute_has_key 'last_name', strategy.info | |
237 | end | |
238 | ||
239 | test 'has no location key' do | |
240 | refute_has_key 'location', strategy.info | |
241 | end | |
242 | ||
243 | test 'has no description key' do | |
244 | refute_has_key 'description', strategy.info | |
245 | end | |
246 | ||
247 | test 'has no urls' do | |
248 | refute_has_key 'urls', strategy.info | |
249 | end | |
250 | ||
251 | test 'has no verified key' do | |
252 | refute_has_key 'verified', strategy.info | |
253 | end | |
254 | end | |
255 | ||
256 | class RawInfoTest < StrategyTestCase | |
257 | def setup | |
258 | super | |
259 | @access_token = stub('OAuth2::AccessToken') | |
260 | @appsecret_proof = 'appsecret_proof' | |
261 | @options = {:appsecret_proof => @appsecret_proof} | |
262 | end | |
263 | ||
264 | test 'performs a GET to https://graph.facebook.com/me' do | |
265 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
266 | strategy.stubs(:access_token).returns(@access_token) | |
267 | params = {:params => @options} | |
268 | @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) | |
269 | strategy.raw_info | |
270 | end | |
271 | ||
272 | test 'performs a GET to https://graph.facebook.com/me with locale' do | |
273 | @options.merge!({ :locale => 'cs_CZ' }) | |
274 | strategy.stubs(:access_token).returns(@access_token) | |
275 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
276 | params = {:params => @options} | |
277 | @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) | |
278 | strategy.raw_info | |
279 | end | |
280 | ||
281 | test 'performs a GET to https://graph.facebook.com/me with info_fields' do | |
282 | @options.merge!({:info_fields => 'about'}) | |
283 | strategy.stubs(:access_token).returns(@access_token) | |
284 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
285 | params = {:params => {:appsecret_proof => @appsecret_proof, :fields => 'about'}} | |
286 | @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) | |
287 | strategy.raw_info | |
288 | end | |
289 | ||
290 | test 'returns a Hash' do | |
291 | strategy.stubs(:access_token).returns(@access_token) | |
292 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
293 | raw_response = stub('Faraday::Response') | |
294 | raw_response.stubs(:body).returns('{ "ohai": "thar" }') | |
295 | raw_response.stubs(:status).returns(200) | |
296 | raw_response.stubs(:headers).returns({'Content-Type' => 'application/json' }) | |
297 | oauth2_response = OAuth2::Response.new(raw_response) | |
298 | params = {:params => @options} | |
299 | @access_token.stubs(:get).with('me', params).returns(oauth2_response) | |
300 | assert_kind_of Hash, strategy.raw_info | |
301 | assert_equal 'thar', strategy.raw_info['ohai'] | |
302 | end | |
303 | ||
304 | test 'returns an empty hash when the response is false' do | |
305 | strategy.stubs(:access_token).returns(@access_token) | |
306 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
307 | oauth2_response = stub('OAuth2::Response', :parsed => false) | |
308 | params = {:params => @options} | |
309 | @access_token.stubs(:get).with('me', params).returns(oauth2_response) | |
310 | assert_kind_of Hash, strategy.raw_info | |
311 | assert_equal({}, strategy.raw_info) | |
312 | end | |
313 | ||
314 | test 'should not include raw_info in extras hash when skip_info is specified' do | |
315 | @options = { :skip_info => true } | |
316 | strategy.stubs(:raw_info).returns({:foo => 'bar' }) | |
317 | refute_has_key 'raw_info', strategy.extra | |
318 | end | |
319 | end | |
320 | ||
321 | class CredentialsTest < StrategyTestCase | |
322 | def setup | |
323 | super | |
324 | @access_token = stub('OAuth2::AccessToken') | |
325 | @access_token.stubs(:token) | |
326 | @access_token.stubs(:expires?) | |
327 | @access_token.stubs(:expires_at) | |
328 | @access_token.stubs(:refresh_token) | |
329 | strategy.stubs(:access_token).returns(@access_token) | |
330 | end | |
331 | ||
332 | test 'returns a Hash' do | |
333 | assert_kind_of Hash, strategy.credentials | |
334 | end | |
335 | ||
336 | test 'returns the token' do | |
337 | @access_token.stubs(:token).returns('123') | |
338 | assert_equal '123', strategy.credentials['token'] | |
339 | end | |
340 | ||
341 | test 'returns the expiry status' do | |
342 | @access_token.stubs(:expires?).returns(true) | |
343 | assert strategy.credentials['expires'] | |
344 | ||
345 | @access_token.stubs(:expires?).returns(false) | |
346 | refute strategy.credentials['expires'] | |
347 | end | |
348 | ||
349 | test 'returns the refresh token and expiry time when expiring' do | |
350 | ten_mins_from_now = (Time.now + 600).to_i | |
351 | @access_token.stubs(:expires?).returns(true) | |
352 | @access_token.stubs(:refresh_token).returns('321') | |
353 | @access_token.stubs(:expires_at).returns(ten_mins_from_now) | |
354 | assert_equal '321', strategy.credentials['refresh_token'] | |
355 | assert_equal ten_mins_from_now, strategy.credentials['expires_at'] | |
356 | end | |
357 | ||
358 | test 'does not return the refresh token when test is nil and expiring' do | |
359 | @access_token.stubs(:expires?).returns(true) | |
360 | @access_token.stubs(:refresh_token).returns(nil) | |
361 | assert_nil strategy.credentials['refresh_token'] | |
362 | refute_has_key 'refresh_token', strategy.credentials | |
363 | end | |
364 | ||
365 | test 'does not return the refresh token when not expiring' do | |
366 | @access_token.stubs(:expires?).returns(false) | |
367 | @access_token.stubs(:refresh_token).returns('XXX') | |
368 | assert_nil strategy.credentials['refresh_token'] | |
369 | refute_has_key 'refresh_token', strategy.credentials | |
370 | end | |
371 | end | |
372 | ||
373 | class ExtraTest < StrategyTestCase | |
374 | def setup | |
375 | super | |
376 | @raw_info = { 'name' => 'Fred Smith' } | |
377 | strategy.stubs(:raw_info).returns(@raw_info) | |
378 | end | |
379 | ||
380 | test 'returns a Hash' do | |
381 | assert_kind_of Hash, strategy.extra | |
382 | end | |
383 | ||
384 | test 'contains raw info' do | |
385 | assert_equal({ 'raw_info' => @raw_info }, strategy.extra) | |
386 | end | |
387 | end | |
388 | ||
389 | module SignedRequestHelpers | |
390 | def signed_request(payload, secret) | |
391 | encoded_payload = base64_encode_url(MultiJson.encode(payload)) | |
392 | encoded_signature = base64_encode_url(signature(encoded_payload, secret)) | |
393 | [encoded_signature, encoded_payload].join('.') | |
394 | end | |
395 | ||
396 | def base64_encode_url(value) | |
397 | Base64.encode64(value).tr('+/', '-_').gsub(/\n/, '') | |
398 | end | |
399 | ||
400 | def signature(payload, secret, algorithm = OpenSSL::Digest::SHA256.new) | |
401 | OpenSSL::HMAC.digest(algorithm, secret, payload) | |
402 | end | |
403 | end | |
404 | ||
405 | module SignedRequestTests | |
406 | class TestCase < StrategyTestCase | |
407 | include SignedRequestHelpers | |
408 | end | |
409 | ||
410 | class CookieAndParamNotPresentTest < TestCase | |
411 | test 'is nil' do | |
412 | assert_nil strategy.send(:signed_request_from_cookie) | |
413 | end | |
414 | ||
415 | test 'throws an error on calling build_access_token' do | |
416 | assert_raises(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError) { strategy.send(:with_authorization_code!) {} } | |
417 | end | |
418 | end | |
419 | ||
420 | class CookiePresentTest < TestCase | |
421 | def setup(algo = nil) | |
422 | super() | |
423 | @payload = { | |
424 | 'algorithm' => algo || 'HMAC-SHA256', | |
425 | 'code' => 'm4c0d3z', | |
426 | 'issued_at' => Time.now.to_i, | |
427 | 'user_id' => '123456' | |
428 | } | |
429 | ||
430 | @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) | |
431 | end | |
432 | ||
433 | test 'parses the access code out from the cookie' do | |
434 | assert_equal @payload, strategy.send(:signed_request_from_cookie) | |
435 | end | |
436 | ||
437 | test 'throws an error if the algorithm is unknown' do | |
438 | setup('UNKNOWN-ALGO') | |
439 | assert_equal "unknown algorithm: UNKNOWN-ALGO", assert_raises(OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError) { strategy.send(:signed_request_from_cookie) }.message | |
440 | end | |
441 | end | |
442 | ||
443 | class EmptySignedRequestTest < TestCase | |
444 | def setup | |
445 | super | |
446 | @request.stubs(:params).returns({'signed_request' => ''}) | |
447 | end | |
448 | ||
449 | test 'empty param' do | |
450 | assert_equal nil, strategy.send(:signed_request_from_cookie) | |
451 | end | |
452 | end | |
453 | ||
454 | class MissingCodeInParamsRequestTest < TestCase | |
455 | def setup | |
456 | super | |
457 | @request.stubs(:params).returns({}) | |
458 | end | |
459 | ||
460 | test 'calls fail! when a code is not included in the params' do | |
461 | strategy.expects(:fail!).times(1).with(:no_authorization_code, kind_of(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError)) | |
462 | strategy.callback_phase | |
463 | end | |
464 | end | |
465 | ||
466 | class MissingCodeInCookieRequestTest < TestCase | |
467 | def setup(algo = nil) | |
468 | super() | |
469 | @payload = { | |
470 | 'algorithm' => algo || 'HMAC-SHA256', | |
471 | 'code' => nil, | |
472 | 'issued_at' => Time.now.to_i, | |
473 | 'user_id' => '123456' | |
474 | } | |
475 | ||
476 | @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) | |
477 | end | |
478 | ||
479 | test 'calls fail! when a code is not included in the cookie' do | |
480 | strategy.expects(:fail!).times(1).with(:no_authorization_code, kind_of(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError)) | |
481 | strategy.callback_phase | |
482 | end | |
483 | end | |
484 | ||
485 | class UnknownAlgorithmInCookieRequestTest < TestCase | |
486 | def setup | |
487 | super() | |
488 | @payload = { | |
489 | 'algorithm' => 'UNKNOWN-ALGO', | |
490 | 'code' => nil, | |
491 | 'issued_at' => Time.now.to_i, | |
492 | 'user_id' => '123456' | |
493 | } | |
494 | ||
495 | @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) | |
496 | end | |
497 | ||
498 | test 'calls fail! when an algorithm is unknown' do | |
499 | strategy.expects(:fail!).times(1).with(:unknown_signature_algorithm, kind_of(OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError)) | |
500 | strategy.callback_phase | |
501 | end | |
502 | end | |
503 | end |
0 | require 'helper' | |
1 | require 'omniauth-facebook' | |
2 | require 'openssl' | |
3 | require 'base64' | |
4 | ||
5 | class StrategyTest < StrategyTestCase | |
6 | include OAuth2StrategyTests | |
7 | end | |
8 | ||
9 | class ClientTest < StrategyTestCase | |
10 | test 'has correct Facebook site' do | |
11 | assert_equal 'https://graph.facebook.com', strategy.client.site | |
12 | end | |
13 | ||
14 | test 'has correct authorize url' do | |
15 | assert_equal 'https://www.facebook.com/dialog/oauth', strategy.client.options[:authorize_url] | |
16 | end | |
17 | ||
18 | test 'has correct token url with versioning' do | |
19 | @options = {:client_options => {:site => 'https://graph.facebook.net/v2.2'}} | |
20 | assert_equal 'oauth/access_token', strategy.client.options[:token_url] | |
21 | assert_equal 'https://graph.facebook.net/v2.2/oauth/access_token', strategy.client.token_url | |
22 | end | |
23 | end | |
24 | ||
25 | class CallbackUrlTest < StrategyTestCase | |
26 | test "returns the default callback url" do | |
27 | url_base = 'http://auth.request.com' | |
28 | @request.stubs(:url).returns("#{url_base}/some/page") | |
29 | strategy.stubs(:script_name).returns('') # as not to depend on Rack env | |
30 | assert_equal "#{url_base}/auth/facebook/callback", strategy.callback_url | |
31 | end | |
32 | ||
33 | test "returns path from callback_path option" do | |
34 | @options = { :callback_path => "/auth/FB/done"} | |
35 | url_base = 'http://auth.request.com' | |
36 | @request.stubs(:url).returns("#{url_base}/page/path") | |
37 | strategy.stubs(:script_name).returns('') # as not to depend on Rack env | |
38 | assert_equal "#{url_base}/auth/FB/done", strategy.callback_url | |
39 | end | |
40 | ||
41 | test "returns url from callback_url option" do | |
42 | url = 'https://auth.myapp.com/auth/fb/callback' | |
43 | @options = { :callback_url => url } | |
44 | assert_equal url, strategy.callback_url | |
45 | end | |
46 | end | |
47 | ||
48 | class AuthorizeParamsTest < StrategyTestCase | |
49 | test 'includes default scope for email' do | |
50 | assert strategy.authorize_params.is_a?(Hash) | |
51 | assert_equal 'email', strategy.authorize_params[:scope] | |
52 | end | |
53 | ||
54 | test 'includes display parameter from request when present' do | |
55 | @request.stubs(:params).returns({ 'display' => 'touch' }) | |
56 | assert strategy.authorize_params.is_a?(Hash) | |
57 | assert_equal 'touch', strategy.authorize_params[:display] | |
58 | end | |
59 | ||
60 | test 'includes auth_type parameter from request when present' do | |
61 | @request.stubs(:params).returns({ 'auth_type' => 'reauthenticate' }) | |
62 | assert strategy.authorize_params.is_a?(Hash) | |
63 | assert_equal 'reauthenticate', strategy.authorize_params[:auth_type] | |
64 | end | |
65 | ||
66 | test 'overrides default scope with parameter passed from request' do | |
67 | @request.stubs(:params).returns({ 'scope' => 'email' }) | |
68 | assert strategy.authorize_params.is_a?(Hash) | |
69 | assert_equal 'email', strategy.authorize_params[:scope] | |
70 | end | |
71 | end | |
72 | ||
73 | class TokeParamsTest < StrategyTestCase | |
74 | test 'has correct parse strategy' do | |
75 | assert_equal :query, strategy.token_params[:parse] | |
76 | end | |
77 | end | |
78 | ||
79 | class AccessTokenOptionsTest < StrategyTestCase | |
80 | test 'has correct param name by default' do | |
81 | assert_equal 'access_token', strategy.access_token_options[:param_name] | |
82 | end | |
83 | ||
84 | test 'has correct header format by default' do | |
85 | assert_equal 'OAuth %s', strategy.access_token_options[:header_format] | |
86 | end | |
87 | end | |
88 | ||
89 | class UidTest < StrategyTestCase | |
90 | def setup | |
91 | super | |
92 | strategy.stubs(:raw_info).returns({ 'id' => '123' }) | |
93 | end | |
94 | ||
95 | test 'returns the id from raw_info' do | |
96 | assert_equal '123', strategy.uid | |
97 | end | |
98 | end | |
99 | ||
100 | class InfoTest < StrategyTestCase | |
101 | test 'returns the secure facebook avatar url when `secure_image_url` option is specified' do | |
102 | @options = { :secure_image_url => true } | |
103 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
104 | strategy.stubs(:raw_info).returns(raw_info) | |
105 | assert_equal 'https://graph.facebook.com/321/picture', strategy.info['image'] | |
106 | end | |
107 | ||
108 | test 'returns the image_url based of the client site' do | |
109 | @options = { :secure_image_url => true, :client_options => {:site => "https://blah.facebook.com/v2.2"}} | |
110 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
111 | strategy.stubs(:raw_info).returns(raw_info) | |
112 | assert_equal 'https://blah.facebook.com/v2.2/321/picture', strategy.info['image'] | |
113 | end | |
114 | ||
115 | test 'returns the image with size specified in the `image_size` option' do | |
116 | @options = { :image_size => 'normal' } | |
117 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
118 | strategy.stubs(:raw_info).returns(raw_info) | |
119 | assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image'] | |
120 | end | |
121 | ||
122 | test 'returns the image with size specified as a symbol in the `image_size` option' do | |
123 | @options = { :image_size => :normal } | |
124 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
125 | strategy.stubs(:raw_info).returns(raw_info) | |
126 | assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image'] | |
127 | end | |
128 | ||
129 | test 'returns the image with width and height specified in the `image_size` option' do | |
130 | @options = { :image_size => { :width => 123, :height => 987 } } | |
131 | raw_info = { 'name' => 'Fred Smith', 'id' => '321' } | |
132 | strategy.stubs(:raw_info).returns(raw_info) | |
133 | assert_match 'width=123', strategy.info['image'] | |
134 | assert_match 'height=987', strategy.info['image'] | |
135 | assert_match 'http://graph.facebook.com/321/picture?', strategy.info['image'] | |
136 | end | |
137 | end | |
138 | ||
139 | class InfoTestOptionalDataPresent < StrategyTestCase | |
140 | def setup | |
141 | super | |
142 | @raw_info ||= { 'name' => 'Fred Smith' } | |
143 | strategy.stubs(:raw_info).returns(@raw_info) | |
144 | end | |
145 | ||
146 | test 'returns the name' do | |
147 | assert_equal 'Fred Smith', strategy.info['name'] | |
148 | end | |
149 | ||
150 | test 'returns the email' do | |
151 | @raw_info['email'] = 'fred@smith.com' | |
152 | assert_equal 'fred@smith.com', strategy.info['email'] | |
153 | end | |
154 | ||
155 | test 'returns the username as nickname' do | |
156 | @raw_info['username'] = 'fredsmith' | |
157 | assert_equal 'fredsmith', strategy.info['nickname'] | |
158 | end | |
159 | ||
160 | test 'returns the first name' do | |
161 | @raw_info['first_name'] = 'Fred' | |
162 | assert_equal 'Fred', strategy.info['first_name'] | |
163 | end | |
164 | ||
165 | test 'returns the last name' do | |
166 | @raw_info['last_name'] = 'Smith' | |
167 | assert_equal 'Smith', strategy.info['last_name'] | |
168 | end | |
169 | ||
170 | test 'returns the location name as location' do | |
171 | @raw_info['location'] = { 'id' => '104022926303756', 'name' => 'Palo Alto, California' } | |
172 | assert_equal 'Palo Alto, California', strategy.info['location'] | |
173 | end | |
174 | ||
175 | test 'returns bio as description' do | |
176 | @raw_info['bio'] = 'I am great' | |
177 | assert_equal 'I am great', strategy.info['description'] | |
178 | end | |
179 | ||
180 | test 'returns the facebook avatar url' do | |
181 | @raw_info['id'] = '321' | |
182 | assert_equal 'http://graph.facebook.com/321/picture', strategy.info['image'] | |
183 | end | |
184 | ||
185 | test 'returns the Facebook link as the Facebook url' do | |
186 | @raw_info['link'] = 'http://www.facebook.com/fredsmith' | |
187 | assert_kind_of Hash, strategy.info['urls'] | |
188 | assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook'] | |
189 | end | |
190 | ||
191 | test 'returns website url' do | |
192 | @raw_info['website'] = 'https://my-wonderful-site.com' | |
193 | assert_kind_of Hash, strategy.info['urls'] | |
194 | assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website'] | |
195 | end | |
196 | ||
197 | test 'return both Facebook link and website urls' do | |
198 | @raw_info['link'] = 'http://www.facebook.com/fredsmith' | |
199 | @raw_info['website'] = 'https://my-wonderful-site.com' | |
200 | assert_kind_of Hash, strategy.info['urls'] | |
201 | assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook'] | |
202 | assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website'] | |
203 | end | |
204 | ||
205 | test 'returns the positive verified status' do | |
206 | @raw_info['verified'] = true | |
207 | assert strategy.info['verified'] | |
208 | end | |
209 | ||
210 | test 'returns the negative verified status' do | |
211 | @raw_info['verified'] = false | |
212 | refute strategy.info['verified'] | |
213 | end | |
214 | end | |
215 | ||
216 | class InfoTestOptionalDataNotPresent < StrategyTestCase | |
217 | def setup | |
218 | super | |
219 | @raw_info ||= { 'name' => 'Fred Smith' } | |
220 | strategy.stubs(:raw_info).returns(@raw_info) | |
221 | end | |
222 | ||
223 | test 'has no email key' do | |
224 | refute_has_key 'email', strategy.info | |
225 | end | |
226 | ||
227 | test 'has no nickname key' do | |
228 | refute_has_key 'nickname', strategy.info | |
229 | end | |
230 | ||
231 | test 'has no first name key' do | |
232 | refute_has_key 'first_name', strategy.info | |
233 | end | |
234 | ||
235 | test 'has no last name key' do | |
236 | refute_has_key 'last_name', strategy.info | |
237 | end | |
238 | ||
239 | test 'has no location key' do | |
240 | refute_has_key 'location', strategy.info | |
241 | end | |
242 | ||
243 | test 'has no description key' do | |
244 | refute_has_key 'description', strategy.info | |
245 | end | |
246 | ||
247 | test 'has no urls' do | |
248 | refute_has_key 'urls', strategy.info | |
249 | end | |
250 | ||
251 | test 'has no verified key' do | |
252 | refute_has_key 'verified', strategy.info | |
253 | end | |
254 | end | |
255 | ||
256 | class RawInfoTest < StrategyTestCase | |
257 | def setup | |
258 | super | |
259 | @access_token = stub('OAuth2::AccessToken') | |
260 | @appsecret_proof = 'appsecret_proof' | |
261 | @options = {:appsecret_proof => @appsecret_proof} | |
262 | end | |
263 | ||
264 | test 'performs a GET to https://graph.facebook.com/me' do | |
265 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
266 | strategy.stubs(:access_token).returns(@access_token) | |
267 | params = {:params => @options} | |
268 | @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) | |
269 | strategy.raw_info | |
270 | end | |
271 | ||
272 | test 'performs a GET to https://graph.facebook.com/me with locale' do | |
273 | @options.merge!({ :locale => 'cs_CZ' }) | |
274 | strategy.stubs(:access_token).returns(@access_token) | |
275 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
276 | params = {:params => @options} | |
277 | @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) | |
278 | strategy.raw_info | |
279 | end | |
280 | ||
281 | test 'performs a GET to https://graph.facebook.com/me with info_fields' do | |
282 | @options.merge!({:info_fields => 'about'}) | |
283 | strategy.stubs(:access_token).returns(@access_token) | |
284 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
285 | params = {:params => {:appsecret_proof => @appsecret_proof, :fields => 'about'}} | |
286 | @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) | |
287 | strategy.raw_info | |
288 | end | |
289 | ||
290 | test 'returns a Hash' do | |
291 | strategy.stubs(:access_token).returns(@access_token) | |
292 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
293 | raw_response = stub('Faraday::Response') | |
294 | raw_response.stubs(:body).returns('{ "ohai": "thar" }') | |
295 | raw_response.stubs(:status).returns(200) | |
296 | raw_response.stubs(:headers).returns({'Content-Type' => 'application/json' }) | |
297 | oauth2_response = OAuth2::Response.new(raw_response) | |
298 | params = {:params => @options} | |
299 | @access_token.stubs(:get).with('me', params).returns(oauth2_response) | |
300 | assert_kind_of Hash, strategy.raw_info | |
301 | assert_equal 'thar', strategy.raw_info['ohai'] | |
302 | end | |
303 | ||
304 | test 'returns an empty hash when the response is false' do | |
305 | strategy.stubs(:access_token).returns(@access_token) | |
306 | strategy.stubs(:appsecret_proof).returns(@appsecret_proof) | |
307 | oauth2_response = stub('OAuth2::Response', :parsed => false) | |
308 | params = {:params => @options} | |
309 | @access_token.stubs(:get).with('me', params).returns(oauth2_response) | |
310 | assert_kind_of Hash, strategy.raw_info | |
311 | assert_equal({}, strategy.raw_info) | |
312 | end | |
313 | ||
314 | test 'should not include raw_info in extras hash when skip_info is specified' do | |
315 | @options = { :skip_info => true } | |
316 | strategy.stubs(:raw_info).returns({:foo => 'bar' }) | |
317 | refute_has_key 'raw_info', strategy.extra | |
318 | end | |
319 | end | |
320 | ||
321 | class CredentialsTest < StrategyTestCase | |
322 | def setup | |
323 | super | |
324 | @access_token = stub('OAuth2::AccessToken') | |
325 | @access_token.stubs(:token) | |
326 | @access_token.stubs(:expires?) | |
327 | @access_token.stubs(:expires_at) | |
328 | @access_token.stubs(:refresh_token) | |
329 | strategy.stubs(:access_token).returns(@access_token) | |
330 | end | |
331 | ||
332 | test 'returns a Hash' do | |
333 | assert_kind_of Hash, strategy.credentials | |
334 | end | |
335 | ||
336 | test 'returns the token' do | |
337 | @access_token.stubs(:token).returns('123') | |
338 | assert_equal '123', strategy.credentials['token'] | |
339 | end | |
340 | ||
341 | test 'returns the expiry status' do | |
342 | @access_token.stubs(:expires?).returns(true) | |
343 | assert strategy.credentials['expires'] | |
344 | ||
345 | @access_token.stubs(:expires?).returns(false) | |
346 | refute strategy.credentials['expires'] | |
347 | end | |
348 | ||
349 | test 'returns the refresh token and expiry time when expiring' do | |
350 | ten_mins_from_now = (Time.now + 600).to_i | |
351 | @access_token.stubs(:expires?).returns(true) | |
352 | @access_token.stubs(:refresh_token).returns('321') | |
353 | @access_token.stubs(:expires_at).returns(ten_mins_from_now) | |
354 | assert_equal '321', strategy.credentials['refresh_token'] | |
355 | assert_equal ten_mins_from_now, strategy.credentials['expires_at'] | |
356 | end | |
357 | ||
358 | test 'does not return the refresh token when test is nil and expiring' do | |
359 | @access_token.stubs(:expires?).returns(true) | |
360 | @access_token.stubs(:refresh_token).returns(nil) | |
361 | assert_nil strategy.credentials['refresh_token'] | |
362 | refute_has_key 'refresh_token', strategy.credentials | |
363 | end | |
364 | ||
365 | test 'does not return the refresh token when not expiring' do | |
366 | @access_token.stubs(:expires?).returns(false) | |
367 | @access_token.stubs(:refresh_token).returns('XXX') | |
368 | assert_nil strategy.credentials['refresh_token'] | |
369 | refute_has_key 'refresh_token', strategy.credentials | |
370 | end | |
371 | end | |
372 | ||
373 | class ExtraTest < StrategyTestCase | |
374 | def setup | |
375 | super | |
376 | @raw_info = { 'name' => 'Fred Smith' } | |
377 | strategy.stubs(:raw_info).returns(@raw_info) | |
378 | end | |
379 | ||
380 | test 'returns a Hash' do | |
381 | assert_kind_of Hash, strategy.extra | |
382 | end | |
383 | ||
384 | test 'contains raw info' do | |
385 | assert_equal({ 'raw_info' => @raw_info }, strategy.extra) | |
386 | end | |
387 | end | |
388 | ||
389 | module SignedRequestHelpers | |
390 | def signed_request(payload, secret) | |
391 | encoded_payload = base64_encode_url(MultiJson.encode(payload)) | |
392 | encoded_signature = base64_encode_url(signature(encoded_payload, secret)) | |
393 | [encoded_signature, encoded_payload].join('.') | |
394 | end | |
395 | ||
396 | def base64_encode_url(value) | |
397 | Base64.encode64(value).tr('+/', '-_').gsub(/\n/, '') | |
398 | end | |
399 | ||
400 | def signature(payload, secret, algorithm = OpenSSL::Digest::SHA256.new) | |
401 | OpenSSL::HMAC.digest(algorithm, secret, payload) | |
402 | end | |
403 | end | |
404 | ||
405 | module SignedRequestTests | |
406 | class TestCase < StrategyTestCase | |
407 | include SignedRequestHelpers | |
408 | end | |
409 | ||
410 | class CookieAndParamNotPresentTest < TestCase | |
411 | test 'is nil' do | |
412 | assert_nil strategy.send(:signed_request_from_cookie) | |
413 | end | |
414 | ||
415 | test 'throws an error on calling build_access_token' do | |
416 | assert_raises(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError) { strategy.send(:with_authorization_code!) {} } | |
417 | end | |
418 | end | |
419 | ||
420 | class CookiePresentTest < TestCase | |
421 | def setup(algo = nil) | |
422 | super() | |
423 | @payload = { | |
424 | 'algorithm' => algo || 'HMAC-SHA256', | |
425 | 'code' => 'm4c0d3z', | |
426 | 'issued_at' => Time.now.to_i, | |
427 | 'user_id' => '123456' | |
428 | } | |
429 | ||
430 | @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) | |
431 | end | |
432 | ||
433 | test 'parses the access code out from the cookie' do | |
434 | assert_equal @payload, strategy.send(:signed_request_from_cookie) | |
435 | end | |
436 | ||
437 | test 'throws an error if the algorithm is unknown' do | |
438 | setup('UNKNOWN-ALGO') | |
439 | assert_equal "unknown algorithm: UNKNOWN-ALGO", assert_raises(OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError) { strategy.send(:signed_request_from_cookie) }.message | |
440 | end | |
441 | end | |
442 | ||
443 | class EmptySignedRequestTest < TestCase | |
444 | def setup | |
445 | super | |
446 | @request.stubs(:params).returns({'signed_request' => ''}) | |
447 | end | |
448 | ||
449 | test 'empty param' do | |
450 | assert_equal nil, strategy.send(:signed_request_from_cookie) | |
451 | end | |
452 | end | |
453 | ||
454 | class MissingCodeInParamsRequestTest < TestCase | |
455 | def setup | |
456 | super | |
457 | @request.stubs(:params).returns({}) | |
458 | end | |
459 | ||
460 | test 'calls fail! when a code is not included in the params' do | |
461 | strategy.expects(:fail!).times(1).with(:no_authorization_code, kind_of(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError)) | |
462 | strategy.callback_phase | |
463 | end | |
464 | end | |
465 | ||
466 | class MissingCodeInCookieRequestTest < TestCase | |
467 | def setup(algo = nil) | |
468 | super() | |
469 | @payload = { | |
470 | 'algorithm' => algo || 'HMAC-SHA256', | |
471 | 'code' => nil, | |
472 | 'issued_at' => Time.now.to_i, | |
473 | 'user_id' => '123456' | |
474 | } | |
475 | ||
476 | @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) | |
477 | end | |
478 | ||
479 | test 'calls fail! when a code is not included in the cookie' do | |
480 | strategy.expects(:fail!).times(1).with(:no_authorization_code, kind_of(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError)) | |
481 | strategy.callback_phase | |
482 | end | |
483 | end | |
484 | ||
485 | class UnknownAlgorithmInCookieRequestTest < TestCase | |
486 | def setup | |
487 | super() | |
488 | @payload = { | |
489 | 'algorithm' => 'UNKNOWN-ALGO', | |
490 | 'code' => nil, | |
491 | 'issued_at' => Time.now.to_i, | |
492 | 'user_id' => '123456' | |
493 | } | |
494 | ||
495 | @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) | |
496 | end | |
497 | ||
498 | test 'calls fail! when an algorithm is unknown' do | |
499 | strategy.expects(:fail!).times(1).with(:unknown_signature_algorithm, kind_of(OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError)) | |
500 | strategy.callback_phase | |
501 | end | |
502 | end | |
503 | end |