Class: Koala::Facebook::OAuth

Inherits:
Object
  • Object
show all
Defined in:
lib/koala/oauth.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app_id, app_secret, oauth_callback_url = nil) ⇒ OAuth

Returns a new instance of OAuth.



5
6
7
8
9
# File 'lib/koala/oauth.rb', line 5

def initialize(app_id, app_secret, oauth_callback_url = nil)
  @app_id = app_id
  @app_secret = app_secret
  @oauth_callback_url = oauth_callback_url
end

Instance Attribute Details

#app_idObject (readonly)

Returns the value of attribute app_id.



4
5
6
# File 'lib/koala/oauth.rb', line 4

def app_id
  @app_id
end

#app_secretObject (readonly)

Returns the value of attribute app_secret.



4
5
6
# File 'lib/koala/oauth.rb', line 4

def app_secret
  @app_secret
end

#oauth_callback_urlObject (readonly)

Returns the value of attribute oauth_callback_url.



4
5
6
# File 'lib/koala/oauth.rb', line 4

def oauth_callback_url
  @oauth_callback_url
end

Instance Method Details

#get_access_token(code, options = {}) ⇒ Object



64
65
66
67
68
69
# File 'lib/koala/oauth.rb', line 64

def get_access_token(code, options = {})
  # upstream methods will throw errors if needed
  if info = get_access_token_info(code, options)
    string = info["access_token"]
  end
end

#get_access_token_info(code, options = {}) ⇒ Object



58
59
60
61
62
# File 'lib/koala/oauth.rb', line 58

def get_access_token_info(code, options = {})
  # convenience method to get a parsed token from Facebook for a given code
  # should this require an OAuth callback URL?
  get_token_from_server({:code => code, :redirect_uri => options[:redirect_uri] || @oauth_callback_url}, false, options)
end

#get_app_access_token(options = {}) ⇒ Object



76
77
78
79
80
# File 'lib/koala/oauth.rb', line 76

def get_app_access_token(options = {})
  if info = get_app_access_token_info(options)
    string = info["access_token"]
  end
end

#get_app_access_token_info(options = {}) ⇒ Object



71
72
73
74
# File 'lib/koala/oauth.rb', line 71

def get_app_access_token_info(options = {})
  # convenience method to get a the application's sessionless access token
  get_token_from_server({:type => 'client_cred'}, true, options)
end

#get_token_from_session_key(session, options = {}) ⇒ Object



129
130
131
132
133
# File 'lib/koala/oauth.rb', line 129

def get_token_from_session_key(session, options = {})
  # convenience method for a single key
  # gets the overlaoded strings automatically
  get_tokens_from_session_keys([session], options)[0]
end

#get_token_info_from_session_keys(sessions, options = {}) ⇒ Object

from session keys



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/koala/oauth.rb', line 104

def get_token_info_from_session_keys(sessions, options = {})
  # fetch the OAuth tokens from Facebook
  response = fetch_token_string({
    :type => 'client_cred',
    :sessions => sessions.join(",")
  }, true, "exchange_sessions", options)

  # Facebook returns an empty body in certain error conditions
  if response == ""
    raise APIError.new({
      "type" => "ArgumentError",
      "message" => "get_token_from_session_key received an error (empty response body) for sessions #{sessions.inspect}!"
    })
  end

  MultiJson.decode(response)
end

#get_tokens_from_session_keys(sessions, options = {}) ⇒ Object



122
123
124
125
126
127
# File 'lib/koala/oauth.rb', line 122

def get_tokens_from_session_keys(sessions, options = {})
  # get the original hash results
  results = get_token_info_from_session_keys(sessions, options)
  # now recollect them as just the access tokens
  results.collect { |r| r ? r["access_token"] : nil }
end


28
29
30
31
32
33
# File 'lib/koala/oauth.rb', line 28

def get_user_from_cookie(cookies)
  if info = (cookies)
    # signed cookie has user_id, unsigned cookie has uid
    string = info["user_id"] || info["uid"]
  end
end


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/koala/oauth.rb', line 11

def (cookie_hash)
  # Parses the cookie set Facebook's JavaScript SDK.
  # You can pass Rack/Rails/Sinatra's cookie hash directly to this method.
  #
  # If the user is logged in via Facebook, we return a dictionary with the
  # keys "uid" and "access_token". The former is the user's Facebook ID,
  # and the latter can be used to make authenticated requests to the Graph API.
  # If the user is not logged in, we return None.

  if signed_cookie = cookie_hash["fbsr_#{@app_id}"]
    parse_signed_cookie(signed_cookie)
  elsif unsigned_cookie = cookie_hash["fbs_#{@app_id}"]
    parse_unsigned_cookie(unsigned_cookie)
  end
end

#parse_signed_request(input) ⇒ Object

Originally provided directly by Facebook, however this has changed as their concept of crypto changed. For historic purposes, this is their proposal: developers.facebook.com/docs/authentication/canvas/encryption_proposal/ Currently see github.com/facebook/php-sdk/blob/master/src/facebook.php#L758 for a more accurate reference implementation strategy.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/koala/oauth.rb', line 87

def parse_signed_request(input)
  encoded_sig, encoded_envelope = input.split('.', 2)
  raise 'SignedRequest: Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope

  signature = base64_url_decode(encoded_sig).unpack("H*").first
  envelope = MultiJson.decode(base64_url_decode(encoded_envelope))

  raise "SignedRequest: Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'

  # now see if the signature is valid (digest, key, data)
  hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, @app_secret, encoded_envelope)
  raise 'SignedRequest: Invalid signature' if (signature != hmac)

  envelope
end

#url_for_access_token(code, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


51
52
53
54
55
56
# File 'lib/koala/oauth.rb', line 51

def url_for_access_token(code, options = {})
  # Creates the URL for the token corresponding to a given code generated by Facebook
  callback = options[:callback] || @oauth_callback_url
  raise ArgumentError, "url_for_access_token must get a callback either from the OAuth object or in the parameters!" unless callback
  "https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
end

#url_for_oauth_code(options = {}) ⇒ Object

URLs

Raises:

  • (ArgumentError)


38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/koala/oauth.rb', line 38

def url_for_oauth_code(options = {})
  # for permissions, see http://developers.facebook.com/docs/authentication/permissions
  permissions = options[:permissions]
  scope = permissions ? "&scope=#{permissions.is_a?(Array) ? permissions.join(",") : permissions}" : ""
  display = options.has_key?(:display) ? "&display=#{options[:display]}" : ""

  callback = options[:callback] || @oauth_callback_url
  raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback

  # Creates the URL for oauth authorization for a given callback and optional set of permissions
  "https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}#{display}"
end