Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add support for access token exchange #166

Merged
merged 3 commits into from

3 participants

Étienne Barrié Laust Rud Jacobsen Alex Koppel
Étienne Barrié

As discussed in arsduo/koala#163.

Mocked specs implementation might not be ideal and there’s still some work to do to pass the live tests.

Laust Rud Jacobsen
rud commented

This looks like a good and friendly patch. Any chance of a release including this? The facebook offline deprecation is already being rolled out, so this would be helpful if included.

Alex Koppel
Owner

I'm merging this in now, and hope to have a release out this week, even if it means rolling out the solution to #165 in a later release. Stay tuned!

Étienne Barrié

I rebased against master and fixed the live specs. I also renamed [get_]exchange_access_token and [get_]exchange_access_token_info. This last one doesn’t sound so good but meh…

I still got this one failure but it fails as well on master. I wouldn’t release Koala with this one failing though ;)

rspec ./spec/support/graph_api_shared_examples.rb:220 # Koala::Facebook::API with an access token it should behave like Koala GraphAPI with an access token can delete posts
Alex Koppel arsduo merged commit 1c404f3 into from
Alex Koppel
Owner

Hi Étienne,

Thanks again for the pull request! I've merged it into master and verified that all the tests are running properly. I think it's ready to go!

I'm seeing the same test failure you saw, but that seems to be a Facebook bug, not a problem with Koala, so I plan to release 1.4 sometime this week.

Best,

Alex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
26 lib/koala/oauth.rb
View
@@ -190,6 +190,32 @@ def get_app_access_token(options = {})
end
end
+ # Fetches an access_token with extended expiration time, along with any other information provided by Facebook.
+ # See https://developers.facebook.com/docs/offline-access-deprecation/#extend_token (search for fb_exchange_token).
+ #
+ # @param access_token the access token to exchange
+ # @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 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 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 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
40 spec/cases/oauth_spec.rb
View
@@ -7,6 +7,7 @@
@secret = KoalaTest.secret
@code = KoalaTest.code
@callback_url = KoalaTest.oauth_test_data["callback_url"]
+ @access_token = KoalaTest.oauth_test_data["access_token"]
@raw_token_string = KoalaTest.oauth_test_data["raw_token_string"]
@raw_offline_access_token_string = KoalaTest.oauth_test_data["raw_offline_access_token_string"]
@@ -445,7 +446,7 @@
end
end
- describe "get_app_acess_token" do
+ describe "get_app_access_token" do
it "uses get_access_token_info to get and parse an access token token results" do
result = @oauth.get_app_access_token
result.should be_a(String)
@@ -464,6 +465,43 @@
end
end
+ describe "exchange_access_token_info" do
+ it "properly gets and parses an app's access token as a hash" do
+ result = @oauth.exchange_access_token_info(KoalaTest.oauth_token)
+ result.should be_a(Hash)
+ end
+
+ it "includes the access token" do
+ result = @oauth.exchange_access_token_info(KoalaTest.oauth_token)
+ result["access_token"].should
+ end
+
+ it "passes on any options provided to make_request" do
+ options = {:a => 2}
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::HTTPService::Response.new(200, "", {}))
+ @oauth.exchange_access_token_info(KoalaTest.oauth_token, options)
+ end
+ end
+
+ describe "exchange_access_token" do
+ it "uses get_access_token_info to get and parse an access token token results" do
+ result = @oauth.exchange_access_token(KoalaTest.oauth_token)
+ result.should be_a(String)
+ end
+
+ it "returns the access token as a string" do
+ result = @oauth.exchange_access_token(KoalaTest.oauth_token)
+ original = @oauth.exchange_access_token_info(KoalaTest.oauth_token)
+ result.should == original["access_token"]
+ end
+
+ it "passes on any options provided to make_request" do
+ options = {:a => 2}
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::HTTPService::Response.new(200, "", {}))
+ @oauth.exchange_access_token(KoalaTest.oauth_token, options)
+ end
+ end
+
describe "protected methods" do
# protected methods
1  spec/fixtures/facebook_data.yml
View
@@ -23,6 +23,7 @@ oauth_test_data:
app_id: 119908831367602
secret: e45e55a333eec232d4206d2703de1307
callback_url: http://oauth.twoalex.com/
+ access_token: "119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk."
app_access_token: 119908831367602|o3wswWQ88LYjEC9-ukR_gjRIOMw.
raw_token_string: "access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.&expires=6621"
raw_offline_access_token_string: access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.
3  spec/fixtures/mock_facebook_responses.yml
View
@@ -308,6 +308,9 @@ graph_api:
client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&type=client_cred:
post:
no_token: access_token=<%= APP_ACCESS_TOKEN %>
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&fb_exchange_token=<%= ACCESS_TOKEN %>&grant_type=fb_exchange_token:
+ post:
+ no_token: access_token=<%= ACCESS_TOKEN %>&expires=5184000
/oauth/exchange_sessions:
client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["session_key"] %>&type=client_cred:
post:
1  spec/support/mock_http_service.rb
View
@@ -40,6 +40,7 @@ def self.make_request(path, args, verb, options = {})
verb ||= 'get'
server = options[:rest_api] ? 'rest_api' : 'graph_api'
token = args.delete('access_token')
+ args[:fb_exchange_token] = ACCESS_TOKEN if args.has_key?(:fb_exchange_token)
with_token = (token == ACCESS_TOKEN || token == APP_ACCESS_TOKEN) ? 'with_token' : 'no_token'
# Assume format is always JSON
Something went wrong with that request. Please try again.