omniauth-facebook-3.0.0/ 0000755 0000041 0000041 00000000000 12624164072 015141 5 ustar www-data www-data omniauth-facebook-3.0.0/Rakefile 0000644 0000041 0000041 00000000263 12624164072 016607 0 ustar www-data www-data require 'bundler/gem_tasks' require 'rake/testtask' Rake::TestTask.new do |task| task.libs << 'test' task.test_files = FileList['test/*_test.rb'] end task :default => :test omniauth-facebook-3.0.0/Gemfile 0000644 0000041 0000041 00000000127 12624164072 016434 0 ustar www-data www-data source 'https://rubygems.org' gemspec platforms :rbx do gem 'rubysl', '~> 2.0' end omniauth-facebook-3.0.0/.travis.yml 0000644 0000041 0000041 00000000335 12624164072 017253 0 ustar www-data www-data before_install: - gem update bundler - bundle --version - gem update --system 2.1.11 - gem --version rvm: - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 - 2.1 - jruby - rbx matrix: allow_failures: - rvm: rbx omniauth-facebook-3.0.0/lib/ 0000755 0000041 0000041 00000000000 12624164072 015707 5 ustar www-data www-data omniauth-facebook-3.0.0/lib/omniauth/ 0000755 0000041 0000041 00000000000 12624164072 017533 5 ustar www-data www-data omniauth-facebook-3.0.0/lib/omniauth/strategies/ 0000755 0000041 0000041 00000000000 12624164072 021705 5 ustar www-data www-data omniauth-facebook-3.0.0/lib/omniauth/strategies/facebook.rb 0000644 0000041 0000041 00000014111 12624164072 024001 0 ustar www-data www-data require 'omniauth/strategies/oauth2' require 'omniauth/facebook/signed_request' require 'openssl' require 'rack/utils' require 'uri' module OmniAuth module Strategies class Facebook < OmniAuth::Strategies::OAuth2 class NoAuthorizationCodeError < StandardError; end DEFAULT_SCOPE = 'email' option :client_options, { :site => 'https://graph.facebook.com', :authorize_url => "https://www.facebook.com/dialog/oauth", :token_url => 'oauth/access_token' } option :token_params, { :parse => :query } option :access_token_options, { :header_format => 'OAuth %s', :param_name => 'access_token' } option :authorize_options, [:scope, :display, :auth_type] uid { raw_info['id'] } info do prune!({ 'nickname' => raw_info['username'], 'email' => raw_info['email'], 'name' => raw_info['name'], 'first_name' => raw_info['first_name'], 'last_name' => raw_info['last_name'], 'image' => image_url(uid, options), 'description' => raw_info['bio'], 'urls' => { 'Facebook' => raw_info['link'], 'Website' => raw_info['website'] }, 'location' => (raw_info['location'] || {})['name'], 'verified' => raw_info['verified'] }) end extra do hash = {} hash['raw_info'] = raw_info unless skip_info? prune! hash end def raw_info @raw_info ||= access_token.get('me', info_options).parsed || {} end def info_options params = {:appsecret_proof => appsecret_proof} params.merge!({:fields => (options[:info_fields] || 'name,email')}) params.merge!({:locale => options[:locale]}) if options[:locale] { :params => params } end def callback_phase with_authorization_code! do super end rescue NoAuthorizationCodeError => e fail!(:no_authorization_code, e) rescue OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError => e fail!(:unknown_signature_algorithm, e) end # NOTE If we're using code from the signed request then FB sets the redirect_uri to '' during the authorize # phase and it must match during the access_token phase: # https://github.com/facebook/facebook-php-sdk/blob/master/src/base_facebook.php#L477 def callback_url if @authorization_code_from_signed_request_in_cookie '' else # Fixes regression in omniauth-oauth2 v1.4.0 by https://github.com/intridea/omniauth-oauth2/commit/85fdbe117c2a4400d001a6368cc359d88f40abc7 options[:callback_url] || (full_host + script_name + callback_path) end end def access_token_options options.access_token_options.inject({}) { |h,(k,v)| h[k.to_sym] = v; h } end # You can pass +display+, +scope+, or +auth_type+ params to the auth request, if you need to set them dynamically. # You can also set these options in the OmniAuth config :authorize_params option. # # For example: /auth/facebook?display=popup def authorize_params super.tap do |params| %w[display scope auth_type].each do |v| if request.params[v] params[v.to_sym] = request.params[v] end end params[:scope] ||= DEFAULT_SCOPE end end protected def build_access_token super.tap do |token| token.options.merge!(access_token_options) end end private def signed_request_from_cookie @signed_request_from_cookie ||= raw_signed_request_from_cookie && OmniAuth::Facebook::SignedRequest.parse(raw_signed_request_from_cookie, client.secret) end def raw_signed_request_from_cookie request.cookies["fbsr_#{client.id}"] end # Picks the authorization code in order, from: # # 1. The request 'code' param (manual callback from standard server-side flow) # 2. A signed request from cookie (passed from the client during the client-side flow) def with_authorization_code! if request.params.key?('code') yield elsif code_from_signed_request = signed_request_from_cookie && signed_request_from_cookie['code'] request.params['code'] = code_from_signed_request @authorization_code_from_signed_request_in_cookie = true # NOTE The code from the signed fbsr_XXX cookie is set by the FB JS SDK will confirm that the identity of the # user contained in the signed request matches the user loading the app. original_provider_ignores_state = options.provider_ignores_state options.provider_ignores_state = true begin yield ensure request.params.delete('code') @authorization_code_from_signed_request_in_cookie = false options.provider_ignores_state = original_provider_ignores_state end else raise NoAuthorizationCodeError, 'must pass either a `code` (via URL or by an `fbsr_XXX` signed request cookie)' end end def prune!(hash) hash.delete_if do |_, value| prune!(value) if value.is_a?(Hash) value.nil? || (value.respond_to?(:empty?) && value.empty?) end end def image_url(uid, options) uri_class = options[:secure_image_url] ? URI::HTTPS : URI::HTTP site_uri = URI.parse(client.site) url = uri_class.build({:host => site_uri.host, :path => "#{site_uri.path}/#{uid}/picture"}) query = if options[:image_size].is_a?(String) || options[:image_size].is_a?(Symbol) { :type => options[:image_size] } elsif options[:image_size].is_a?(Hash) options[:image_size] end url.query = Rack::Utils.build_query(query) if query url.to_s end def appsecret_proof @appsecret_proof ||= OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, client.secret, access_token.token) end end end end omniauth-facebook-3.0.0/lib/omniauth/facebook/ 0000755 0000041 0000041 00000000000 12624164072 021304 5 ustar www-data www-data omniauth-facebook-3.0.0/lib/omniauth/facebook/signed_request.rb 0000644 0000041 0000041 00000002536 12624164072 024660 0 ustar www-data www-data require 'openssl' module OmniAuth module Facebook class SignedRequest class UnknownSignatureAlgorithmError < NotImplementedError; end SUPPORTED_ALGORITHM = 'HMAC-SHA256' attr_reader :value, :secret def self.parse(value, secret) new(value, secret).payload end def initialize(value, secret) @value = value @secret = secret end def payload @payload ||= parse_signed_request end private def parse_signed_request signature, encoded_payload = value.split('.') return if signature.nil? decoded_hex_signature = base64_decode_url(signature) decoded_payload = MultiJson.decode(base64_decode_url(encoded_payload)) unless decoded_payload['algorithm'] == SUPPORTED_ALGORITHM raise UnknownSignatureAlgorithmError, "unknown algorithm: #{decoded_payload['algorithm']}" end if valid_signature?(decoded_hex_signature, encoded_payload) decoded_payload end end def valid_signature?(signature, payload, algorithm = OpenSSL::Digest::SHA256.new) OpenSSL::HMAC.digest(algorithm, secret, payload) == signature end def base64_decode_url(value) value += '=' * (4 - value.size.modulo(4)) Base64.decode64(value.tr('-_', '+/')) end end end end omniauth-facebook-3.0.0/lib/omniauth/facebook/version.rb 0000644 0000041 0000041 00000000102 12624164072 023307 0 ustar www-data www-data module OmniAuth module Facebook VERSION = "3.0.0" end end omniauth-facebook-3.0.0/lib/omniauth/facebook.rb 0000644 0000041 0000041 00000000113 12624164072 021624 0 ustar www-data www-data require 'omniauth/facebook/version' require 'omniauth/strategies/facebook' omniauth-facebook-3.0.0/lib/omniauth-facebook.rb 0000644 0000041 0000041 00000000034 12624164072 021624 0 ustar www-data www-data require 'omniauth/facebook' omniauth-facebook-3.0.0/metadata.yml 0000644 0000041 0000041 00000006010 12624164072 017441 0 ustar www-data www-data --- !ruby/object:Gem::Specification name: omniauth-facebook version: !ruby/object:Gem::Version version: 3.0.0 platform: ruby authors: - Mark Dodwell - Josef Šimánek autorequire: bindir: bin cert_chain: [] date: 2015-10-27 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: omniauth-oauth2 requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '1.2' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '1.2' - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: mocha requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' description: email: - mark@madeofcode.com - retro@ballgag.cz executables: [] extensions: [] extra_rdoc_files: [] files: - .gitignore - .travis.yml - CHANGELOG.md - Gemfile - README.md - Rakefile - example/Gemfile - example/Gemfile.lock - example/app.rb - example/config.ru - lib/omniauth-facebook.rb - lib/omniauth/facebook.rb - lib/omniauth/facebook/signed_request.rb - lib/omniauth/facebook/version.rb - lib/omniauth/strategies/facebook.rb - omniauth-facebook.gemspec - test/fixtures/payload.json - test/fixtures/signed_request.txt - test/helper.rb - test/signed_request_test.rb - test/strategy_test.rb - test/support/shared_examples.rb homepage: https://github.com/mkdynamic/omniauth-facebook licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.0.14 signing_key: specification_version: 4 summary: Facebook OAuth2 Strategy for OmniAuth test_files: - test/fixtures/payload.json - test/fixtures/signed_request.txt - test/helper.rb - test/signed_request_test.rb - test/strategy_test.rb - test/support/shared_examples.rb omniauth-facebook-3.0.0/test/ 0000755 0000041 0000041 00000000000 12624164072 016120 5 ustar www-data www-data omniauth-facebook-3.0.0/test/signed_request_test.rb 0000644 0000041 0000041 00000001334 12624164072 022526 0 ustar www-data www-data require 'helper' require 'omniauth/facebook/signed_request' class SignedRequestTest < Minitest::Test def setup @value = fixture('signed_request.txt').strip @secret = "897z956a2z7zzzzz5783z458zz3z7556" @expected_payload = MultiJson.decode(fixture('payload.json')) end def test_signed_request_payload signed_request = OmniAuth::Facebook::SignedRequest.new(@value, @secret) assert_equal @expected_payload, signed_request.payload end def test_signed_request_parse payload = OmniAuth::Facebook::SignedRequest.parse(@value, @secret) assert_equal @expected_payload, payload end private def fixture(name) File.read(File.expand_path("fixtures/#{name}", File.dirname(__FILE__))) end end omniauth-facebook-3.0.0/test/helper.rb 0000644 0000041 0000041 00000002741 12624164072 017730 0 ustar www-data www-data require 'bundler/setup' require 'minitest/autorun' require 'mocha/setup' require 'omniauth/strategies/facebook' OmniAuth.config.test_mode = true module BlockTestHelper def test(name, &blk) method_name = "test_#{name.gsub(/\s+/, '_')}" raise "Method already defined: #{method_name}" if instance_methods.include?(method_name.to_sym) define_method method_name, &blk end end module CustomAssertions def assert_has_key(key, hash, msg = nil) msg = message(msg) { "Expected #{hash.inspect} to have key #{key.inspect}" } assert hash.has_key?(key), msg end def refute_has_key(key, hash, msg = nil) msg = message(msg) { "Expected #{hash.inspect} not to have key #{key.inspect}" } refute hash.has_key?(key), msg end end class TestCase < Minitest::Test extend BlockTestHelper include CustomAssertions end class StrategyTestCase < TestCase def setup @request = stub('Request') @request.stubs(:params).returns({}) @request.stubs(:cookies).returns({}) @request.stubs(:env).returns({}) @request.stubs(:scheme).returns({}) @request.stubs(:ssl?).returns(false) @client_id = '123' @client_secret = '53cr3tz' end def strategy @strategy ||= begin args = [@client_id, @client_secret, @options].compact OmniAuth::Strategies::Facebook.new(nil, *args).tap do |strategy| strategy.stubs(:request).returns(@request) end end end end Dir[File.expand_path('../support/**/*', __FILE__)].each &method(:require) omniauth-facebook-3.0.0/test/fixtures/ 0000755 0000041 0000041 00000000000 12624164072 017771 5 ustar www-data www-data omniauth-facebook-3.0.0/test/fixtures/payload.json 0000644 0000041 0000041 00000000520 12624164072 022312 0 ustar www-data www-data { "algorithm": "HMAC-SHA256", "expires": 1308988800, "issued_at": 1308985018, "oauth_token": "111111111111111|2.AQBAttRlLVnwqNPZ.3600.1111111111.1-111111111111111|T49w3BqoZUegypru51Gra70hED8", "user": { "country": "de", "locale": "en_US", "age": { "min": 21 } }, "user_id": "111111111111111" } omniauth-facebook-3.0.0/test/fixtures/signed_request.txt 0000644 0000041 0000041 00000000625 12624164072 023556 0 ustar www-data www-data 53umfudisP7mKhsi9nZboBg15yMZKhfQAARL9UoZtSE.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDg5ODg4MDAsImlzc3VlZF9hdCI6MTMwODk4NTAxOCwib2F1dGhfdG9rZW4iOiIxMTExMTExMTExMTExMTF8Mi5BUUJBdHRSbExWbndxTlBaLjM2MDAuMTExMTExMTExMS4xLTExMTExMTExMTExMTExMXxUNDl3M0Jxb1pVZWd5cHJ1NTFHcmE3MGhFRDgiLCJ1c2VyIjp7ImNvdW50cnkiOiJkZSIsImxvY2FsZSI6ImVuX1VTIiwiYWdlIjp7Im1pbiI6MjF9fSwidXNlcl9pZCI6IjExMTExMTExMTExMTExMSJ9 omniauth-facebook-3.0.0/test/strategy_test.rb 0000644 0000041 0000041 00000042126 12624164072 021353 0 ustar www-data www-data require 'helper' require 'omniauth-facebook' require 'openssl' require 'base64' class StrategyTest < StrategyTestCase include OAuth2StrategyTests end class ClientTest < StrategyTestCase test 'has correct Facebook site' do assert_equal 'https://graph.facebook.com', strategy.client.site end test 'has correct authorize url' do assert_equal 'https://www.facebook.com/dialog/oauth', strategy.client.options[:authorize_url] end test 'has correct token url with versioning' do @options = {:client_options => {:site => 'https://graph.facebook.net/v2.2'}} assert_equal 'oauth/access_token', strategy.client.options[:token_url] assert_equal 'https://graph.facebook.net/v2.2/oauth/access_token', strategy.client.token_url end end class CallbackUrlTest < StrategyTestCase test "returns the default callback url (omitting querystring)" do url_base = 'http://auth.request.com' @request.stubs(:url).returns("#{url_base}/some/page") strategy.stubs(:script_name).returns('') # as not to depend on Rack env strategy.stubs(:query_string).returns('?foo=bar') assert_equal "#{url_base}/auth/facebook/callback", strategy.callback_url end test "returns path from callback_path option (omitting querystring)" do @options = { :callback_path => "/auth/FB/done"} url_base = 'http://auth.request.com' @request.stubs(:url).returns("#{url_base}/page/path") strategy.stubs(:script_name).returns('') # as not to depend on Rack env strategy.stubs(:query_string).returns('?foo=bar') assert_equal "#{url_base}/auth/FB/done", strategy.callback_url end test "returns url from callback_url option" do url = 'https://auth.myapp.com/auth/fb/callback' @options = { :callback_url => url } assert_equal url, strategy.callback_url end end class AuthorizeParamsTest < StrategyTestCase test 'includes default scope for email' do assert strategy.authorize_params.is_a?(Hash) assert_equal 'email', strategy.authorize_params[:scope] end test 'includes display parameter from request when present' do @request.stubs(:params).returns({ 'display' => 'touch' }) assert strategy.authorize_params.is_a?(Hash) assert_equal 'touch', strategy.authorize_params[:display] end test 'includes auth_type parameter from request when present' do @request.stubs(:params).returns({ 'auth_type' => 'reauthenticate' }) assert strategy.authorize_params.is_a?(Hash) assert_equal 'reauthenticate', strategy.authorize_params[:auth_type] end test 'overrides default scope with parameter passed from request' do @request.stubs(:params).returns({ 'scope' => 'email' }) assert strategy.authorize_params.is_a?(Hash) assert_equal 'email', strategy.authorize_params[:scope] end end class TokeParamsTest < StrategyTestCase test 'has correct parse strategy' do assert_equal :query, strategy.token_params[:parse] end end class AccessTokenOptionsTest < StrategyTestCase test 'has correct param name by default' do assert_equal 'access_token', strategy.access_token_options[:param_name] end test 'has correct header format by default' do assert_equal 'OAuth %s', strategy.access_token_options[:header_format] end end class UidTest < StrategyTestCase def setup super strategy.stubs(:raw_info).returns({ 'id' => '123' }) end test 'returns the id from raw_info' do assert_equal '123', strategy.uid end end class InfoTest < StrategyTestCase test 'returns the secure facebook avatar url when `secure_image_url` option is specified' do @options = { :secure_image_url => true } raw_info = { 'name' => 'Fred Smith', 'id' => '321' } strategy.stubs(:raw_info).returns(raw_info) assert_equal 'https://graph.facebook.com/321/picture', strategy.info['image'] end test 'returns the image_url based of the client site' do @options = { :secure_image_url => true, :client_options => {:site => "https://blah.facebook.com/v2.2"}} raw_info = { 'name' => 'Fred Smith', 'id' => '321' } strategy.stubs(:raw_info).returns(raw_info) assert_equal 'https://blah.facebook.com/v2.2/321/picture', strategy.info['image'] end test 'returns the image with size specified in the `image_size` option' do @options = { :image_size => 'normal' } raw_info = { 'name' => 'Fred Smith', 'id' => '321' } strategy.stubs(:raw_info).returns(raw_info) assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image'] end test 'returns the image with size specified as a symbol in the `image_size` option' do @options = { :image_size => :normal } raw_info = { 'name' => 'Fred Smith', 'id' => '321' } strategy.stubs(:raw_info).returns(raw_info) assert_equal 'http://graph.facebook.com/321/picture?type=normal', strategy.info['image'] end test 'returns the image with width and height specified in the `image_size` option' do @options = { :image_size => { :width => 123, :height => 987 } } raw_info = { 'name' => 'Fred Smith', 'id' => '321' } strategy.stubs(:raw_info).returns(raw_info) assert_match 'width=123', strategy.info['image'] assert_match 'height=987', strategy.info['image'] assert_match 'http://graph.facebook.com/321/picture?', strategy.info['image'] end end class InfoTestOptionalDataPresent < StrategyTestCase def setup super @raw_info ||= { 'name' => 'Fred Smith' } strategy.stubs(:raw_info).returns(@raw_info) end test 'returns the name' do assert_equal 'Fred Smith', strategy.info['name'] end test 'returns the email' do @raw_info['email'] = 'fred@smith.com' assert_equal 'fred@smith.com', strategy.info['email'] end test 'returns the username as nickname' do @raw_info['username'] = 'fredsmith' assert_equal 'fredsmith', strategy.info['nickname'] end test 'returns the first name' do @raw_info['first_name'] = 'Fred' assert_equal 'Fred', strategy.info['first_name'] end test 'returns the last name' do @raw_info['last_name'] = 'Smith' assert_equal 'Smith', strategy.info['last_name'] end test 'returns the location name as location' do @raw_info['location'] = { 'id' => '104022926303756', 'name' => 'Palo Alto, California' } assert_equal 'Palo Alto, California', strategy.info['location'] end test 'returns bio as description' do @raw_info['bio'] = 'I am great' assert_equal 'I am great', strategy.info['description'] end test 'returns the facebook avatar url' do @raw_info['id'] = '321' assert_equal 'http://graph.facebook.com/321/picture', strategy.info['image'] end test 'returns the Facebook link as the Facebook url' do @raw_info['link'] = 'http://www.facebook.com/fredsmith' assert_kind_of Hash, strategy.info['urls'] assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook'] end test 'returns website url' do @raw_info['website'] = 'https://my-wonderful-site.com' assert_kind_of Hash, strategy.info['urls'] assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website'] end test 'return both Facebook link and website urls' do @raw_info['link'] = 'http://www.facebook.com/fredsmith' @raw_info['website'] = 'https://my-wonderful-site.com' assert_kind_of Hash, strategy.info['urls'] assert_equal 'http://www.facebook.com/fredsmith', strategy.info['urls']['Facebook'] assert_equal 'https://my-wonderful-site.com', strategy.info['urls']['Website'] end test 'returns the positive verified status' do @raw_info['verified'] = true assert strategy.info['verified'] end test 'returns the negative verified status' do @raw_info['verified'] = false refute strategy.info['verified'] end end class InfoTestOptionalDataNotPresent < StrategyTestCase def setup super @raw_info ||= { 'name' => 'Fred Smith' } strategy.stubs(:raw_info).returns(@raw_info) end test 'has no email key' do refute_has_key 'email', strategy.info end test 'has no nickname key' do refute_has_key 'nickname', strategy.info end test 'has no first name key' do refute_has_key 'first_name', strategy.info end test 'has no last name key' do refute_has_key 'last_name', strategy.info end test 'has no location key' do refute_has_key 'location', strategy.info end test 'has no description key' do refute_has_key 'description', strategy.info end test 'has no urls' do refute_has_key 'urls', strategy.info end test 'has no verified key' do refute_has_key 'verified', strategy.info end end class RawInfoTest < StrategyTestCase def setup super @access_token = stub('OAuth2::AccessToken') @appsecret_proof = 'appsecret_proof' @options = {:appsecret_proof => @appsecret_proof, :fields => 'name,email'} end test 'performs a GET to https://graph.facebook.com/me' do strategy.stubs(:appsecret_proof).returns(@appsecret_proof) strategy.stubs(:access_token).returns(@access_token) params = {:params => @options} @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) strategy.raw_info end test 'performs a GET to https://graph.facebook.com/me with locale' do @options.merge!({ :locale => 'cs_CZ' }) strategy.stubs(:access_token).returns(@access_token) strategy.stubs(:appsecret_proof).returns(@appsecret_proof) params = {:params => @options} @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) strategy.raw_info end test 'performs a GET to https://graph.facebook.com/me with info_fields' do @options.merge!({:info_fields => 'about'}) strategy.stubs(:access_token).returns(@access_token) strategy.stubs(:appsecret_proof).returns(@appsecret_proof) params = {:params => {:appsecret_proof => @appsecret_proof, :fields => 'about'}} @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) strategy.raw_info end test 'performs a GET to https://graph.facebook.com/me with default info_fields' do strategy.stubs(:access_token).returns(@access_token) strategy.stubs(:appsecret_proof).returns(@appsecret_proof) params = {:params => {:appsecret_proof => @appsecret_proof, :fields => 'name,email'}} @access_token.expects(:get).with('me', params).returns(stub_everything('OAuth2::Response')) strategy.raw_info end test 'returns a Hash' do strategy.stubs(:access_token).returns(@access_token) strategy.stubs(:appsecret_proof).returns(@appsecret_proof) raw_response = stub('Faraday::Response') raw_response.stubs(:body).returns('{ "ohai": "thar" }') raw_response.stubs(:status).returns(200) raw_response.stubs(:headers).returns({'Content-Type' => 'application/json' }) oauth2_response = OAuth2::Response.new(raw_response) params = {:params => @options} @access_token.stubs(:get).with('me', params).returns(oauth2_response) assert_kind_of Hash, strategy.raw_info assert_equal 'thar', strategy.raw_info['ohai'] end test 'returns an empty hash when the response is false' do strategy.stubs(:access_token).returns(@access_token) strategy.stubs(:appsecret_proof).returns(@appsecret_proof) oauth2_response = stub('OAuth2::Response', :parsed => false) params = {:params => @options} @access_token.stubs(:get).with('me', params).returns(oauth2_response) assert_kind_of Hash, strategy.raw_info assert_equal({}, strategy.raw_info) end test 'should not include raw_info in extras hash when skip_info is specified' do @options = { :skip_info => true } strategy.stubs(:raw_info).returns({:foo => 'bar' }) refute_has_key 'raw_info', strategy.extra end end class CredentialsTest < StrategyTestCase def setup super @access_token = stub('OAuth2::AccessToken') @access_token.stubs(:token) @access_token.stubs(:expires?) @access_token.stubs(:expires_at) @access_token.stubs(:refresh_token) strategy.stubs(:access_token).returns(@access_token) end test 'returns a Hash' do assert_kind_of Hash, strategy.credentials end test 'returns the token' do @access_token.stubs(:token).returns('123') assert_equal '123', strategy.credentials['token'] end test 'returns the expiry status' do @access_token.stubs(:expires?).returns(true) assert strategy.credentials['expires'] @access_token.stubs(:expires?).returns(false) refute strategy.credentials['expires'] end test 'returns the refresh token and expiry time when expiring' do ten_mins_from_now = (Time.now + 600).to_i @access_token.stubs(:expires?).returns(true) @access_token.stubs(:refresh_token).returns('321') @access_token.stubs(:expires_at).returns(ten_mins_from_now) assert_equal '321', strategy.credentials['refresh_token'] assert_equal ten_mins_from_now, strategy.credentials['expires_at'] end test 'does not return the refresh token when test is nil and expiring' do @access_token.stubs(:expires?).returns(true) @access_token.stubs(:refresh_token).returns(nil) assert_nil strategy.credentials['refresh_token'] refute_has_key 'refresh_token', strategy.credentials end test 'does not return the refresh token when not expiring' do @access_token.stubs(:expires?).returns(false) @access_token.stubs(:refresh_token).returns('XXX') assert_nil strategy.credentials['refresh_token'] refute_has_key 'refresh_token', strategy.credentials end end class ExtraTest < StrategyTestCase def setup super @raw_info = { 'name' => 'Fred Smith' } strategy.stubs(:raw_info).returns(@raw_info) end test 'returns a Hash' do assert_kind_of Hash, strategy.extra end test 'contains raw info' do assert_equal({ 'raw_info' => @raw_info }, strategy.extra) end end module SignedRequestHelpers def signed_request(payload, secret) encoded_payload = base64_encode_url(MultiJson.encode(payload)) encoded_signature = base64_encode_url(signature(encoded_payload, secret)) [encoded_signature, encoded_payload].join('.') end def base64_encode_url(value) Base64.encode64(value).tr('+/', '-_').gsub(/\n/, '') end def signature(payload, secret, algorithm = OpenSSL::Digest::SHA256.new) OpenSSL::HMAC.digest(algorithm, secret, payload) end end module SignedRequestTests class TestCase < StrategyTestCase include SignedRequestHelpers end class CookieAndParamNotPresentTest < TestCase test 'is nil' do assert_nil strategy.send(:signed_request_from_cookie) end test 'throws an error on calling build_access_token' do assert_raises(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError) { strategy.send(:with_authorization_code!) {} } end end class CookiePresentTest < TestCase def setup(algo = nil) super() @payload = { 'algorithm' => algo || 'HMAC-SHA256', 'code' => 'm4c0d3z', 'issued_at' => Time.now.to_i, 'user_id' => '123456' } @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) end test 'parses the access code out from the cookie' do assert_equal @payload, strategy.send(:signed_request_from_cookie) end test 'throws an error if the algorithm is unknown' do setup('UNKNOWN-ALGO') assert_equal "unknown algorithm: UNKNOWN-ALGO", assert_raises(OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError) { strategy.send(:signed_request_from_cookie) }.message end end class EmptySignedRequestTest < TestCase def setup super @request.stubs(:params).returns({'signed_request' => ''}) end test 'empty param' do assert_equal nil, strategy.send(:signed_request_from_cookie) end end class MissingCodeInParamsRequestTest < TestCase def setup super @request.stubs(:params).returns({}) end test 'calls fail! when a code is not included in the params' do strategy.expects(:fail!).times(1).with(:no_authorization_code, kind_of(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError)) strategy.callback_phase end end class MissingCodeInCookieRequestTest < TestCase def setup(algo = nil) super() @payload = { 'algorithm' => algo || 'HMAC-SHA256', 'code' => nil, 'issued_at' => Time.now.to_i, 'user_id' => '123456' } @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) end test 'calls fail! when a code is not included in the cookie' do strategy.expects(:fail!).times(1).with(:no_authorization_code, kind_of(OmniAuth::Strategies::Facebook::NoAuthorizationCodeError)) strategy.callback_phase end end class UnknownAlgorithmInCookieRequestTest < TestCase def setup super() @payload = { 'algorithm' => 'UNKNOWN-ALGO', 'code' => nil, 'issued_at' => Time.now.to_i, 'user_id' => '123456' } @request.stubs(:cookies).returns({"fbsr_#{@client_id}" => signed_request(@payload, @client_secret)}) end test 'calls fail! when an algorithm is unknown' do strategy.expects(:fail!).times(1).with(:unknown_signature_algorithm, kind_of(OmniAuth::Facebook::SignedRequest::UnknownSignatureAlgorithmError)) strategy.callback_phase end end end omniauth-facebook-3.0.0/test/support/ 0000755 0000041 0000041 00000000000 12624164072 017634 5 ustar www-data www-data omniauth-facebook-3.0.0/test/support/shared_examples.rb 0000644 0000041 0000041 00000006452 12624164072 023334 0 ustar www-data www-data # NOTE it would be useful if this lived in omniauth-oauth2 eventually module OAuth2StrategyTests def self.included(base) base.class_eval do include ClientTests include AuthorizeParamsTests include CSRFAuthorizeParamsTests include TokenParamsTests end end module ClientTests extend BlockTestHelper test 'should be initialized with symbolized client_options' do @options = { :client_options => { 'authorize_url' => 'https://example.com' } } assert_equal 'https://example.com', strategy.client.options[:authorize_url] end end module AuthorizeParamsTests extend BlockTestHelper test 'should include any authorize params passed in the :authorize_params option' do @options = { :authorize_params => { :foo => 'bar', :baz => 'zip' } } assert_equal 'bar', strategy.authorize_params['foo'] assert_equal 'zip', strategy.authorize_params['baz'] end test 'should include top-level options that are marked as :authorize_options' do @options = { :authorize_options => [:scope, :foo], :scope => 'bar', :foo => 'baz' } assert_equal 'bar', strategy.authorize_params['scope'] assert_equal 'baz', strategy.authorize_params['foo'] end test 'should exclude top-level options that are not passed' do @options = { :authorize_options => [:bar] } refute_has_key :bar, strategy.authorize_params refute_has_key 'bar', strategy.authorize_params end end module CSRFAuthorizeParamsTests extend BlockTestHelper test 'should store random state in the session when none is present in authorize or request params' do assert_includes strategy.authorize_params.keys, 'state' refute_empty strategy.authorize_params['state'] refute_empty strategy.session['omniauth.state'] assert_equal strategy.authorize_params['state'], strategy.session['omniauth.state'] end test 'should not store state in the session when present in authorize params vs. a random one' do @options = { :authorize_params => { :state => 'bar' } } refute_empty strategy.authorize_params['state'] refute_equal 'bar', strategy.authorize_params[:state] refute_empty strategy.session['omniauth.state'] refute_equal 'bar', strategy.session['omniauth.state'] end test 'should not store state in the session when present in request params vs. a random one' do @request.stubs(:params).returns({ 'state' => 'foo' }) refute_empty strategy.authorize_params['state'] refute_equal 'foo', strategy.authorize_params[:state] refute_empty strategy.session['omniauth.state'] refute_equal 'foo', strategy.session['omniauth.state'] end end module TokenParamsTests extend BlockTestHelper test 'should include any authorize params passed in the :token_params option' do @options = { :token_params => { :foo => 'bar', :baz => 'zip' } } assert_equal 'bar', strategy.token_params['foo'] assert_equal 'zip', strategy.token_params['baz'] end test 'should include top-level options that are marked as :token_options' do @options = { :token_options => [:scope, :foo], :scope => 'bar', :foo => 'baz' } assert_equal 'bar', strategy.token_params['scope'] assert_equal 'baz', strategy.token_params['foo'] end end end omniauth-facebook-3.0.0/omniauth-facebook.gemspec 0000644 0000041 0000041 00000001560 12624164072 022103 0 ustar www-data www-data # -*- encoding: utf-8 -*- $:.push File.expand_path('../lib', __FILE__) require 'omniauth/facebook/version' Gem::Specification.new do |s| s.name = 'omniauth-facebook' s.version = OmniAuth::Facebook::VERSION s.authors = ['Mark Dodwell', 'Josef Šimánek'] s.email = ['mark@madeofcode.com', 'retro@ballgag.cz'] s.summary = 'Facebook OAuth2 Strategy for OmniAuth' s.homepage = 'https://github.com/mkdynamic/omniauth-facebook' s.license = 'MIT' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } s.require_paths = ['lib'] s.add_runtime_dependency 'omniauth-oauth2', '~> 1.2' s.add_development_dependency 'minitest' s.add_development_dependency 'mocha' s.add_development_dependency 'rake' end omniauth-facebook-3.0.0/.gitignore 0000644 0000041 0000041 00000000111 12624164072 017122 0 ustar www-data www-data *.gem .bundle .rspec /Gemfile.lock pkg/* .powenv tmp bin example/app.log omniauth-facebook-3.0.0/example/ 0000755 0000041 0000041 00000000000 12624164072 016574 5 ustar www-data www-data omniauth-facebook-3.0.0/example/Gemfile.lock 0000644 0000041 0000041 00000002206 12624164072 021016 0 ustar www-data www-data PATH remote: ../ specs: omniauth-facebook (2.0.0) omniauth-oauth2 (~> 1.2) GEM remote: https://rubygems.org/ specs: backports (3.3.5) faraday (0.9.0) multipart-post (>= 1.2, < 3) hashie (3.2.0) jwt (1.0.0) multi_json (1.8.2) multi_xml (0.5.5) multipart-post (2.0.0) oauth2 (1.0.0) faraday (>= 0.8, < 0.10) jwt (~> 1.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (~> 1.2) omniauth (1.2.2) hashie (>= 1.2, < 4) rack (~> 1.0) omniauth-oauth2 (1.2.0) faraday (>= 0.8, < 0.10) multi_json (~> 1.3) oauth2 (~> 1.0) omniauth (~> 1.2) rack (1.5.2) rack-protection (1.5.1) rack rack-test (0.6.2) rack (>= 1.0) sinatra (1.4.4) rack (~> 1.4) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) sinatra-contrib (1.4.2) backports (>= 2.0) multi_json rack-protection rack-test sinatra (~> 1.4.0) tilt (~> 1.3) sinatra-reloader (1.0) sinatra-contrib tilt (1.4.1) PLATFORMS ruby DEPENDENCIES omniauth-facebook! sinatra sinatra-reloader omniauth-facebook-3.0.0/example/Gemfile 0000644 0000041 0000041 00000000154 12624164072 020067 0 ustar www-data www-data source 'https://rubygems.org' gem 'sinatra' gem 'sinatra-reloader' gem 'omniauth-facebook', :path => '../' omniauth-facebook-3.0.0/example/app.rb 0000644 0000041 0000041 00000005477 12624164072 017716 0 ustar www-data www-data require 'sinatra' require "sinatra/reloader" require 'yaml' # configure sinatra set :run, false set :raise_errors, true # setup logging to file log = File.new("app.log", "a+") $stdout.reopen(log) $stderr.reopen(log) $stderr.sync = true $stdout.sync = true # server-side flow get '/server-side' do # NOTE: You would just hit this endpoint directly from the browser in a real app. The redirect is just here to # explicit declare this server-side flow. redirect '/auth/facebook' end # client-side flow get '/client-side' do content_type 'text/html' # NOTE: When you enable cookie below in the FB.init call the GET request in the FB.login callback will send a signed # request in a cookie back the OmniAuth callback which will parse out the authorization code and obtain an # access_token with it. <<-END