koala 1.0.0.beta2 → 1.0.0.beta2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/Rakefile +1 -1
- data/koala.gemspec +2 -2
- data/lib/koala.rb +17 -31
- data/lib/koala/http_services.rb +0 -6
- data/spec/facebook_data.yml +17 -19
- data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +1 -1
- data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +2 -2
- data/spec/koala/http_services/net_http_service_tests.rb +2 -2
- data/spec/koala/oauth/oauth_tests.rb +3 -40
- data/spec/koala_spec_helper.rb +2 -2
- data/spec/mock_facebook_responses.yml +2 -2
- metadata +4 -3
data/CHANGELOG
CHANGED
@@ -19,6 +19,7 @@ Internal improvements:
|
|
19
19
|
-- Beta 2: photo and file uploads now accept symbols as well as strings overall
|
20
20
|
-- Beta 2: APIError is now < StandardError, not Exception
|
21
21
|
-- Beta 2: Added KoalaError for non-API errors
|
22
|
+
-- Beta 3: Updated parse_signed_request to match Facebook's current implementation (thanks, imajes!)
|
22
23
|
Test improvements:
|
23
24
|
-- Expanded HTTP service tests (added Typhoeus test suite and additional Net::HTTP test cases)
|
24
25
|
-- Live tests now verify that the access token has the necessary permissions before starting
|
data/Rakefile
CHANGED
@@ -4,7 +4,7 @@ require 'rake'
|
|
4
4
|
require 'echoe'
|
5
5
|
|
6
6
|
# gem management
|
7
|
-
Echoe.new('koala', '1.0.0.beta2') do |p|
|
7
|
+
Echoe.new('koala', '1.0.0.beta2.1') do |p|
|
8
8
|
p.summary = "A lightweight, flexible library for Facebook with support for the Graph API, the old REST API, realtime updates, and OAuth validation."
|
9
9
|
p.description = "Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph API and the older REST API, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services."
|
10
10
|
p.url = "http://github.com/arsduo/koala"
|
data/koala.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{koala}
|
5
|
-
s.version = "1.0.0.beta2"
|
5
|
+
s.version = "1.0.0.beta2.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional"]
|
9
|
-
s.date = %q{2011-
|
9
|
+
s.date = %q{2011-04-06}
|
10
10
|
s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph API and the older REST API, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.}
|
11
11
|
s.email = %q{alex@alexkoppel.com}
|
12
12
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb", "lib/koala/test_users.rb", "lib/koala/uploadable_io.rb"]
|
data/lib/koala.rb
CHANGED
@@ -211,38 +211,24 @@ module Koala
|
|
211
211
|
string = info["access_token"]
|
212
212
|
end
|
213
213
|
end
|
214
|
-
|
215
|
-
# provided directly by Facebook
|
216
|
-
#
|
217
|
-
#
|
218
|
-
|
214
|
+
|
215
|
+
# Originally provided directly by Facebook, however this has changed
|
216
|
+
# as their concept of crypto changed. For historic purposes, this is their proposal:
|
217
|
+
# https://developers.facebook.com/docs/authentication/canvas/encryption_proposal/
|
218
|
+
# Currently see https://github.com/facebook/php-sdk/blob/master/src/facebook.php#L758
|
219
|
+
# for a more accurate reference implementation strategy.
|
220
|
+
def parse_signed_request(input)
|
219
221
|
encoded_sig, encoded_envelope = input.split('.', 2)
|
222
|
+
signature = base64_url_decode(encoded_sig).unpack("H*").first
|
220
223
|
envelope = JSON.parse(base64_url_decode(encoded_envelope))
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
raise 'Invalid
|
227
|
-
|
228
|
-
|
229
|
-
raise 'Invalid request. (Invalid signature.)' \
|
230
|
-
if base64_url_decode(encoded_sig) !=
|
231
|
-
OpenSSL::HMAC.hexdigest(
|
232
|
-
'sha256', @app_secret, encoded_envelope).split.pack('H*')
|
233
|
-
|
234
|
-
# for requests that are signed, but not encrypted, we're done
|
235
|
-
return envelope if algorithm == 'HMAC-SHA256'
|
236
|
-
|
237
|
-
# otherwise, decrypt the payload
|
238
|
-
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
|
239
|
-
cipher.decrypt
|
240
|
-
cipher.key = @app_secret
|
241
|
-
cipher.iv = base64_url_decode(envelope['iv'])
|
242
|
-
cipher.padding = 0
|
243
|
-
decrypted_data = cipher.update(base64_url_decode(envelope['payload']))
|
244
|
-
decrypted_data << cipher.final
|
245
|
-
return JSON.parse(decrypted_data.strip)
|
224
|
+
|
225
|
+
raise "SignedRequest: Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
|
226
|
+
|
227
|
+
# now see if the signature is valid (digest, key, data)
|
228
|
+
hmac = OpenSSL::HMAC.hexdigest('sha256', @app_secret, encoded_envelope.tr("-_", "+/"))
|
229
|
+
raise 'SignedRequest: Invalid signature' if (signature != hmac)
|
230
|
+
|
231
|
+
return envelope
|
246
232
|
end
|
247
233
|
|
248
234
|
# from session keys
|
@@ -309,7 +295,7 @@ module Koala
|
|
309
295
|
# directly from https://github.com/facebook/crypto-request-examples/raw/master/sample.rb
|
310
296
|
def base64_url_decode(str)
|
311
297
|
str += '=' * (4 - str.length.modulo(4))
|
312
|
-
Base64.decode64(str.
|
298
|
+
Base64.decode64(str.tr('-_', '+/'))
|
313
299
|
end
|
314
300
|
end
|
315
301
|
end
|
data/lib/koala/http_services.rb
CHANGED
@@ -57,12 +57,6 @@ module Koala
|
|
57
57
|
http = Net::HTTP.new(server(options), private_request ? 443 : nil)
|
58
58
|
http.use_ssl = true if private_request
|
59
59
|
|
60
|
-
# we turn off certificate validation to avoid the
|
61
|
-
# "warning: peer certificate won't be verified in this SSL session" warning
|
62
|
-
# not sure if this is the right way to handle it
|
63
|
-
# see http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
|
64
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
65
|
-
|
66
60
|
result = http.start do |http|
|
67
61
|
response, body = if verb == "post"
|
68
62
|
if params_require_multipart? args
|
data/spec/facebook_data.yml
CHANGED
@@ -5,18 +5,18 @@
|
|
5
5
|
|
6
6
|
# You must supply this value yourself to test the GraphAPI class.
|
7
7
|
# Your OAuth token should have publish_stream, read_stream, and user_photos permissions.
|
8
|
-
oauth_token:
|
8
|
+
oauth_token: 119908831367602|2.SzVOt20se6d7VnLzsG3USg__.3600.1302102000-2905623|Qxhc8NPxIQFKuNOaL1XdYNcztAM
|
9
9
|
|
10
10
|
# for testing the OAuth class
|
11
11
|
# baseline app
|
12
12
|
oauth_test_data:
|
13
13
|
# You must supply this value yourself, since they will expire.
|
14
|
-
code:
|
14
|
+
code: 2.SzVOt20se6d7VnLzsG3USg__.3600.1302102000-2905623|Z5x3PcJgROjfj6DOwVQpb714nkQ
|
15
15
|
# easiest way to get session keys: use multiple test accounts with the Javascript login at http://oauth.twoalex.com
|
16
|
-
session_key:
|
16
|
+
session_key: 2.SzVOt20se6d7VnLzsG3USg__.3600.1302102000-2905623
|
17
17
|
multiple_session_keys:
|
18
|
-
-
|
19
|
-
-
|
18
|
+
- 2.SzVOt20se6d7VnLzsG3USg__.3600.1302102000-2905623
|
19
|
+
- 2.SzVOt20se6d7VnLzsG3USg__.3600.1302102000-2905623
|
20
20
|
|
21
21
|
# These values will work out of the box
|
22
22
|
app_id: 119908831367602
|
@@ -35,23 +35,21 @@ oauth_test_data:
|
|
35
35
|
# note: I've revoked the offline access for security reasons, so you can't make calls against this :)
|
36
36
|
fbs_119908831367602: '"access_token=119908831367602|08170230801eb225068e7a70-2905623|Q3LDCYYF8CX9cstxnZLsxiR0nwg.&expires=0&secret=78abaee300b392e275072a9f2727d436&session_key=08170230801eb225068e7a70-2905623&sig=423b8aa4b6fa1f9a571955f8e929d567&uid=2905623"'
|
37
37
|
|
38
|
-
# These values will work out of the box
|
39
|
-
# They're from Facebook's example at http://developers.facebook.com/docs/authentication/canvas
|
38
|
+
# These values from the OAuth Playground (see above) will work out of the box
|
40
39
|
# You can update this to live data if desired
|
41
40
|
# request_secret is optional and will fall back to the secret above if absent
|
42
|
-
|
43
|
-
signed_request: "vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0"
|
44
|
-
signed_request_result:
|
45
|
-
"0": payload
|
46
|
-
algorithm: HMAC-SHA256
|
47
|
-
# signed params
|
48
|
-
# examples from http://developers.facebook.com/docs/authentication/canvas/encryption_proposal
|
49
|
-
signed_params: t63pZQ4Q3ZTHJt0hOsKrY2pb28xRlduW0pg4lL_Zhl4.eyJhbGdvcml0aG0iOiJBRVMtMjU2LUNCQyBITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTI4NzYwMTk4OCwiaXYiOiJmRExKQ1cteWlYbXVOYTI0ZVNhckpnIiwicGF5bG9hZCI6IllHeW00cG9Rbk1UckVnaUFPa0ZUVkk4NWxsNVJ1VWlFbC1JZ3FmeFRPVEhRTkl2VlZJOFk4a1Z1T29lS2FXT2Vhc3NXRlRFdjBRZ183d0NDQkVlbjdsVUJCemxGSjFWNjNISjNBZjBTSW5nY3hXVEo3TDZZTGF0TW13WGdEQXZXbjVQc2ZxeldrNG1sOWg5RExuWXB0V0htREdMNmlCaU9oTjdXeUk3cDZvRXBWcmlGdUp3X2NoTG9QYjhhM3ZHRG5vVzhlMlN4eDA2QTJ4MnhraWFwdmcifQ
|
50
|
-
signed_params_secret: 13750c9911fec5865d01f3bd00bdf4db
|
41
|
+
signed_params: "zWRm0gd5oHW_jzXP_WA9CirO7c5CLHotn-SKRqH2NmU.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDE5MjIwMDAsImlzc3VlZF9hdCI6MTMwMTkxNzI5OSwib2F1dGhfdG9rZW4iOiIxMTk5MDg4MzEzNjc2MDJ8Mi56VkZfNk5yTUVMSHVKYTRnSVU5dEt3X18uMzYwMC4xMzAxOTIyMDAwLTI5MDU2MjN8emdxUHNyMkJHOUxvT0s5a2VrR2dSVVJaeDBrIiwidXNlciI6eyJjb3VudHJ5IjoiZGUiLCJsb2NhbGUiOiJkZV9ERSIsImFnZSI6eyJtaW4iOjIxfX0sInVzZXJfaWQiOiIyOTA1NjIzIn0"
|
51
42
|
signed_params_result:
|
52
|
-
|
53
|
-
|
54
|
-
|
43
|
+
expires: 1301922000
|
44
|
+
algorithm: HMAC-SHA256
|
45
|
+
user_id: "2905623"
|
46
|
+
oauth_token: 119908831367602|2.zVF_6NrMELHuJa4gIU9tKw__.3600.1301922000-2905623|zgqPsr2BG9LoOK9kekGgRURZx0k
|
47
|
+
user:
|
48
|
+
country: de
|
49
|
+
locale: de_DE
|
50
|
+
age:
|
51
|
+
min: 21
|
52
|
+
issued_at: 1301917299
|
55
53
|
|
56
54
|
subscription_test_data:
|
57
55
|
subscription_path: http://oauth.twoalex.com/subscriptions
|
@@ -22,7 +22,7 @@ shared_examples_for "Koala GraphAPI without an access token" do
|
|
22
22
|
# these are not strictly necessary as the other put methods resolve to put_object, but are here for completeness
|
23
23
|
it "should not be able to post to a feed" do
|
24
24
|
(lambda do
|
25
|
-
attachment = {:name => "
|
25
|
+
attachment = {:name => "OAuth Playground", :link => "http://www.oauth.twoalex.com/"}
|
26
26
|
@result = @api.put_wall_post("Hello, world", attachment, "contextoptional")
|
27
27
|
end).should raise_error(Koala::Facebook::APIError)
|
28
28
|
puts "Error! Object #{@result.inspect} somehow put onto Context Optional's wall!" if @result
|
@@ -55,7 +55,7 @@ shared_examples_for "Koala GraphAPI with an access token" do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should be able to post a message with an attachment to a feed" do
|
58
|
-
result = @api.put_wall_post("Hello, world, from the test suite again!", {:name => "
|
58
|
+
result = @api.put_wall_post("Hello, world, from the test suite again!", {:name => "OAuth Playground", :link => "http://oauth.twoalex.com/"})
|
59
59
|
@temporary_object_id = result["id"]
|
60
60
|
@temporary_object_id.should_not be_nil
|
61
61
|
end
|
@@ -93,7 +93,7 @@ shared_examples_for "Koala GraphAPI with an access token" do
|
|
93
93
|
end
|
94
94
|
|
95
95
|
it "should be able to verify a message with an attachment posted to a feed" do
|
96
|
-
attachment = {"name" => "
|
96
|
+
attachment = {"name" => "OAuth Playground", "link" => "http://oauth.twoalex.com/"}
|
97
97
|
result = @api.put_wall_post("Hello, world, from the test suite again!", attachment)
|
98
98
|
@temporary_object_id = result["id"]
|
99
99
|
get_result = @api.get_object(@temporary_object_id)
|
@@ -138,8 +138,8 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
138
138
|
Bear.make_request('anything', {}, 'anything', :rest_api => true)
|
139
139
|
end
|
140
140
|
|
141
|
-
it "
|
142
|
-
@http_mock.
|
141
|
+
it "no longer turns off vertificate validaiton warnings" do
|
142
|
+
@http_mock.should_not_receive('verify_mode=')
|
143
143
|
|
144
144
|
Bear.make_request('anything', {}, 'anything')
|
145
145
|
end
|
@@ -10,14 +10,7 @@ class FacebookOAuthTests < Test::Unit::TestCase
|
|
10
10
|
@raw_token_string = @oauth_data["raw_token_string"]
|
11
11
|
@raw_offline_access_token_string = @oauth_data["raw_offline_access_token_string"]
|
12
12
|
|
13
|
-
# per Facebook's example:
|
14
|
-
# http://developers.facebook.com/docs/authentication/canvas
|
15
|
-
# this allows us to use Facebook's example data while running the other live data
|
16
|
-
@request_secret = @oauth_data["request_secret"] || @secret
|
17
|
-
@signed_request = @oauth_data["signed_request"]
|
18
|
-
@signed_request_result = @oauth_data["signed_request_result"]
|
19
13
|
# for signed requests (http://developers.facebook.com/docs/authentication/canvas/encryption_proposal)
|
20
|
-
@signed_params_secret = @oauth_data["signed_params_secret"] || @secret
|
21
14
|
@signed_params = @oauth_data["signed_params"]
|
22
15
|
@signed_params_result = @oauth_data["signed_params_result"]
|
23
16
|
|
@@ -354,12 +347,6 @@ class FacebookOAuthTests < Test::Unit::TestCase
|
|
354
347
|
end
|
355
348
|
|
356
349
|
describe "for parsing signed requests" do
|
357
|
-
before :each do
|
358
|
-
# you can test against live data by updating the YML, or you can use the default data
|
359
|
-
# which tests against Facebook's example on http://developers.facebook.com/docs/authentication/canvas
|
360
|
-
@oauth = Koala::Facebook::OAuth.new(@app_id, @request_secret || @app_secret)
|
361
|
-
end
|
362
|
-
|
363
350
|
# the signed request code comes directly from Facebook
|
364
351
|
# so we only need to test at a high level that it works
|
365
352
|
# signed params refers to http://developers.facebook.com/docs/authentication/canvas
|
@@ -374,34 +361,10 @@ class FacebookOAuthTests < Test::Unit::TestCase
|
|
374
361
|
lambda { @oauth.parse_signed_request(@signed_request) }.should raise_error
|
375
362
|
end
|
376
363
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
end
|
364
|
+
it "properly parses requests" do
|
365
|
+
@oauth = Koala::Facebook::OAuth.new(@app_id, @secret || @app_secret)
|
366
|
+
@oauth.parse_signed_request(@signed_params).should == @signed_params_result
|
381
367
|
end
|
382
|
-
|
383
|
-
describe "for signed requests" do
|
384
|
-
it "should work" do
|
385
|
-
@oauth = Koala::Facebook::OAuth.new(@app_id, @signed_params_secret || @app_secret)
|
386
|
-
@oauth.parse_signed_request(@signed_params).should == @signed_params_result
|
387
|
-
end
|
388
|
-
|
389
|
-
it "should throw an error if the params are too old" do
|
390
|
-
@time.stub!(:to_i).and_return(1287601988 + 4000)
|
391
|
-
@oauth = Koala::Facebook::OAuth.new(@app_id, @signed_params_secret || @app_secret)
|
392
|
-
|
393
|
-
lambda { @oauth.parse_signed_request(@signed_params) }.should raise_error
|
394
|
-
end
|
395
|
-
|
396
|
-
it "should let you specify the max age for a request" do
|
397
|
-
@time.stub!(:to_i).and_return(1287601988 + 4000)
|
398
|
-
@oauth = Koala::Facebook::OAuth.new(@app_id, @signed_params_secret || @app_secret)
|
399
|
-
|
400
|
-
lambda { @oauth.parse_signed_request(@signed_params, 4001) }.should_not raise_error
|
401
|
-
end
|
402
|
-
|
403
|
-
end
|
404
|
-
|
405
368
|
end
|
406
369
|
|
407
370
|
end # describe
|
data/spec/koala_spec_helper.rb
CHANGED
@@ -83,7 +83,7 @@ graph_api:
|
|
83
83
|
message=Hello, world, from the test suite delete method!:
|
84
84
|
post:
|
85
85
|
with_token: '{"id": "FEED_ITEM_DELETE"}'
|
86
|
-
link=http://
|
86
|
+
link=http://oauth.twoalex.com/&message=Hello, world, from the test suite again!&name=OAuth Playground:
|
87
87
|
post:
|
88
88
|
with_token: '{"id": "FEED_ITEM_CONTEXT"}'
|
89
89
|
/me/photos:
|
@@ -238,7 +238,7 @@ graph_api:
|
|
238
238
|
no_args:
|
239
239
|
<<: *item_deleted
|
240
240
|
get:
|
241
|
-
with_token: '{"link":"http://
|
241
|
+
with_token: '{"link":"http://oauth.twoalex.com/", "name": "OAuth Playground"}'
|
242
242
|
|
243
243
|
/FEED_ITEM_CATS:
|
244
244
|
no_args:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: koala
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 124392909
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
@@ -9,7 +9,8 @@ version: !ruby/object:Gem::Version
|
|
9
9
|
- 0
|
10
10
|
- beta
|
11
11
|
- 2
|
12
|
-
|
12
|
+
- 1
|
13
|
+
version: 1.0.0.beta2.1
|
13
14
|
platform: ruby
|
14
15
|
authors:
|
15
16
|
- Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional
|
@@ -17,7 +18,7 @@ autorequire:
|
|
17
18
|
bindir: bin
|
18
19
|
cert_chain: []
|
19
20
|
|
20
|
-
date: 2011-
|
21
|
+
date: 2011-04-06 00:00:00 +02:00
|
21
22
|
default_executable:
|
22
23
|
dependencies:
|
23
24
|
- !ruby/object:Gem::Dependency
|