diff --git a/.gitignore b/.gitignore index c111b33..cec3cb5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.gem +Gemfile.lock 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 deleted file mode 100644 index 4e2ed29..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,53 +0,0 @@ -PATH - remote: . - specs: - omniauth-paypal (1.3) - omniauth-oauth2 (~> 1.3.1) - -GEM - remote: https://rubygems.org/ - specs: - diff-lcs (1.2.4) - faraday (0.9.1) - 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) - 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.3.1) - 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) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.3) - -PLATFORMS - ruby - -DEPENDENCIES - json - omniauth-oauth2 (~> 1.3.1) - omniauth-paypal! - rake - rspec (~> 2.14) - -BUNDLED WITH - 1.10.6 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 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/lib/omniauth/strategies/paypal.rb b/lib/omniauth/strategies/paypal.rb index d240b0c..7077f43 100644 --- a/lib/omniauth/strategies/paypal.rb +++ b/lib/omniauth/strategies/paypal.rb @@ -3,62 +3,62 @@ 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', - :setup => true + 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'], - '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'] - }) + prune!( + name: raw_info['name'], + email: raw_info['email'], + first_name: raw_info['given_name'], + 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!({ - '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 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 + def callback_url + options[:redirect_uri] || (full_host + script_name + callback_path) + 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 @@ -68,21 +68,36 @@ 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 || {} - end + def build_access_token + verifier = request.params["code"] + redirect_uri = request.params['redirect_uri'] - def prune!(hash) - hash.delete_if do |_, value| - prune!(value) if value.is_a?(Hash) - value.nil? || (value.respond_to?(:empty?) && value.empty?) - end + if request.xhr? && request.params['code'] + redirect_uri ||= 'postmessage' + elsif !request.params['code'] || !request.params['redirect_uri'] + redirect_uri = callback_url end + 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 + + private + + def location + address = raw_info.fetch('address', {}) + address.values_at('locality', 'region', 'country').compact.join(', ') + 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 end end end diff --git a/omniauth-paypal.gemspec b/omniauth-paypal.gemspec index 94131b2..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' @@ -16,8 +16,9 @@ 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 'rspec' s.add_development_dependency 'rake' end