Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #57 from coopsite/master

Oauth2 support beginnings
  • Loading branch information...
commit f44b4ab6446789571b0d35b67d2725cbcb4fc6dc 2 parents 6dde48d + 1fea1bf
@mmangino mmangino authored
View
3  .gitignore
@@ -1,4 +1,5 @@
*.swp
.bundle
.rvmrc
-Gemfile.lock
+Gemfile.lock
+.idea
View
1  Gemfile
@@ -2,3 +2,4 @@ source "http://rubygems.org"
source :gemcutter
gemspec
+gem "jslint_on_rails"
View
12 lib/facebooker2.rb
@@ -1,9 +1,13 @@
# Facebooker2
require "mogli"
module Facebooker2
+
+ @oauth2 = false
+ @cookie_prefix = 'fbs_'
+
class NotConfigured < Exception; end
class << self
- attr_accessor :api_key, :secret, :app_id
+ attr_accessor :api_key, :secret, :app_id, :cookie_prefix, :oauth2
end
def self.secret
@@ -13,7 +17,7 @@ def self.secret
def self.app_id
@app_id || raise_unconfigured_exception
end
-
+
def self.raise_unconfigured_exception
raise NotConfigured.new("No configuration provided for Facebooker2. Either set the app_id and secret or call Facebooker2.load_facebooker_yaml in an initializer")
end
@@ -22,10 +26,12 @@ def self.configuration=(hash)
self.api_key = hash[:api_key]
self.secret = hash[:secret]
self.app_id = hash[:app_id]
+ self.cookie_prefix = 'fbsr_' unless hash[:oauth2].blank?
+ self.oauth2 = hash[:oauth2].blank? ? false : true
end
def self.load_facebooker_yaml
- config = YAML.load(ERB.new(File.read(File.join(::Rails.root,"config","facebooker.yml"))).result)[::Rails.env]
+ config = (YAML.load(ERB.new(File.read(File.join(::Rails.root,"config","facebooker.yml"))).result)[::Rails.env])
raise NotConfigured.new("Unable to load configuration for #{::Rails.env} from facebooker.yml. Is it set up?") if config.nil?
self.configuration = config.with_indifferent_access
end
View
46 lib/facebooker2/rails/controller.rb
@@ -12,12 +12,20 @@ def self.included(controller)
end
def current_facebook_user
- fetch_client_and_user
+ if (Facebooker2.oauth2)
+ oauth2_fetch_client_and_user
+ else
+ fetch_client_and_user
+ end
@_current_facebook_user
end
def current_facebook_client
- fetch_client_and_user
+ if (Facebooker2.oauth2)
+ oauth2_fetch_client_and_user
+ else
+ fetch_client_and_user
+ end
@_current_facebook_client
end
@@ -84,7 +92,7 @@ def fb_cookie
end
def fb_cookie_name
- return "fbs_#{Facebooker2.app_id}"
+ return "#{Facebooker2.cookie_prefix + Facebooker2.app_id.to_s}"
end
# check if the expected signature matches the one from facebook
@@ -201,7 +209,37 @@ def set_fb_cookie(access_token,expires,uid,sig)
def set_p3p_header_for_third_party_cookies
response.headers['P3P'] = 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"'
end
-
+
+ ### Oauth2
+ def oauth2_current_facebook_user
+ oauth2_fetch_client_and_user
+ @_current_facebook_user
+ end
+
+ def oauth2_fetch_client_and_user
+ return if @_fb_user_fetched
+ sig = oauth2_fetch_client_and_user_from_cookie if @_current_facebook_client.nil?
+ @_fb_user_fetched = true
+ end
+
+ def oauth2_fetch_client_and_user_from_cookie
+ return unless fb_cookie?
+ sig,payload = fb_cookie.split('.')
+ return unless fb_signed_request_sig_valid?(sig, payload)
+ data = JSON.parse(base64_url_decode(payload))
+ authenticator = Mogli::Authenticator.new(Facebooker2.app_id, Facebooker2.secret, nil)
+ client = Mogli::Client.create_from_code_and_authenticator(data["code"], authenticator)
+ user = Mogli::User.new(:id=>data["user_id"])
+ fb_sign_in_user_and_client(user, client)
+ end
+
+
+ def base64_url_decode(encoded)
+ chars_to_add = 4-(encoded.size % 4)
+ encoded += ("=" * chars_to_add)
+ Base64.decode64(encoded.tr("-_", "+/"))
+ end
+
end
end
end
View
2  lib/facebooker2/rails/helpers/javascript.rb
@@ -16,6 +16,7 @@ def fb_connect_async_js(app_id=Facebooker2.app_id,options={},&proc)
cookie = opts[:cookie].nil? ? true : opts[:cookie]
status = opts[:status].nil? ? true : opts[:status]
xfbml = opts[:xfbml].nil? ? true : opts[:xfbml]
+ oauth2 = Facebooker2.oauth2 ? true : false
channel_url = opts[:channel_url]
lang = opts[:locale] || 'en_US'
extra_js = capture(&proc) if block_given?
@@ -28,6 +29,7 @@ def fb_connect_async_js(app_id=Facebooker2.app_id,options={},&proc)
status : #{status}, // check login status
cookie : #{cookie}, // enable cookies to allow the server to access the session
#{"channelUrl : '#{channel_url}', // add channelURL to avoid IE redirect problems" unless channel_url.blank?}
+ #{"oauth : true," if oauth2}
xfbml : #{xfbml} // parse XFBML
});
#{extra_js}
View
16 spec/be_lintable.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+require 'jslint_on_rails'
+
+def be_lintable
+ ::Spec::Matchers::Matcher.new :be_lintable do
+ match do |actual|
+ tmp_js_output = Tempfile.new 'output.js'
+ tmp_js_output.puts(actual)
+ lint = JSLint::Lint.new(
+ :paths => [tmp_js_output.path]
+ )
+ lint.run
+ true
+ end
+ end
+end
View
11 spec/facebooker2_spec.rb
@@ -1,5 +1,9 @@
require "spec_helper"
describe Facebooker2 do
+ after :all do
+ Facebooker2.configuration = {:app_id=>1234,:secret=>"secret", :oauth2=>false}
+ Facebooker2.cookie_prefix='fbs_'
+ end
describe "Configuration" do
it "allows setting of the api_key" do
@@ -45,6 +49,13 @@
end.should raise_error(Facebooker2::NotConfigured)
end
+
+ context "with oauth2" do
+ it "specifies the correct cookie prefix" do
+ Facebooker2.configuration= {:oauth2=>true}
+ Facebooker2.cookie_prefix.should == 'fbsr_'
+ end
+ end
end
describe "Casting to facebook_id" do
View
70 spec/helpers/javascript_spec.rb
@@ -1,32 +1,45 @@
require "spec_helper"
describe Facebooker2::Rails::Helpers::Javascript, :type=>:helper do
include Facebooker2::Rails::Helpers
+ include Facebooker2
describe "fb_connect_async_js" do
- it "loads with defaults" do
- js = fb_connect_async_js '12345'
- js.should == <<-JAVASCRIPT
- <div id="fb-root"></div>
- <script>
- window.fbAsyncInit = function() {
- FB.init({
- appId : '12345',
- status : true, // check login status
- cookie : true, // enable cookies to allow the server to access the session
-
- xfbml : true // parse XFBML
- });
-
- };
+ context "loading with defaults" do
+ it "specifies correct appId" do
+ js = fb_connect_async_js '12345'
+ js.include?("appId : '12345',").should be_true, js
+ end
+ it "enables status" do
+ js = fb_connect_async_js '12345'
+ js.include?("status : true,").should be_true, js
+ end
+ it "enables cookies" do
+ js = fb_connect_async_js '12345'
+ js.include?("cookie : true,").should be_true, js
+ end
+ it "enables xfbml" do
+ js = fb_connect_async_js '12345'
+ js.include?("xfbml : true").should be_true, js
+ end
+ it "does not specify a channelUrl" do
+ js = fb_connect_async_js '12345'
+ js.include?("channelUrl").should be_false, js
+ end
+ it "does not specify oauth2" do
+ js = fb_connect_async_js '12345'
+ js.include?("oauth2").should be_false, js
+ end
+ it "does select en_US" do
+ js = fb_connect_async_js '12345'
+ js.include?("en_US").should be_true, js
+ end
- (function() {
- var e = document.createElement('script'); e.async = true;
- e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
- document.getElementById('fb-root').appendChild(e);
- }());
- </script>
- JAVASCRIPT
+ it "should be properly formed" do
+ js = fb_connect_async_js '12345'
+ js.should be_lintable
+ end
end
-
+
+
it "disables cookies" do
js = fb_connect_async_js '12345', :cookie => false
js.include?("cookie : false").should be_true, js
@@ -52,6 +65,17 @@
js.include?("//connect.facebook.net/fr_FR/all.js").should be_true, js
end
+ context "Oauth2" do
+ after(:all) do
+ Facebooker2.oauth2=false
+ end
+ it "enables oauth" do
+ Facebooker2.oauth2=true
+ js = fb_connect_async_js '12345'
+ js.include?("oauth").should be_true, js
+ end
+ end
+
# Can't get this to work!
# it "adds extra js" do
# helper.output_buffer = ""
View
394 spec/rails/controller_spec.rb
@@ -5,199 +5,241 @@ class FakeController < ActionController::Base
end
describe Facebooker2::Rails::Controller do
- before(:each) do
+ # This spec has side effects. The configuration
+ # needs to be rebuilt for the following tests to pass.
+ after(:all) do
Facebooker2.app_id = "12345"
Facebooker2.secret = "42ca6de519d53f6e0420247a4d108d90"
end
-
- let :controller do
- controller = FakeController.new
- controller.stub!(:params).and_return({})
- controller.stub!(:cookies).and_return("fbs_12345"=>"\"access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.&expires=0&secret=1e3375dcc4527e7ead0f82c095421690&session_key=57f0206b01ad48bf84ac86f1-12451752&sig=4337fcdee4cc68bb70ec495c0eebf89c&uid=12451752\"")
- controller
- end
-
-
- it "should include helpers" do
- controller.master_helper_module.ancestors.should include(Facebooker2::Rails::Helpers)
- end
-
- describe "Cookie handling" do
-
- it "knows if a cookie exists for this app" do
- controller.fb_cookie.should be_true
- end
-
- it "knows when there isn't a cookie" do
- controller.stub!(:cookies).and_return("")
- controller.fb_cookie?.should be_false
- end
-
- it "gets the hash from the cookie" do
- controller.stub!(:cookies).and_return("fbs_12345"=>"param1=val1&param2=val2")
- controller.fb_cookie_hash.should == {"param1"=>"val1", "param2"=>"val2"}
- end
-
- it "creates a user from the cookie" do
- controller.current_facebook_user.should_not be_nil
- controller.current_facebook_user.should be_an_instance_of(Mogli::User)
- controller.current_facebook_user.id.should == "12451752"
- end
-
- it "sets the client for the user" do
- controller.current_facebook_user.client.access_token.should == "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA."
- end
-
- it "doesn't create a user if there is no app cookie" do
- Facebooker2.app_id="other_app"
- controller.current_facebook_user.should be_nil
- end
-
- it "creates a client from the cookie" do
- controller.current_facebook_client.should_not be_nil
- controller.current_facebook_client.should be_an_instance_of(Mogli::Client)
- controller.current_facebook_client.access_token.should == "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA."
- end
-
- it "creates a client from params" do
- controller.stub!(:fb_cookie_hash).and_return({})
- controller.stub!(:cookies).and_return({})
- controller.stub!(:facebook_params).and_return(
- :oauth_token => "103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY.",
- :expires=>"1279814400",
- :user_id => "585612657")
- controller.current_facebook_client.access_token.should == "103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY."
- controller.current_facebook_user.id.should == "585612657"
- end
-
- it "verifies that the signature is correct" do
- controller.fb_cookie_signature_correct?({
- "access_token" => "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
- "expires" => "0",
- "secret" => "1e3375dcc4527e7ead0f82c095421690",
- "session_key" => "57f0206b01ad48bf84ac86f1-12451752",
- "uid" => "12451752",
- "sig" => "4337fcdee4cc68bb70ec495c0eebf89c"},
- "42ca6de519d53f6e0420247a4d108d90"
- ).should be_true
- end
-
- it "returns false if the signature is not correct" do
- controller.fb_cookie_signature_correct?({
- "access_token" => "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
- "expires" => "0",
- "secret" => "1e3375dcc4527e7ead0f82c095421690",
- "session_key" => "57f0206b01ad48bf84ac86f1-12451752",
- "uid" => "5436785463785",
- "sig" => "4337fcdee4cc68bb70ec495c0eebf89c"},
- "42ca6de519d53f6e0420247a4d108d90"
- ).should be_false
-
- end
-
- it "does not set a cookie if it is not required" do
- controller.stub!(:cookies).and_return("")
- controller.set_fb_cookie(nil,
- Time.now,
- "5436785463785",
- "4337fcdee4cc68bb70ec495c0eebf89c").should be_nil
- controller.fb_cookie.should be_nil
- end
- it "sets a valid cookie if the access token is not nil" do
- tn = Time.now
- controller.set_fb_cookie("114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
- tn,
- "5436785463785",
- "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
- controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&expires=#{tn.to_i}&uid=5436785463785&sig=4337fcdee4cc68bb70ec495c0eebf89c&secret=1e3375dcc4527e7ead0f82c095421690&access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.\""
+ context "Without oauth2" do
+ before(:each) do
+ Facebooker2.app_id = "12345"
+ Facebooker2.secret = "42ca6de519d53f6e0420247a4d108d90"
end
- it "sets a cookie with an expires value of 0 if the access token expires value is far in the future" do
- controller.set_fb_cookie("114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
- Time.now+2.year,
- "5436785463785",
- "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
- controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&expires=0&uid=5436785463785&sig=4337fcdee4cc68bb70ec495c0eebf89c&secret=1e3375dcc4527e7ead0f82c095421690&access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.\""
+ let :controller do
+ controller = FakeController.new
+ controller.stub!(:params).and_return({})
+ controller.stub!(:cookies).and_return("fbs_12345"=>"\"access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.&expires=0&secret=1e3375dcc4527e7ead0f82c095421690&session_key=57f0206b01ad48bf84ac86f1-12451752&sig=4337fcdee4cc68bb70ec495c0eebf89c&uid=12451752\"")
+ controller
end
- it "sets a cookie with the value deleted if the access token is nil" do
- controller.set_fb_cookie(nil,
- Time.now,
- "5436785463785",
- "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
- controller.fb_cookie[:value].should == "deleted"
- end
- end
-
- describe "Signed Request handling" do
- it "should correctly parse JSON that is poorly encoded" do
- controller.fb_signed_request_json("eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MTQ0MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIuTjBrQnE1RDBjYndqVEdtOUo0eFJnQV9fLjM2MDAuMTI3OTgxNDQwMC01ODU2MTI2NTd8VHh3eThTN3NXQklKbnlBWGViRWdTeDZudGdZLiIsInVzZXJfaWQiOiI1ODU2MTI2NTcifQ").
- should == "{\"algorithm\":\"HMAC-SHA256\",\"expires\":1279814400,\"oauth_token\":\"103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY.\",\"user_id\":\"585612657\"}"
- end
-
- it "provides facebook_params if the sig is valid" do
- Facebooker2.secret = "mysecretkey"
- controller.stub!(:params).and_return(:signed_request=>"N1JJFILX63MufS1zpHZwN109VK1ggzEsD0N4pH-yPtc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
- controller.facebook_params[:user_id].should == "532828868"
- end
-
- it "doesn't provide facebook params if the sig is invalid" do
- Facebooker2.secret = "mysecretkey"
- controller.stub!(:params).and_return(:signed_request=>"invalid.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
- controller.facebook_params.should be_blank
+
+ it "should include helpers" do
+ controller.master_helper_module.ancestors.should include(Facebooker2::Rails::Helpers)
end
-
- it "writes a cookie to the client if the sig is valid" do
- controller.stub!(:params).and_return(:signed_request=>"N1JJFILX63MufS1zpHZwN109VK1ggzEsD0N4pH-yPtc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
- Facebooker2.secret = "mysecretkey"
- controller.fetch_client_and_user.should be_true
- controller.fb_cookie.should_not be_nil
- sig = controller.generate_signature({"uid"=>controller.facebook_params[:user_id],
- "access_token"=>controller.facebook_params[:oauth_token],
- "expires"=>controller.facebook_params[:expires]},
- Facebooker2.secret)
-
- controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&"+
- "expires=1279821600&"+
- "uid=532828868&"+
- "sig=0d82b1bb944e5bf8e753a71ee72e9e23&"+
- "secret=1e3375dcc4527e7ead0f82c095421690&"+
- "access_token=103188716396725|2.rrQJKrG1QazFa1hkfz1jLg__.3600.1279821600-532828868|MaxAWqMkUKyJlAp9X0fWFXAt3M8.\""
+ describe "Cookie handling" do
+
+ it "knows if a cookie exists for this app" do
+ controller.fb_cookie.should be_true
+ end
+
+ it "knows when there isn't a cookie" do
+ controller.stub!(:cookies).and_return("")
+ controller.fb_cookie?.should be_false
+ end
+
+ it "gets the hash from the cookie" do
+ controller.stub!(:cookies).and_return("fbs_12345"=>"param1=val1&param2=val2")
+ controller.fb_cookie_hash.should == {"param1"=>"val1", "param2"=>"val2"}
+ end
+
+ it "creates a user from the cookie" do
+ controller.current_facebook_user.should_not be_nil
+ controller.current_facebook_user.should be_an_instance_of(Mogli::User)
+ controller.current_facebook_user.id.should == "12451752"
+ end
+
+ it "sets the client for the user" do
+ controller.current_facebook_user.client.access_token.should == "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA."
+ end
+
+ it "doesn't create a user if there is no app cookie" do
+ Facebooker2.app_id="other_app"
+ controller.current_facebook_user.should be_nil
+ end
+
+ it "creates a client from the cookie" do
+ controller.current_facebook_client.should_not be_nil
+ controller.current_facebook_client.should be_an_instance_of(Mogli::Client)
+ controller.current_facebook_client.access_token.should == "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA."
+ end
+
+ it "creates a client from params" do
+ controller.stub!(:fb_cookie_hash).and_return({})
+ controller.stub!(:cookies).and_return({})
+ controller.stub!(:facebook_params).and_return(
+ :oauth_token => "103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY.",
+ :expires=>"1279814400",
+ :user_id => "585612657")
+ controller.current_facebook_client.access_token.should == "103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY."
+ controller.current_facebook_user.id.should == "585612657"
+ end
+
+ it "verifies that the signature is correct" do
+ controller.fb_cookie_signature_correct?({
+ "access_token" => "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
+ "expires" => "0",
+ "secret" => "1e3375dcc4527e7ead0f82c095421690",
+ "session_key" => "57f0206b01ad48bf84ac86f1-12451752",
+ "uid" => "12451752",
+ "sig" => "4337fcdee4cc68bb70ec495c0eebf89c"},
+ "42ca6de519d53f6e0420247a4d108d90"
+ ).should be_true
+ end
+
+ it "returns false if the signature is not correct" do
+ controller.fb_cookie_signature_correct?({
+ "access_token" => "114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
+ "expires" => "0",
+ "secret" => "1e3375dcc4527e7ead0f82c095421690",
+ "session_key" => "57f0206b01ad48bf84ac86f1-12451752",
+ "uid" => "5436785463785",
+ "sig" => "4337fcdee4cc68bb70ec495c0eebf89c"},
+ "42ca6de519d53f6e0420247a4d108d90"
+ ).should be_false
+
+ end
+
+ it "does not set a cookie if it is not required" do
+ controller.stub!(:cookies).and_return("")
+ controller.set_fb_cookie(nil,
+ Time.now,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_nil
+ controller.fb_cookie.should be_nil
+ end
+
+ it "sets a valid cookie if the access token is not nil" do
+ tn = Time.now
+ controller.set_fb_cookie("114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
+ tn,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
+ controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&expires=#{tn.to_i}&uid=5436785463785&sig=4337fcdee4cc68bb70ec495c0eebf89c&secret=1e3375dcc4527e7ead0f82c095421690&access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.\""
+ end
+
+ it "sets a cookie with an expires value of 0 if the access token expires value is far in the future" do
+ controller.set_fb_cookie("114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
+ Time.now+2.year,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
+ controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&expires=0&uid=5436785463785&sig=4337fcdee4cc68bb70ec495c0eebf89c&secret=1e3375dcc4527e7ead0f82c095421690&access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.\""
+ end
+
+ it "sets a cookie with the value deleted if the access token is nil" do
+ controller.set_fb_cookie(nil,
+ Time.now,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
+ controller.fb_cookie[:value].should == "deleted"
+ end
end
-
- it "uses the cookie if no signed_request is provided" do
- controller.fetch_client_and_user.should be_true
- controller.current_facebook_user.id.should == "12451752"
+
+ describe "Signed Request handling" do
+ it "should correctly parse JSON that is poorly encoded" do
+ controller.fb_signed_request_json("eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MTQ0MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIuTjBrQnE1RDBjYndqVEdtOUo0eFJnQV9fLjM2MDAuMTI3OTgxNDQwMC01ODU2MTI2NTd8VHh3eThTN3NXQklKbnlBWGViRWdTeDZudGdZLiIsInVzZXJfaWQiOiI1ODU2MTI2NTcifQ").
+ should == "{\"algorithm\":\"HMAC-SHA256\",\"expires\":1279814400,\"oauth_token\":\"103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY.\",\"user_id\":\"585612657\"}"
+ end
+
+ it "provides facebook_params if the sig is valid" do
+ Facebooker2.secret = "mysecretkey"
+ controller.stub!(:params).and_return(:signed_request=>"N1JJFILX63MufS1zpHZwN109VK1ggzEsD0N4pH-yPtc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
+ controller.facebook_params[:user_id].should == "532828868"
+ end
+
+ it "doesn't provide facebook params if the sig is invalid" do
+ Facebooker2.secret = "mysecretkey"
+ controller.stub!(:params).and_return(:signed_request=>"invalid.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
+ controller.facebook_params.should be_blank
+ end
+
+ it "writes a cookie to the client if the sig is valid" do
+ controller.stub!(:params).and_return(:signed_request=>"N1JJFILX63MufS1zpHZwN109VK1ggzEsD0N4pH-yPtc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
+ Facebooker2.secret = "mysecretkey"
+ controller.fetch_client_and_user.should be_true
+ controller.fb_cookie.should_not be_nil
+ sig = controller.generate_signature({"uid"=>controller.facebook_params[:user_id],
+ "access_token"=>controller.facebook_params[:oauth_token],
+ "expires"=>controller.facebook_params[:expires]},
+ Facebooker2.secret)
+
+ controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&"+
+ "expires=1279821600&"+
+ "uid=532828868&"+
+ "sig=0d82b1bb944e5bf8e753a71ee72e9e23&"+
+ "secret=1e3375dcc4527e7ead0f82c095421690&"+
+ "access_token=103188716396725|2.rrQJKrG1QazFa1hkfz1jLg__.3600.1279821600-532828868|MaxAWqMkUKyJlAp9X0fWFXAt3M8.\""
+
+ end
+
+ it "uses the cookie if no signed_request is provided" do
+ controller.fetch_client_and_user.should be_true
+ controller.current_facebook_user.id.should == "12451752"
+ end
+
+ it "deletes the cookie if the signed_request does not contain a oauth token (logged out or unauthorized user)" do
+ controller.stub!(:facebook_params).and_return({"algorithm"=>"HMAC-SHA256", "issued_at"=>1300976861, "user"=>{"country"=>"ca", "locale"=>"fr_CA", "age"=>{"min"=>21}}})
+ controller.fetch_client_and_user.should be_true
+ controller.fb_cookie[:value].should == "deleted"
+ controller.current_facebook_user.should be_nil
+ end
+
end
-
- it "deletes the cookie if the signed_request does not contain a oauth token (logged out or unauthorized user)" do
- controller.stub!(:facebook_params).and_return({"algorithm"=>"HMAC-SHA256", "issued_at"=>1300976861, "user"=>{"country"=>"ca", "locale"=>"fr_CA", "age"=>{"min"=>21}}})
- controller.fetch_client_and_user.should be_true
- controller.fb_cookie[:value].should == "deleted"
- controller.current_facebook_user.should be_nil
+
+ describe "Methods" do
+
+ it "allows you to sign in a user" do
+ controller.fb_sign_in_user_and_client(Mogli::User.new,Mogli::Client.new)
+ end
+ it "has a current_facebook_user" do
+ user = mock("user",:client= => nil)
+ controller.fb_sign_in_user_and_client(user,Mogli::Client.new)
+ controller.current_facebook_user.should == user
+ end
+
+ it "has a current_facebook_client" do
+ client = mock("client")
+ controller.fb_sign_in_user_and_client(Mogli::User.new,client)
+ controller.current_facebook_client.should == client
+ end
+
end
-
end
-
- describe "Methods" do
-
- it "allows you to sign in a user" do
- controller.fb_sign_in_user_and_client(Mogli::User.new,Mogli::Client.new)
+
+ describe "Using oauth2" do
+ let :controller do
+ controller = FakeController.new
end
- it "has a current_facebook_user" do
- user = mock("user",:client= => nil)
- controller.fb_sign_in_user_and_client(user,Mogli::Client.new)
- controller.current_facebook_user.should == user
+
+ it "decodes valid base64url data" do
+ # The Base64 representation of '>>>>??????' is 'Pj4+Pj8/Pz8/Pw=='
+ # The FB doc http://developers.facebook.com/docs/authentication/signed_request/ references
+ # http://developers.facebook.com/docs/authentication/signed_request/. The test input is a valid
+ # Base64URL encoded string.
+ controller.base64_url_decode('Pj4-Pj8_Pz8_Pw').should == ">>>>??????"
end
-
- it "has a current_facebook_client" do
- client = mock("client")
- controller.fb_sign_in_user_and_client(Mogli::User.new,client)
- controller.current_facebook_client.should == client
+
+ it "correctly decodes valid JSON payload" do
+ JSON.parse(controller.base64_url_decode('eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0')).should == {"algorithm"=>"HMAC-SHA256", "0" => "payload"}
+ end
+
+ context "Signed request present" do
+ before do
+ Facebooker2.secret='secret'
+ end
+ # Example from the FB Signed Request doc : http://developers.facebook.com/docs/authentication/signed_request/
+ #vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0
+ it "recognizes a valid signature" do
+ controller.fb_signed_request_sig_valid?('vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso','eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0').should be_true
+ end
+ it "rejects an invalid signature" do
+ controller.fb_signed_request_sig_valid?('QGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso','eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0').should be_false
+ end
+
end
-
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.