facebookdp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +76 -0
- data/lib/facebookdp.rb +8 -0
- data/lib/facebookdp/base.rb +56 -0
- data/lib/facebookdp/oauth.rb +35 -0
- data/test/facebookdp_test.rb +94 -0
- metadata +71 -0
data/README.markdown
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Overview
|
2
|
+
|
3
|
+
This gem allows you to authenticate against facebook and then make Graph API calls from ruby
|
4
|
+
|
5
|
+
# Authenticating a user against Facebook to obtain an access\_token
|
6
|
+
|
7
|
+
The goal here is to delegate authentication to Facebook and retrieve a
|
8
|
+
secret OAuth2 `access_token`. In other words, you want your web
|
9
|
+
application to be able to send a user to facebook, and have facebook
|
10
|
+
figure out whether or not they are who they say they are.
|
11
|
+
|
12
|
+
Facebook uses OAuth2 to authenticate users on thirdparty application's
|
13
|
+
behalf. This gem handles the Oauth2 "handshake" with
|
14
|
+
facebook. Basically, here are the steps:
|
15
|
+
|
16
|
+
1) Register you application with Facebook and get your API Key and API Secret
|
17
|
+
|
18
|
+
2) Create Facebook::OAuth object like so:
|
19
|
+
|
20
|
+
@oauth2 ||= Facebookdp::OAuth.new(your-api-key, you-api-secret, 'https://graph.facebook.com', facebook-callback-url)
|
21
|
+
|
22
|
+
The `facebook-callback-url` argument should be something like
|
23
|
+
`http://yourwebapp/facebook-controller/handle-facebook-response`. If
|
24
|
+
you don't specifiy a facebook-callback-url, it will default to
|
25
|
+
`http://localhost:3000/facebook`. So you might want to just stick a
|
26
|
+
controller there when doing development for easy testing.
|
27
|
+
|
28
|
+
3) Next, call `@oauth2.authorize_url`. This should give you a url like
|
29
|
+
this:
|
30
|
+
`https://graph.facebook.com/oauth/authorize?client_id=YOUR_APP_ID&type=web_server&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Ffacebook%2Fcallback`
|
31
|
+
|
32
|
+
4) Now it's time to trade the `client_id` for a Access Token (note the
|
33
|
+
http param named `client_id` in the `authorize_url`). Your web app
|
34
|
+
should redirect the user's browser to the `authorize_url`. Facebook
|
35
|
+
then prompts for a username and password. The user enters a username
|
36
|
+
and password.
|
37
|
+
|
38
|
+
Tip: During development, sometimes it helps to simply copy and paste the `authorize_url` into your
|
39
|
+
browser.
|
40
|
+
|
41
|
+
5a) If the user enters invalid credentials, they'll be redirected back
|
42
|
+
to the `facebook-callback-url` specified above. The request will
|
43
|
+
include a http param named `error_reason` so your application can
|
44
|
+
handle the invalid username and password error appropriately.
|
45
|
+
|
46
|
+
5b) If this is the first time the user has ever logged into your
|
47
|
+
application, they'll be prompted by Facebook whether to allow or deny
|
48
|
+
your web application. After they choose to allow or deny, they'll be
|
49
|
+
redirected to the facebook-callback-url specified above.
|
50
|
+
|
51
|
+
6) Assuming the user entered correct credentials and approved your web
|
52
|
+
application, then they'll be redirected back to the
|
53
|
+
`facebook-callback-url` you specified above. For example, something like this
|
54
|
+
|
55
|
+
http://yourwebapp/facebook-controller/handle-facebook-response?code=dd8490a3a1c82de377f45bc3-1388092492|\_6MST-8QGIQhiKP3ZkdEMou44Uo
|
56
|
+
|
57
|
+
Your web appilcation should parse that access code and hang onto it!
|
58
|
+
|
59
|
+
7) Next, you trade the access code for an `access_token` like so:
|
60
|
+
|
61
|
+
@oauth2_token = @oath2.get_access_token
|
62
|
+
@oauth2_token ||= @oauth2.get_access_token(the-access-code-you-parsed-and-saved)
|
63
|
+
|
64
|
+
# Using this Facebook Gem to make Graph API calls
|
65
|
+
|
66
|
+
First, you have to do the whole OAuth2 song and dance as described above. Once you do that, you should have a OAuth2 `access_token` for the user. You can then use the token to create an instance of the Facebookdp::Base class.
|
67
|
+
|
68
|
+
@client = Facebookdp::Base.new(@oauth2_token)
|
69
|
+
|
70
|
+
Then, simply use the `@client` instance to make Facebook Graph API
|
71
|
+
calls on the user's behalf. For example, you can get all the users
|
72
|
+
friends:
|
73
|
+
|
74
|
+
friends = @client.friends
|
75
|
+
|
76
|
+
|
data/lib/facebookdp.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Facebookdp
|
2
|
+
class Base
|
3
|
+
def initialize(oauth2_access_token)
|
4
|
+
@access_token = oauth2_access_token
|
5
|
+
end
|
6
|
+
|
7
|
+
#
|
8
|
+
# Return current user's account information
|
9
|
+
def my_account
|
10
|
+
@my_account ||= Crack::JSON.parse(get_request("/me"))
|
11
|
+
end
|
12
|
+
|
13
|
+
def my_picture_url
|
14
|
+
@my_picture_url ||= "http://graph.facebook.com/#{my_account['id']}/picture"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get list of hash's id and name keys for each of current_user's friends
|
18
|
+
def friend_ids_and_names
|
19
|
+
@friend_ids ||= Crack::JSON.parse(get_request("/me/friends?fields=id,name"))['data']
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get all information about all your friends. Pass limit
|
23
|
+
def friends(limit=0, offset=0)
|
24
|
+
if(limit<=0)
|
25
|
+
@friends ||= Crack::JSON.parse(get_request("/me/friends"))['data']
|
26
|
+
else
|
27
|
+
#TODO: this isn't working, not sure why
|
28
|
+
@friends ||= Crack::JSON.parse(get_request("/me/friends?limit=#{limit}&offset=#{offset}"))['data']
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Retrieve full information about a friend given their facebook id
|
33
|
+
def friend_info(fbid)
|
34
|
+
Crack::JSON.parse(get_request("/#{fbid}"))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Retrieve last 10 statuses of a friend. Pass in limit to control
|
38
|
+
# number of status returned
|
39
|
+
def friend_statuses(fbid, limit=10)
|
40
|
+
Crack::JSON.parse(get_request("/#{fbid}/statuses?limit=#{limit}"))['data']
|
41
|
+
end
|
42
|
+
|
43
|
+
# Retrieve all statuses published by a friend since the date specified.
|
44
|
+
# TODO: not tested yet
|
45
|
+
def friend_latest_statuses(unix_timestamp)
|
46
|
+
Crack::JSON.parse(get_request("/#{fbid}/statuses?since=#{unix_timestamp}"))
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def get_request(path)
|
52
|
+
@access_token.get(path)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Facebookdp
|
2
|
+
class OAuth
|
3
|
+
attr_accessor :apikey, :apisecret, :graph_api_url, :callback_url, :code
|
4
|
+
|
5
|
+
def initialize(apikey, apisecret, graph_api_url = "https://graph.facebook.com", callback_url = "http://localhost:3000/facebook/callback")
|
6
|
+
@apikey = apikey
|
7
|
+
@apisecret = apisecret
|
8
|
+
@graph_api_url = graph_api_url
|
9
|
+
@callback_url = callback_url
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# client is an instance of an oauth object, but needs to be
|
14
|
+
# authenticated by having a user visit facebook and retrieve a
|
15
|
+
# access code
|
16
|
+
def client
|
17
|
+
@client ||= OAuth2::Client.new(@apikey, @apisecret, :site => @graph_api_url)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Get the url needed to recieve auth token
|
22
|
+
# behind the scenes, oauth2 is passing id and secret
|
23
|
+
def authorize_url
|
24
|
+
client.web_server.authorize_url( :redirect_uri => callback_url )
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Create access_token, and then we're connected
|
29
|
+
def get_access_token(code)
|
30
|
+
@code = code
|
31
|
+
@access_token ||= client.web_server.get_access_token( @code, :redirect_uri => callback_url)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'facebookdp'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class FacebookdpTest < Test::Unit::TestCase
|
6
|
+
# copy valid code here:
|
7
|
+
ACCESS_CODE = ''
|
8
|
+
FACEBOOK_APP_ID = ''
|
9
|
+
FACEBOOK_APP_SECRET = ''
|
10
|
+
class << self
|
11
|
+
def startup
|
12
|
+
unless @oauth2_token
|
13
|
+
@oauth2 ||= Facebookdp::OAuth.new(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET , 'https://graph.facebook.com', 'http://localhost:3000/oauth2_consumers/facebook/callback')
|
14
|
+
expected = "https://graph.facebook.com/oauth/authorize?client_id=#{FACEBOOK_APP_ID}&type=web_server&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Ffacebook%2Fcallback"
|
15
|
+
begin
|
16
|
+
@oauth2_token ||= @oauth2.get_access_token(ACCESS_CODE)
|
17
|
+
@client = Facebookdp::Base.new(@oauth2_token)
|
18
|
+
rescue
|
19
|
+
#TODO: how to know if session is invalid and recover?
|
20
|
+
puts "Copy the following url into your browser to get a valid access token: #{@oauth2.authorize_url}"
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def shutdown
|
27
|
+
# puts 'this runs once at end'
|
28
|
+
end
|
29
|
+
|
30
|
+
def oauth2_token
|
31
|
+
@oauth2_token
|
32
|
+
end
|
33
|
+
|
34
|
+
def client
|
35
|
+
@client
|
36
|
+
end
|
37
|
+
|
38
|
+
def suite
|
39
|
+
mysuite = super
|
40
|
+
def mysuite.run(*args)
|
41
|
+
FacebookdpTest.startup()
|
42
|
+
super
|
43
|
+
FacebookdpTest.shutdown()
|
44
|
+
end
|
45
|
+
mysuite
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def setup
|
50
|
+
# puts 'runs once before each test'
|
51
|
+
end
|
52
|
+
|
53
|
+
def teardown
|
54
|
+
# puts 'runs once after each test'
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_simple
|
58
|
+
assert(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_get_my_account
|
62
|
+
result = self.class.client.my_account
|
63
|
+
assert_equal("Dave Paroulek", result['name'])
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_get_friend_ids
|
67
|
+
result = self.class.client.friend_ids_and_names
|
68
|
+
assert_equal(159, result.size)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_get_friends
|
72
|
+
result = self.class.client.friends
|
73
|
+
assert_equal(159, result.size)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_get_friend_info
|
77
|
+
result = self.class.client.friend_info(1500782)
|
78
|
+
assert_equal(result['name'], "Michael Shafrir")
|
79
|
+
assert_equal(result['first_name'], "Michael")
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_get_friend_statuses
|
83
|
+
result = self.class.client.friend_statuses(1500782, 1)
|
84
|
+
assert_equal(1, result.size)
|
85
|
+
assert_not_nil(result[0]['message'])
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_get_my_picture
|
89
|
+
expected = "http://graph.facebook.com/1388092492/picture"
|
90
|
+
result = self.class.client.my_picture_url
|
91
|
+
assert_equal(expected,result)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: facebookdp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dave Paroulek
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-02 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Consumes the Facebook OAuth2 Graph Rest API
|
23
|
+
email: dave @nospam@ daveparoulek.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- README.markdown
|
32
|
+
- lib/facebookdp/base.rb
|
33
|
+
- lib/facebookdp/oauth.rb
|
34
|
+
- lib/facebookdp.rb
|
35
|
+
- test/facebookdp_test.rb
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://upgradingdave.com
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.7
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Exposes Facebook OAuth2 Graph Rest API and provides ability to authenticate users against Facebook
|
70
|
+
test_files: []
|
71
|
+
|