Skip to content

Commit

Permalink
Merge branch 'fb_exchange_token' of https://github.com/etiennebarrie/…
Browse files Browse the repository at this point in the history
…koala into etiennebarrie-fb_exchange_token

Conflicts:
	lib/koala/oauth.rb
	spec/cases/oauth_spec.rb
  • Loading branch information
arsduo committed Feb 7, 2012
2 parents 97d9303 + 1c404f3 commit c4e0a84
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 84 deletions.
83 changes: 42 additions & 41 deletions lib/koala/oauth.rb
Expand Up @@ -4,12 +4,12 @@

module Koala
module Facebook

DIALOG_HOST = "www.facebook.com"

class OAuth
attr_reader :app_id, :app_secret, :oauth_callback_url

# Creates a new OAuth client.
#
# @param app_id [String, Integer] a Facebook application ID
Expand All @@ -20,14 +20,14 @@ def initialize(app_id, app_secret, oauth_callback_url = nil)
@app_secret = app_secret
@oauth_callback_url = oauth_callback_url
end

# Parses the cookie set Facebook's JavaScript SDK.
#
# @note in parsing Facebook's new signed cookie format this method has to make a request to Facebook.
# We recommend storing authenticated user info in your Rails session (or equivalent) and only
# calling this when needed.
#
# @param cookie_hash a set of cookies that includes the Facebook cookie.
# @param cookie_hash a set of cookies that includes the Facebook cookie.
# You can pass Rack/Rails/Sinatra's cookie hash directly to this method.
#
# @return the authenticated user's information as a hash, or nil.
Expand Down Expand Up @@ -60,21 +60,21 @@ def get_user_from_cookies(cookies)
alias_method :get_user_from_cookie, :get_user_from_cookies

# URLs

# Builds an OAuth URL, where users will be prompted to log in and for any desired permissions.
# When the users log in, you receive a callback with their
# When the users log in, you receive a callback with their
# See http://developers.facebook.com/docs/authentication/.
#
# @see #url_for_access_token
#
# @note The server-side authentication and dialog methods should only be used
# @note The server-side authentication and dialog methods should only be used
# if your application can't use the Facebook Javascript SDK,
# which provides a much better user experience.
# See http://developers.facebook.com/docs/reference/javascript/.
#
# @param options any query values to add to the URL, as well as any special/required values listed below.
# @option options permissions an array or comma-separated string of desired permissions
#
#
# @raise ArgumentError if no OAuth callback was specified in OAuth#new or in options as :redirect_uri
#
# @return an OAuth URL you can send your users to
Expand All @@ -84,17 +84,17 @@ def url_for_oauth_code(options = {})
options[:scope] = permissions.is_a?(Array) ? permissions.join(",") : permissions
end
url_options = {:client_id => @app_id}.merge(options)

# Creates the URL for oauth authorization for a given callback and optional set of permissions
build_url("https://#{GRAPH_SERVER}/oauth/authorize", true, url_options)
end

# Once you receive an OAuth code, you need to redeem it from Facebook using an appropriate URL.
# (This is done by your server behind the scenes.)
# See http://developers.facebook.com/docs/authentication/.
#
#
# @see #url_for_oauth_code
#
#
# @note (see #url_for_oauth_code)
#
# @param code an OAuth code received from Facebook
Expand All @@ -106,7 +106,7 @@ def url_for_oauth_code(options = {})
def url_for_access_token(code, options = {})
# Creates the URL for the token corresponding to a given code generated by Facebook
url_options = {
:client_id => @app_id,
:client_id => @app_id,
:code => code,
:client_secret => @app_secret
}.merge(options)
Expand All @@ -115,7 +115,7 @@ def url_for_access_token(code, options = {})

# Builds a URL for a given dialog (feed, friends, OAuth, pay, send, etc.)
# See http://developers.facebook.com/docs/reference/dialogs/.
#
#
# @note (see #url_for_oauth_code)
#
# @param dialog_type the kind of Facebook dialog you want to show
Expand All @@ -124,37 +124,37 @@ def url_for_access_token(code, options = {})
# @return an URL your server can query for the user's access token
def url_for_dialog(dialog_type, options = {})
# some endpoints require app_id, some client_id, supply both doesn't seem to hurt
url_options = {:app_id => @app_id, :client_id => @app_id}.merge(options)
url_options = {:app_id => @app_id, :client_id => @app_id}.merge(options)
build_url("http://#{DIALOG_HOST}/dialog/#{dialog_type}", true, url_options)
end

# access tokens

# Fetches an access token, token expiration, and other info from Facebook.
# Useful when you've received an OAuth code using the server-side authentication process.
# @see url_for_oauth_code
#
# @note (see #url_for_oauth_code)
#
#
# @param code (see #url_for_access_token)
# @param options any additional parameters to send to Facebook when redeeming the token
#
# @raise Koala::Facebook::APIError if Facebook returns an error response
#
# @return a hash of the access token info returned by Facebook (token, expiration, etc.)
#
# @raise Koala::Facebook::APIError if Facebook returns an error response
#
# @return a hash of the access token info returned by Facebook (token, expiration, etc.)
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


# Fetches the access token (ignoring expiration and other info) from Facebook.
# Useful when you've received an OAuth code using the server-side authentication process.
# @see get_access_token_info
#
#
# @note (see #url_for_oauth_code)
#
#
# @param (see #get_access_token_info)
#
# @raise (see #get_access_token_info)
Expand All @@ -169,7 +169,7 @@ def get_access_token(code, options = {})

# Fetches the application's access token, along with any other information provided by Facebook.
# See http://developers.facebook.com/docs/authentication/ (search for App Login).
#
#
# @param options any additional parameters to send to Facebook when redeeming the token
#
# @return the application access token and other information (expiration, etc.)
Expand All @@ -180,7 +180,7 @@ def get_app_access_token_info(options = {})

# Fetches the application's access token (ignoring expiration and other info).
# @see get_app_access_token_info
#
#
# @param (see #get_app_access_token_info)
#
# @return the application access token
Expand All @@ -197,32 +197,33 @@ def get_app_access_token(options = {})
# @param options any additional parameters to send to Facebook when exchanging tokens.
#
# @return the access token with extended expiration time and other information (expiration, etc.)
def get_exchange_access_token_info(access_token, options = {})
def exchange_access_token_info(access_token, options = {})
get_token_from_server({
:grant_type => 'fb_exchange_token',
:fb_exchange_token => access_token
}, true, options)
end

# Fetches an access token with extended expiration time (ignoring expiration and other info).
# @see get_exchange_access_token_info

# @see exchange_access_token_info
#
# @param (see #get_exchange_access_token_info)
# @param (see #exchange_access_token_info)
#
# @return A new access token or the existing one, set to expire in 60 days.
def get_exchange_access_token(access_token, options = {})
if info = get_exchange_access_token_info(access_token, options)
def exchange_access_token(access_token, options = {})
if info = exchange_access_token_info(access_token, options)
info["access_token"]
end
end

# Parses a signed request string provided by Facebook to canvas apps or in a secure cookie.
#
# @param input the signed request from Facebook
#
#
# @raise RuntimeError if the signature is incomplete, invalid, or using an unsupported algorithm
#
# @return a hash of the validated request information
#
# @return a hash of the validated request information
def parse_signed_request(input)
encoded_sig, encoded_envelope = input.split('.', 2)
raise 'SignedRequest: Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
Expand All @@ -240,7 +241,7 @@ def parse_signed_request(input)
end

# Old session key code

# @deprecated Facebook no longer provides session keys.
def get_token_info_from_session_keys(sessions, options = {})
Koala::Utils.deprecate("Facebook no longer provides session keys. The relevant OAuth methods will be removed in the next release.")
Expand Down Expand Up @@ -297,7 +298,7 @@ def parse_access_token(response_text)
end
components
end

def parse_unsigned_cookie(fb_cookie)
# remove the opening/closing quote
fb_cookie = fb_cookie.gsub(/\"/, "")
Expand All @@ -311,7 +312,7 @@ def parse_unsigned_cookie(fb_cookie)
sig = Digest::MD5.hexdigest(auth_string + @app_secret)
sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
end

def parse_signed_cookie(fb_cookie)
components = parse_signed_request(fb_cookie)
if code = components["code"]
Expand Down Expand Up @@ -341,12 +342,12 @@ def base64_url_decode(str)
str += '=' * (4 - str.length.modulo(4))
Base64.decode64(str.tr('-_', '+/'))
end

def build_url(base, require_redirect_uri = false, url_options = {})
if require_redirect_uri && !(url_options[:redirect_uri] ||= url_options.delete(:callback) || @oauth_callback_url)
if require_redirect_uri && !(url_options[:redirect_uri] ||= url_options.delete(:callback) || @oauth_callback_url)
raise ArgumentError, "url_for_dialog must get a callback either from the OAuth object or in the parameters!"
end

"#{base}?#{Koala::HTTPService.encode_params(url_options)}"
end
end
Expand Down

0 comments on commit c4e0a84

Please sign in to comment.