From ce9df5cd35d4a299e18ed3357463e977e2fab518 Mon Sep 17 00:00:00 2001 From: kbravi Date: Fri, 7 Apr 2017 19:41:27 -0700 Subject: [PATCH 1/5] works with paypal openid - build access token from code --- Gemfile | 1 - Gemfile.lock | 52 +++++++++--------- lib/omniauth/strategies/paypal.rb | 89 +++++++++++++++++++------------ omniauth-paypal.gemspec | 3 +- 4 files changed, 83 insertions(+), 62 deletions(-) diff --git a/Gemfile b/Gemfile index bb91cc4..a9764c3 100644 --- a/Gemfile +++ b/Gemfile @@ -2,5 +2,4 @@ source "https://rubygems.org" gemspec -gem 'omniauth-oauth2', "~> 1.3.1" gem 'json' diff --git a/Gemfile.lock b/Gemfile.lock index 4e2ed29..c3f7831 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,52 +2,52 @@ PATH remote: . specs: omniauth-paypal (1.3) - omniauth-oauth2 (~> 1.3.1) + omniauth (>= 1.1.1) + omniauth-oauth2 (>= 1.3.1) GEM remote: https://rubygems.org/ specs: - diff-lcs (1.2.4) - faraday (0.9.1) + diff-lcs (1.3) + faraday (0.11.0) multipart-post (>= 1.2, < 3) - hashie (3.4.2) - json (1.8.3) - jwt (1.5.1) - multi_json (1.11.2) - multi_xml (0.5.5) + hashie (3.5.5) + json (2.0.3) + jwt (1.5.6) + multi_json (1.12.1) + multi_xml (0.6.0) multipart-post (2.0.0) - oauth2 (1.0.0) - faraday (>= 0.8, < 0.10) + oauth2 (1.3.1) + faraday (>= 0.8, < 0.12) 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.3.1) + rack (>= 1.2, < 3) + omniauth (1.6.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-oauth2 (1.4.0) oauth2 (~> 1.0) omniauth (~> 1.2) - rack (1.6.4) - rake (10.1.0) - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.5) - rspec-expectations (2.14.3) + rack (2.0.1) + rake (12.0.0) + rspec (2.99.0) + rspec-core (~> 2.99.0) + rspec-expectations (~> 2.99.0) + rspec-mocks (~> 2.99.0) + rspec-core (2.99.2) + rspec-expectations (2.99.2) diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.3) + rspec-mocks (2.99.4) PLATFORMS ruby DEPENDENCIES json - omniauth-oauth2 (~> 1.3.1) omniauth-paypal! rake rspec (~> 2.14) BUNDLED WITH - 1.10.6 + 1.14.6 diff --git a/lib/omniauth/strategies/paypal.rb b/lib/omniauth/strategies/paypal.rb index d240b0c..2310fd7 100644 --- a/lib/omniauth/strategies/paypal.rb +++ b/lib/omniauth/strategies/paypal.rb @@ -12,7 +12,6 @@ class PayPal < OmniAuth::Strategies::OAuth2 :site => 'https://api.paypal.com', :authorize_url => 'https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize', :token_url => '/v1/identity/openidconnect/tokenservice', - :setup => true } option :authorize_options, [:scope, :response_type] @@ -23,30 +22,18 @@ class PayPal < OmniAuth::Strategies::OAuth2 info do prune!({ - 'name' => raw_info['name'], - 'email' => raw_info['email'], - 'first_name' => raw_info['given_name'], - 'last_name' => raw_info['family_name'], - 'given_name' => raw_info['given_name'], - 'family_name' => raw_info['family_name'], - 'location' => (raw_info['address'] || {})['locality'], - 'phone' => raw_info['phone_number'] - }) + name: raw_info['name'], + email: raw_info['email'], + first_name: raw_info['given_name'], + last_name: raw_info['family_name'], + location: build_user_location, + phone: raw_info['phone_number'], + image: raw_info['picture'] + }) end extra do - prune!({ - 'account_type' => raw_info['account_type'], - 'user_id' => raw_info['user_id'], - 'address' => raw_info['address'], - 'verified_account' => (raw_info['verified_account'] == 'true'), - 'language' => raw_info['language'], - 'zoneinfo' => raw_info['zoneinfo'], - 'locale' => raw_info['locale'], - 'account_creation_date' => raw_info['account_creation_date'], - 'age_range' => raw_info['age_range'], - 'birthday' => raw_info['birthday'] - }) + prune!({'raw_info' => raw_info}) end def setup_phase @@ -57,8 +44,12 @@ def setup_phase super end + def callback_url + options[:redirect_uri] || (full_host + script_name + callback_path) + end + def raw_info - @raw_info ||= load_identity() + @raw_info ||= load_identity end def authorize_params @@ -68,21 +59,51 @@ def authorize_params end end - private - def load_identity - access_token.options[:mode] = :query - access_token.options[:param_name] = :access_token - access_token.options[:grant_type] = :authorization_code - access_token.get('/v1/identity/openidconnect/userinfo', { :params => { :schema => 'openid'}}).parsed || {} + def custom_build_access_token + access_token = + if request.xhr? && request.params['code'] + verifier = request.params['code'] + redirect_uri = request.params['redirect_uri'] || 'postmessage' + client.auth_code.get_token(verifier, get_token_options(redirect_uri), deep_symbolize(options.auth_token_params || {})) + elsif request.params['code'] && request.params['redirect_uri'] + verifier = request.params['code'] + redirect_uri = request.params['redirect_uri'] + client.auth_code.get_token(verifier, get_token_options(redirect_uri), deep_symbolize(options.auth_token_params || {})) + else + verifier = request.params["code"] + client.auth_code.get_token(verifier, get_token_options(callback_url), deep_symbolize(options.auth_token_params)) end + access_token + end + alias_method :build_access_token, :custom_build_access_token + + private - def prune!(hash) - hash.delete_if do |_, value| - prune!(value) if value.is_a?(Hash) - value.nil? || (value.respond_to?(:empty?) && value.empty?) - end + def load_identity + access_token.options[:mode] = :query + access_token.options[:param_name] = :access_token + access_token.options[:grant_type] = :authorization_code + access_token.get('/v1/identity/openidconnect/userinfo', { :params => { :schema => 'openid'}}).parsed || {} + end + + def get_token_options(redirect_uri) + { :redirect_uri => redirect_uri }.merge(token_params.to_hash(:symbolize_keys => true)) + 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 build_user_location + return unless raw_info['address'] + location = [ + raw_info['address']['locality'], + raw_info['address']['region'] + ].compact.join(', ') + end end end end diff --git a/omniauth-paypal.gemspec b/omniauth-paypal.gemspec index 94131b2..0714d1d 100644 --- a/omniauth-paypal.gemspec +++ b/omniauth-paypal.gemspec @@ -16,7 +16,8 @@ Gem::Specification.new do |s| s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } s.require_paths = ['lib'] - s.add_runtime_dependency 'omniauth-oauth2', '~> 1.3.1' + s.add_runtime_dependency 'omniauth', '>= 1.1.1' + s.add_runtime_dependency 'omniauth-oauth2', '>= 1.3.1' s.add_development_dependency 'rspec', '~> 2.14' s.add_development_dependency 'rake' From 970264b559c856144c9cc82643c39a990ae5192a Mon Sep 17 00:00:00 2001 From: kbravi Date: Fri, 7 Apr 2017 19:49:34 -0700 Subject: [PATCH 2/5] updated readme --- README.md | 65 +++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 470e818..16b6a6b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Note:** This gem is designed to work with OmniAuth 1.0 library. -This gem contains the Log In With PayPal strategy for OmniAuth. +This gem contains the Log In With PayPal OpenID strategy for OmniAuth. ## Installing @@ -33,25 +33,25 @@ The possible attributes to be returned at the moment are: ```ruby info['name'] info['email'] -info['first_name'] # also available as given_name -info['last_name'] # also available as family_name +info['first_name'] +info['last_name'] info['location'] info['name'] info['phone'] -extra['account_creation_date'] -extra['account_type'] -extra['address']['country'] -extra['address']['locality'] -extra['address']['postal_code'] -extra['address']['region'] -extra['address']['street_address'] -extra['language'] -extra['locale'] -extra['verified_account'] -extra['zoneinfo'] -extra['age_range'] -extra['birthday'] +extra['raw_info']['account_creation_date'] +extra['raw_info']['account_type'] +extra['raw_info']['address']['country'] +extra['raw_info']['address']['locality'] +extra['raw_info']['address']['postal_code'] +extra['raw_info']['address']['region'] +extra['raw_info']['address']['street_address'] +extra['raw_info']['language'] +extra['raw_info']['locale'] +extra['raw_info']['verified_account'] +extra['raw_info']['zoneinfo'] +extra['raw_info']['age_range'] +extra['raw_info']['birthday'] ``` The actual set of attributes returned depends on the scopes set. The currently available scopes are: @@ -87,8 +87,6 @@ info: email: example@example.com first_name: John last_name: Smith - given_name: John - family_name: Smith location: Moscow name: John Smith phone: "71234567890" @@ -98,21 +96,22 @@ credentials: expires_at: 1355082790 expires: true extra: - account_creation_date: "2008-04-21" - account_type: PERSONAL - user_id: https://www.paypal.com/webapps/auth/identity/user/bathjJwvdhKjgfgh8Jd745J7dh5Qkgflbnczd65dfnw - address: - country: US - locality: San Jose - postal_code: "95131" - region: CA - street_address: 1 Main St - language: en_US - locale: en_US - verified_account: true - zoneinfo: America/Los_Angeles - age_range: 31-35 - birthday: "1982-01-01" + raw_info: + account_creation_date: "2008-04-21" + account_type: PERSONAL + user_id: https://www.paypal.com/webapps/auth/identity/user/bathjJwvdhKjgfgh8Jd745J7dh5Qkgflbnczd65dfnw + address: + country: US + locality: San Jose + postal_code: "95131" + region: CA + street_address: 1 Main St + language: en_US + locale: en_US + verified_account: true + zoneinfo: America/Los_Angeles + age_range: 31-35 + birthday: "1982-01-01" ``` ## Contributing From 3050f88a08ffedcc5304b18fa2736d7942427e3a Mon Sep 17 00:00:00 2001 From: Joel Van Horn Date: Sat, 9 Sep 2017 20:19:00 -0400 Subject: [PATCH 3/5] Refactor and consolidate --- lib/omniauth/strategies/paypal.rb | 94 +++++++++++++++---------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/lib/omniauth/strategies/paypal.rb b/lib/omniauth/strategies/paypal.rb index 2310fd7..7077f43 100644 --- a/lib/omniauth/strategies/paypal.rb +++ b/lib/omniauth/strategies/paypal.rb @@ -3,44 +3,50 @@ module OmniAuth module Strategies class PayPal < OmniAuth::Strategies::OAuth2 - DEFAULT_SCOPE = "openid profile" + DEFAULT_SCOPE = "openid profile" DEFAULT_RESPONSE_TYPE = "code" - SANDBOX_SITE = "https://api.sandbox.paypal.com" + SANDBOX_SITE = "https://api.sandbox.paypal.com" SANDBOX_AUTHORIZE_URL = 'https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize' option :client_options, { - :site => 'https://api.paypal.com', - :authorize_url => 'https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize', - :token_url => '/v1/identity/openidconnect/tokenservice', + site: 'https://api.paypal.com', + authorize_url: 'https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize', + token_url: '/v1/identity/openidconnect/tokenservice', } option :authorize_options, [:scope, :response_type] option :provider_ignores_state, true option :sandbox, false - uid { @parsed_uid ||= (/\/([^\/]+)\z/.match raw_info['user_id'])[1] } #https://www.paypal.com/webapps/auth/identity/user/baCNqjGvIxzlbvDCSsfhN3IrQDtQtsVr79AwAjMxekw => baCNqjGvIxzlbvDCSsfhN3IrQDtQtsVr79AwAjMxekw + # https://www.paypal.com/webapps/auth/identity/user/baCNqjGvIxzlbvDCSsfhN3IrQDtQtsVr79AwAjMxekw => baCNqjGvIxzlbvDCSsfhN3IrQDtQtsVr79AwAjMxekw + uid { raw_info['user_id'].scan(Regexp.new('identity/user/([^/]+)')).flatten.first || raw_info['user_id'] } info do - prune!({ - name: raw_info['name'], - email: raw_info['email'], + prune!( + name: raw_info['name'], + email: raw_info['email'], first_name: raw_info['given_name'], - last_name: raw_info['family_name'], - location: build_user_location, - phone: raw_info['phone_number'], - image: raw_info['picture'] - }) + last_name: raw_info['family_name'], + location: location, + phone: raw_info['phone_number'], + image: raw_info['picture'], + time_zone: raw_info['zoneinfo'], + locale: raw_info['locale'] || raw_info['language'] + ) end extra do - prune!({'raw_info' => raw_info}) + prune!(raw_info: raw_info) end def setup_phase if options.sandbox - options.client_options[:site] = SANDBOX_SITE - options.client_options[:authorize_url] = SANDBOX_AUTHORIZE_URL + options.client_options.merge!( + site: SANDBOX_SITE, + authorize_url: SANDBOX_AUTHORIZE_URL + ) end + super end @@ -49,7 +55,10 @@ def callback_url end def raw_info - @raw_info ||= load_identity + @raw_info ||= begin + access_token.options.merge!(mode: :query, param_name: :access_token, grant_type: :authorization_code) + access_token.get('/v1/identity/openidconnect/userinfo', { params: { schema: 'openid'}}).parsed || {} + end end def authorize_params @@ -59,35 +68,28 @@ def authorize_params end end - def custom_build_access_token - access_token = + def build_access_token + verifier = request.params["code"] + redirect_uri = request.params['redirect_uri'] + if request.xhr? && request.params['code'] - verifier = request.params['code'] - redirect_uri = request.params['redirect_uri'] || 'postmessage' - client.auth_code.get_token(verifier, get_token_options(redirect_uri), deep_symbolize(options.auth_token_params || {})) - elsif request.params['code'] && request.params['redirect_uri'] - verifier = request.params['code'] - redirect_uri = request.params['redirect_uri'] - client.auth_code.get_token(verifier, get_token_options(redirect_uri), deep_symbolize(options.auth_token_params || {})) - else - verifier = request.params["code"] - client.auth_code.get_token(verifier, get_token_options(callback_url), deep_symbolize(options.auth_token_params)) + redirect_uri ||= 'postmessage' + elsif !request.params['code'] || !request.params['redirect_uri'] + redirect_uri = callback_url end - access_token - end - alias_method :build_access_token, :custom_build_access_token - private - - def load_identity - access_token.options[:mode] = :query - access_token.options[:param_name] = :access_token - access_token.options[:grant_type] = :authorization_code - access_token.get('/v1/identity/openidconnect/userinfo', { :params => { :schema => 'openid'}}).parsed || {} + client.auth_code.get_token( + verifier, + { redirect_uri: redirect_uri }.merge(token_params.to_hash(symbolize_keys: true)), + deep_symbolize(options.auth_token_params || {}) + ) end - def get_token_options(redirect_uri) - { :redirect_uri => redirect_uri }.merge(token_params.to_hash(:symbolize_keys => true)) + private + + def location + address = raw_info.fetch('address', {}) + address.values_at('locality', 'region', 'country').compact.join(', ') end def prune!(hash) @@ -96,14 +98,6 @@ def prune!(hash) value.nil? || (value.respond_to?(:empty?) && value.empty?) end end - - def build_user_location - return unless raw_info['address'] - location = [ - raw_info['address']['locality'], - raw_info['address']['region'] - ].compact.join(', ') - end end end end From b1acbb9e21e90a417fa4e4817e83ed636ae642a5 Mon Sep 17 00:00:00 2001 From: Joel Van Horn Date: Sun, 10 Sep 2017 01:11:33 -0400 Subject: [PATCH 4/5] Fix rake --- .gitignore | 1 + Gemfile.lock | 53 ----------------------------------------- Rakefile | 2 +- omniauth-paypal.gemspec | 2 +- 4 files changed, 3 insertions(+), 55 deletions(-) delete mode 100644 Gemfile.lock diff --git a/.gitignore b/.gitignore index c111b33..cec3cb5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.gem +Gemfile.lock diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index c3f7831..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,53 +0,0 @@ -PATH - remote: . - specs: - omniauth-paypal (1.3) - omniauth (>= 1.1.1) - omniauth-oauth2 (>= 1.3.1) - -GEM - remote: https://rubygems.org/ - specs: - diff-lcs (1.3) - faraday (0.11.0) - multipart-post (>= 1.2, < 3) - hashie (3.5.5) - json (2.0.3) - jwt (1.5.6) - multi_json (1.12.1) - multi_xml (0.6.0) - multipart-post (2.0.0) - oauth2 (1.3.1) - faraday (>= 0.8, < 0.12) - jwt (~> 1.0) - multi_json (~> 1.3) - multi_xml (~> 0.5) - rack (>= 1.2, < 3) - omniauth (1.6.1) - hashie (>= 3.4.6, < 3.6.0) - rack (>= 1.6.2, < 3) - omniauth-oauth2 (1.4.0) - oauth2 (~> 1.0) - omniauth (~> 1.2) - rack (2.0.1) - rake (12.0.0) - rspec (2.99.0) - rspec-core (~> 2.99.0) - rspec-expectations (~> 2.99.0) - rspec-mocks (~> 2.99.0) - rspec-core (2.99.2) - rspec-expectations (2.99.2) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.99.4) - -PLATFORMS - ruby - -DEPENDENCIES - json - omniauth-paypal! - rake - rspec (~> 2.14) - -BUNDLED WITH - 1.14.6 diff --git a/Rakefile b/Rakefile index b2fb8da..93cb943 100644 --- a/Rakefile +++ b/Rakefile @@ -3,4 +3,4 @@ require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) -task :default => :spec \ No newline at end of file +task :default => :spec diff --git a/omniauth-paypal.gemspec b/omniauth-paypal.gemspec index 0714d1d..b4f8f5a 100644 --- a/omniauth-paypal.gemspec +++ b/omniauth-paypal.gemspec @@ -19,6 +19,6 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'omniauth', '>= 1.1.1' s.add_runtime_dependency 'omniauth-oauth2', '>= 1.3.1' - s.add_development_dependency 'rspec', '~> 2.14' + s.add_development_dependency 'rspec' s.add_development_dependency 'rake' end From 413da808abd3a7e29fbad972b902f2dee3e88202 Mon Sep 17 00:00:00 2001 From: Joel Van Horn Date: Sun, 10 Sep 2017 01:15:21 -0400 Subject: [PATCH 5/5] Updated authors --- omniauth-paypal.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omniauth-paypal.gemspec b/omniauth-paypal.gemspec index b4f8f5a..1778286 100644 --- a/omniauth-paypal.gemspec +++ b/omniauth-paypal.gemspec @@ -5,8 +5,8 @@ require 'omniauth/paypal/version' Gem::Specification.new do |s| s.name = 'omniauth-paypal' s.version = OmniAuth::PayPal::VERSION - s.authors = ['David W. Allen'] - s.email = ['david@datariot.io'] + s.authors = ['David W. Allen', 'Joel Van Horn'] + s.email = ['david@datariot.io', 'joel@joelvanhorn.com'] s.summary = 'PayPal Identity strategy for OmniAuth' s.homepage = 'https://github.com/datariot/omniauth-paypal' s.license = 'MIT'