omniauth-linkedin-oauth2 0.2.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ab29207dc1df42074dfd2f67013de227d2c6975d
4
- data.tar.gz: 2228ae416dc859c6de0e475e5af90f3becba4160
2
+ SHA256:
3
+ metadata.gz: 6d11513de3f678424cce8734f022e66ccbc734287753cb2f0ac36632f8924f49
4
+ data.tar.gz: b8bff314c85bc29a8da42eb2e9f31337cf82b1ae79a6004f2757d24e1c2742c8
5
5
  SHA512:
6
- metadata.gz: 61991a55b3fd1294691f8be37afa2abca4812fb6f48b381bca66fa3e8655862cb6f0fe7e866a523f0d59467a610c5c8185252d2c37e8e2e997da56f59a38f0b6
7
- data.tar.gz: 1cdae475837c9c89d7d41769f73799754c84b92f80686502e87b30919c9d3f380c27836804d23977d709c14c11514afcce8554a7a9235427644f07b2413830a4
6
+ metadata.gz: c8eb5cb6af45018dc4bb6a883582516710033a8ce24d87e13d2b31b72563b04e45676d990be9d864e5f5c3f190f8a0a8b7edf99395f56d931bc21df420212c9e
7
+ data.tar.gz: 9a1bb809c54de350c45c0f54acfc9cf14a01a2c0e242fd42b99aecd42170ece335bb6a1447f1c28bcd490eff0dd08d71afcfa34e43872d9064b62c0e5455a0d4
@@ -1,3 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
3
+ - 2.2
4
+ - 2.3
5
+ - 2.4
6
+ - 2.5
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  A LinkedIn OAuth2 strategy for OmniAuth.
6
6
 
7
- For more details, read the LinkedIn documentation: https://developer.linkedin.com/documents/authentication
7
+ For more details, read the LinkedIn documentation: https://developer.linkedin.com/docs/oauth2
8
8
 
9
9
  ## Installation
10
10
 
@@ -22,6 +22,8 @@ Or install it yourself as:
22
22
 
23
23
  ## Upgrading
24
24
 
25
+ This version is a major upgrade to the LinkedIn API version 2. As such, it switches from the soon to be no longer available `r_basicprofile` to `r_liteprofile`. This results in a much limited set of data that we can get from LinkedIn.
26
+
25
27
  Previous versions of this gem used the provider name `:linkedin_oauth2`. In order to provide a cleaner upgrade path for users who were previously using the OAuth 1.0 omniauth adapter for LinkedIn [https://github.com/skorks/omniauth-linkedin], this has been renamed to just `:linkedin`.
26
28
 
27
29
  Users who are upgrading from previous versions of this gem may need to update their Omniauth and/or Devise configurations to use the shorter provider name.
@@ -43,16 +45,16 @@ You can now access the OmniAuth LinkedIn OAuth2 URL: `/auth/linkedin`.
43
45
  ## Granting Member Permissions to Your Application
44
46
 
45
47
  With the LinkedIn API, you have the ability to specify which permissions you want users to grant your application.
46
- For more details, read the LinkedIn documentation: https://developer.linkedin.com/documents/authentication
48
+ For more details, read the LinkedIn documentation: https://developer.linkedin.com/docs/oauth2
47
49
 
48
50
  By default, omniauth-linkedin-oauth2 requests the following permissions:
49
51
 
50
- 'r_basicprofile r_emailaddress'
52
+ 'r_liteprofile r_emailaddress'
51
53
 
52
54
  You can configure the scope option:
53
55
 
54
56
  ```ruby
55
- provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :scope => 'r_fullprofile r_emailaddress r_network'
57
+ provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :scope => 'r_literofile'
56
58
  ```
57
59
 
58
60
  ## Profile Fields
@@ -60,25 +62,21 @@ provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :scope => 'r_fu
60
62
  When specifying which permissions you want to users to grant to your application, you will probably want to specify the array of fields that you want returned in the omniauth hash. The list of default fields is as follows:
61
63
 
62
64
  ```ruby
63
- ['id', 'email-address', 'first-name', 'last-name', 'headline', 'location', 'industry', 'picture-url', 'public-profile-url']
65
+ ['id', 'first-name', 'last-name', 'picture-url', 'email-address']
64
66
  ```
65
67
 
66
- Here's an example of a possible configuration where the fields returned from the API are: id, email-address, first-name and last-name.
68
+ Here's an example of a possible configuration where the fields returned from the API are: id, first-name and last-name.
67
69
 
68
70
  ```ruby
69
- provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :fields => ['id', 'email-address', 'first-name', 'last-name']
71
+ provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :fields => ['id', 'first-name', 'last-name']
70
72
  ```
71
73
 
72
- To see a complete list of available fields, consult the LinkedIn documentation at: https://developer.linkedin.com/documents/profile-fields
73
-
74
- ## Other Options
75
-
76
- * `secure_image_url` - Set to `true` to use https for the profile picture url. Default is `false`.
74
+ To see a complete list of available fields, consult the LinkedIn documentation at: https://developer.linkedin.com/docs/fields
77
75
 
78
76
  ## Contributing
79
77
 
80
- 1. Fork it
81
- 2. Create your feature branch (`git checkout -b my-new-feature`)
82
- 3. Commit your changes (`git commit -am 'Add some feature'`)
83
- 4. Push to the branch (`git push origin my-new-feature`)
84
- 5. Create new Pull Request
78
+ 1. Fork it
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create new Pull Request
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module LinkedInOAuth2
3
- VERSION = "0.2.5"
3
+ VERSION = '1.0.0'
4
4
  end
5
5
  end
@@ -3,45 +3,34 @@ require 'omniauth-oauth2'
3
3
  module OmniAuth
4
4
  module Strategies
5
5
  class LinkedIn < OmniAuth::Strategies::OAuth2
6
- # Give your strategy a name.
7
6
  option :name, 'linkedin'
8
7
 
9
- # This is where you pass the options you would pass when
10
- # initializing your consumer from the OAuth gem.
11
8
  option :client_options, {
12
9
  :site => 'https://api.linkedin.com',
13
10
  :authorize_url => 'https://www.linkedin.com/oauth/v2/authorization?response_type=code',
14
11
  :token_url => 'https://www.linkedin.com/oauth/v2/accessToken'
15
12
  }
16
13
 
17
- option :scope, 'r_basicprofile r_emailaddress'
18
- option :fields, ['id', 'email-address', 'first-name', 'last-name', 'headline', 'location', 'industry', 'picture-url', 'public-profile-url']
14
+ option :scope, 'r_liteprofile r_emailaddress'
15
+ option :fields, ['id', 'first-name', 'last-name', 'picture-url', 'email-address']
19
16
 
20
- # These are called after authentication has succeeded. If
21
- # possible, you should try to set the UID without making
22
- # additional calls (if the user id is returned with the token
23
- # or as a URI parameter). This may not be possible with all
24
- # providers.
25
- uid { raw_info['id'] }
17
+ uid do
18
+ raw_info['id']
19
+ end
26
20
 
27
21
  info do
28
22
  {
29
- :name => user_name,
30
- :email => raw_info['emailAddress'],
31
- :nickname => user_name,
32
- :first_name => raw_info['firstName'],
33
- :last_name => raw_info['lastName'],
34
- :location => raw_info['location'],
35
- :description => raw_info['headline'],
36
- :image => raw_info['pictureUrl'],
37
- :urls => {
38
- 'public_profile' => raw_info['publicProfileUrl']
39
- }
23
+ :email => email_address,
24
+ :first_name => localized_field('firstName'),
25
+ :last_name => localized_field('lastName'),
26
+ :picture_url => picture_url
40
27
  }
41
28
  end
42
29
 
43
30
  extra do
44
- { 'raw_info' => raw_info }
31
+ {
32
+ 'raw_info' => raw_info
33
+ }
45
34
  end
46
35
 
47
36
  def callback_url
@@ -52,28 +41,93 @@ module OmniAuth
52
41
 
53
42
  def access_token
54
43
  ::OAuth2::AccessToken.new(client, oauth2_access_token.token, {
55
- :mode => :query,
56
- :param_name => 'oauth2_access_token',
57
44
  :expires_in => oauth2_access_token.expires_in,
58
45
  :expires_at => oauth2_access_token.expires_at
59
46
  })
60
47
  end
61
48
 
62
49
  def raw_info
63
- @raw_info ||= access_token.get("/v1/people/~:(#{option_fields.join(',')})?format=json").parsed
50
+ @raw_info ||= access_token.get(profile_endpoint).parsed
64
51
  end
65
52
 
66
53
  private
67
54
 
68
- def option_fields
69
- fields = options.fields
70
- fields.map! { |f| f == "picture-url" ? "picture-url;secure=true" : f } if !!options[:secure_image_url]
71
- fields
55
+ def email_address
56
+ if options.fields.include? 'email-address'
57
+ fetch_email_address
58
+ parse_email_address
59
+ end
60
+ end
61
+
62
+ def fetch_email_address
63
+ @email_address_response ||= access_token.get(email_address_endpoint).parsed
64
+ end
65
+
66
+ def parse_email_address
67
+ return unless email_address_available?
68
+
69
+ @email_address_response['elements'].first['handle~']['emailAddress']
70
+ end
71
+
72
+ def email_address_available?
73
+ @email_address_response['elements'] &&
74
+ @email_address_response['elements'].is_a?(Array) &&
75
+ @email_address_response['elements'].first &&
76
+ @email_address_response['elements'].first['handle~']
77
+ end
78
+
79
+ def fields_mapping
80
+ {
81
+ 'id' => 'id',
82
+ 'first-name' => 'firstName',
83
+ 'last-name' => 'lastName',
84
+ 'picture-url' => 'profilePicture(displayImage~:playableStreams)'
85
+ }
86
+ end
87
+
88
+ def fields
89
+ options.fields.each.with_object([]) do |field, result|
90
+ result << fields_mapping[field] if fields_mapping.has_key? field
91
+ end
92
+ end
93
+
94
+ def localized_field field_name
95
+ return unless localized_field_available? field_name
96
+
97
+ raw_info[field_name]['localized'][field_locale(field_name)]
98
+ end
99
+
100
+ def field_locale field_name
101
+ "#{ raw_info[field_name]['preferredLocale']['language'] }_" \
102
+ "#{ raw_info[field_name]['preferredLocale']['country'] }"
103
+ end
104
+
105
+ def localized_field_available? field_name
106
+ raw_info[field_name] && raw_info[field_name]['localized']
107
+ end
108
+
109
+ def picture_url
110
+ return unless picture_available?
111
+
112
+ picture_references.last['identifiers'].first['identifier']
113
+ end
114
+
115
+ def picture_available?
116
+ raw_info['profilePicture'] &&
117
+ raw_info['profilePicture']['displayImage~'] &&
118
+ picture_references
119
+ end
120
+
121
+ def picture_references
122
+ raw_info['profilePicture']['displayImage~']['elements']
123
+ end
124
+
125
+ def email_address_endpoint
126
+ '/v2/emailAddress?q=members&projection=(elements*(handle~))'
72
127
  end
73
128
 
74
- def user_name
75
- name = "#{raw_info['firstName']} #{raw_info['lastName']}".strip
76
- name.empty? ? nil : name
129
+ def profile_endpoint
130
+ "/v2/me?projection=(#{ fields.join(',') })"
77
131
  end
78
132
  end
79
133
  end
@@ -18,12 +18,11 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_runtime_dependency 'omniauth', '~> 1.0'
22
21
  gem.add_runtime_dependency 'omniauth-oauth2'
23
22
 
24
- gem.add_development_dependency 'bundler', '~> 1.3'
23
+ gem.add_development_dependency 'bundler'
25
24
  gem.add_development_dependency 'rake'
26
25
 
27
- gem.add_development_dependency 'rspec', '~> 2.14.1'
26
+ gem.add_development_dependency 'rspec'
28
27
  gem.add_development_dependency 'simplecov'
29
28
  end
@@ -4,7 +4,7 @@ require 'omniauth-linkedin-oauth2'
4
4
  describe OmniAuth::Strategies::LinkedIn do
5
5
  subject { OmniAuth::Strategies::LinkedIn.new(nil) }
6
6
 
7
- it 'should add a camelization for itself' do
7
+ it 'adds camelization for itself' do
8
8
  expect(OmniAuth::Utils.camelize('linkedin')).to eq('LinkedIn')
9
9
  end
10
10
 
@@ -13,11 +13,11 @@ describe OmniAuth::Strategies::LinkedIn do
13
13
  expect(subject.client.site).to eq('https://api.linkedin.com')
14
14
  end
15
15
 
16
- it 'has correct authorize url' do
16
+ it 'has correct `authorize_url`' do
17
17
  expect(subject.client.options[:authorize_url]).to eq('https://www.linkedin.com/oauth/v2/authorization?response_type=code')
18
18
  end
19
19
 
20
- it 'has correct token url' do
20
+ it 'has correct `token_url`' do
21
21
  expect(subject.client.options[:token_url]).to eq('https://www.linkedin.com/oauth/v2/accessToken')
22
22
  end
23
23
  end
@@ -30,7 +30,7 @@ describe OmniAuth::Strategies::LinkedIn do
30
30
 
31
31
  describe '#uid' do
32
32
  before :each do
33
- allow(subject).to receive(:raw_info) { { 'id' => 'uid' } }
33
+ allow(subject).to receive(:raw_info) { Hash['id' => 'uid'] }
34
34
  end
35
35
 
36
36
  it 'returns the id from raw_info' do
@@ -38,84 +38,75 @@ describe OmniAuth::Strategies::LinkedIn do
38
38
  end
39
39
  end
40
40
 
41
- describe '#info' do
41
+ describe '#info / #raw_info' do
42
+ let(:access_token) { instance_double OAuth2::AccessToken }
43
+
44
+ let(:parsed_response) { Hash[:foo => 'bar'] }
45
+
46
+ let(:profile_endpoint) { '/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))' }
47
+ let(:email_address_endpoint) { '/v2/emailAddress?q=members&projection=(elements*(handle~))' }
48
+
49
+ let(:email_address_response) { instance_double OAuth2::Response, parsed: parsed_response }
50
+ let(:profile_response) { instance_double OAuth2::Response, parsed: parsed_response }
51
+
42
52
  before :each do
43
- allow(subject).to receive(:raw_info) { {} }
53
+ allow(subject).to receive(:access_token).and_return access_token
54
+
55
+ allow(access_token).to receive(:get)
56
+ .with(email_address_endpoint)
57
+ .and_return(email_address_response)
58
+
59
+ allow(access_token).to receive(:get)
60
+ .with(profile_endpoint)
61
+ .and_return(profile_response)
44
62
  end
45
63
 
46
- context 'and therefore has all the necessary fields' do
47
- it { expect(subject.info).to have_key :name }
48
- it { expect(subject.info).to have_key :email }
49
- it { expect(subject.info).to have_key :nickname }
50
- it { expect(subject.info).to have_key :first_name }
51
- it { expect(subject.info).to have_key :last_name }
52
- it { expect(subject.info).to have_key :location }
53
- it { expect(subject.info).to have_key :description }
54
- it { expect(subject.info).to have_key :image }
55
- it { expect(subject.info).to have_key :urls }
64
+ it 'returns parsed responses using access token' do
65
+ expect(subject.info).to have_key :email
66
+ expect(subject.info).to have_key :first_name
67
+ expect(subject.info).to have_key :last_name
68
+ expect(subject.info).to have_key :picture_url
69
+
70
+ expect(subject.raw_info).to eq({ :foo => 'bar' })
56
71
  end
57
72
  end
58
73
 
59
74
  describe '#extra' do
75
+ let(:raw_info) { Hash[:foo => 'bar'] }
76
+
60
77
  before :each do
61
- allow(subject).to receive(:raw_info) { { :foo => 'bar' } }
78
+ allow(subject).to receive(:raw_info).and_return raw_info
62
79
  end
63
80
 
64
- it { expect(subject.extra['raw_info']).to eq({ :foo => 'bar' }) }
81
+ specify { expect(subject.extra['raw_info']).to eq raw_info }
65
82
  end
66
83
 
67
84
  describe '#access_token' do
68
- before :each do
69
- allow(subject).to receive(:oauth2_access_token) { double('oauth2 access token', :expires_in => 3600, :expires_at => 946688400).as_null_object }
85
+ let(:expires_in) { 3600 }
86
+ let(:expires_at) { 946688400 }
87
+ let(:token) { 'token' }
88
+ let(:access_token) do
89
+ instance_double OAuth2::AccessToken, :expires_in => expires_in,
90
+ :expires_at => expires_at, :token => token
70
91
  end
71
92
 
72
- it { expect(subject.access_token.expires_in).to eq(3600) }
73
- it { expect(subject.access_token.expires_at).to eq(946688400) }
74
- end
75
-
76
- describe '#raw_info' do
77
93
  before :each do
78
- access_token = double('access token')
79
- response = double('response', :parsed => { :foo => 'bar' })
80
- expect(access_token).to receive(:get).with("/v1/people/~:(baz,qux)?format=json").and_return(response)
81
-
82
- allow(subject).to receive(:option_fields) { ['baz', 'qux'] }
83
- allow(subject).to receive(:access_token) { access_token }
94
+ allow(subject).to receive(:oauth2_access_token).and_return access_token
84
95
  end
85
96
 
86
- it 'returns parsed response from access token' do
87
- expect(subject.raw_info).to eq({ :foo => 'bar' })
88
- end
97
+ specify { expect(subject.access_token.expires_in).to eq expires_in }
98
+ specify { expect(subject.access_token.expires_at).to eq expires_at }
89
99
  end
90
100
 
91
101
  describe '#authorize_params' do
92
102
  describe 'scope' do
93
103
  before :each do
94
- subject.stub(:session => {})
104
+ allow(subject).to receive(:session).and_return({})
95
105
  end
96
106
 
97
107
  it 'sets default scope' do
98
- expect(subject.authorize_params['scope']).to eq('r_basicprofile r_emailaddress')
108
+ expect(subject.authorize_params['scope']).to eq('r_liteprofile r_emailaddress')
99
109
  end
100
110
  end
101
111
  end
102
-
103
- describe '#option_fields' do
104
- it 'returns options fields' do
105
- subject.stub(:options => double('options', :fields => ['foo', 'bar']).as_null_object)
106
- expect(subject.send(:option_fields)).to eq(['foo', 'bar'])
107
- end
108
-
109
- it 'http avatar image by default' do
110
- subject.stub(:options => double('options', :fields => ['picture-url']))
111
- allow(subject.options).to receive(:[]).with(:secure_image_url).and_return(false)
112
- expect(subject.send(:option_fields)).to eq(['picture-url'])
113
- end
114
-
115
- it 'https avatar image if secure_image_url truthy' do
116
- subject.stub(:options => double('options', :fields => ['picture-url']))
117
- allow(subject.options).to receive(:[]).with(:secure_image_url).and_return(true)
118
- expect(subject.send(:option_fields)).to eq(['picture-url;secure=true'])
119
- end
120
- end
121
112
  end
@@ -8,7 +8,6 @@ SimpleCov.start
8
8
  #
9
9
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
10
10
  RSpec.configure do |config|
11
- config.treat_symbols_as_metadata_keys_with_true_values = true
12
11
  config.run_all_when_everything_filtered = true
13
12
  config.filter_run :focus
14
13
 
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-linkedin-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Décio Ferreira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-11 00:00:00.000000000 Z
11
+ date: 2019-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: omniauth
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: omniauth-oauth2
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -42,16 +28,16 @@ dependencies:
42
28
  name: bundler
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
- - - "~>"
31
+ - - ">="
46
32
  - !ruby/object:Gem::Version
47
- version: '1.3'
33
+ version: '0'
48
34
  type: :development
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
- - - "~>"
38
+ - - ">="
53
39
  - !ruby/object:Gem::Version
54
- version: '1.3'
40
+ version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rake
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +56,16 @@ dependencies:
70
56
  name: rspec
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - "~>"
59
+ - - ">="
74
60
  - !ruby/object:Gem::Version
75
- version: 2.14.1
61
+ version: '0'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - "~>"
66
+ - - ">="
81
67
  - !ruby/object:Gem::Version
82
- version: 2.14.1
68
+ version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: simplecov
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -135,8 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
121
  - !ruby/object:Gem::Version
136
122
  version: '0'
137
123
  requirements: []
138
- rubyforge_project:
139
- rubygems_version: 2.6.11
124
+ rubygems_version: 3.0.1
140
125
  signing_key:
141
126
  specification_version: 4
142
127
  summary: A LinkedIn OAuth2 strategy for OmniAuth.