omniauth-withings-oauth2 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 790581559a7f50a1b2df09ef40cb2d057ce2d08b
4
- data.tar.gz: d1d7214e92ab218e1cd8b658dd28538d0bcd972e
2
+ SHA256:
3
+ metadata.gz: 919a285f818c60af0dddcb963265cfeace3c6179c098f321590812d445a28015
4
+ data.tar.gz: a1f63f0a1ad0c1a8fa33a3fe7a5b4b757cb607522fbfb1ffac72588d66ef5fa3
5
5
  SHA512:
6
- metadata.gz: ab1226627ec664f3b0dace6d7f383b44d58f041788ca96ff7179e8906b0cdd93b23ab5ac05e0f02cab13c8dd433667e6828554b73d5f5177a389caeaad801b5b
7
- data.tar.gz: f62bd79b20e383e2114acdb95aeb7f575e2b1027acf821250996c7ee365cf6f467b52b33910a845a047ca95636dc1a05ec7ccd651238980ac49250d03ceddb8b
6
+ metadata.gz: 117810510a52949a4d9203727d308e4306c74f181cc10a552a35aaeb83e9818237710ade2aa0a2821f81379bf5f977bc0aaeb0f7e1b2c9a6fe1950aa9927a8f1
7
+ data.tar.gz: cf0e9d103ae7bd31e6603cad397523b2bb5d8f8d5248f3a41c2b6d6f66f6d082580055b351ffd073edae52ba5075a63c0860346e55c641145a884405b1e40c4a
data/.travis.yml CHANGED
@@ -1,6 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2
4
- - 2.3
5
- - 2.4
6
- - 2.5
3
+ - 2.6
4
+ - 2.7
5
+ - 3.0
6
+ - 3.1
7
+ - 3.2
8
+ - 3.3
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # OmniAuth Withings OAuth2 Strategy
2
2
 
3
3
  [![Build Status](https://travis-ci.org/bartimaeus/omniauth-withings-oauth2.svg?branch=master)](https://travis-ci.org/bartimaeus/omniauth-withings-oauth2)
4
+ [![Gem Version](https://badge.fury.io/rb/omniauth-withings-oauth2.svg)](https://badge.fury.io/rb/omniauth-withings-oauth2)
4
5
 
5
6
  A Withings OAuth2 strategy for OmniAuth.
6
7
 
@@ -28,7 +29,7 @@ This is an example that you might put into a Rails initializer at `config/initia
28
29
 
29
30
  ```ruby
30
31
  Rails.application.config.middleware.use OmniAuth::Builder do
31
- provider :withings, ENV['WITHINGS_CLIENT_ID'], ENV['WITHINGS_CLIENT_SECRET'], :scope => 'user.info user.metrics'
32
+ provider :withings, ENV['WITHINGS_CLIENT_ID'], ENV['WITHINGS_CLIENT_SECRET'], :scope => 'user.info,user.metrics'
32
33
  end
33
34
  ```
34
35
 
@@ -42,7 +43,7 @@ For more details, read the withings documentation: http://developer.withings.com
42
43
  You can configure the scope option:
43
44
 
44
45
  ```ruby
45
- provider :withings, ENV['WITHINGS_CLIENT_ID'], ENV['WITHINGS_CLIENT_SECRET'], :scope => 'user.info user.metrics'
46
+ provider :withings, ENV['WITHINGS_CLIENT_ID'], ENV['WITHINGS_CLIENT_SECRET'], :scope => 'user.info,user.metrics,user.activity'
46
47
  ```
47
48
 
48
49
  ## Contributing
@@ -8,7 +8,9 @@ module OmniAuth
8
8
  option :client_options, {
9
9
  :site => 'https://account.withings.com',
10
10
  :authorize_url => 'https://account.withings.com/oauth2_user/authorize2',
11
- :token_url => 'https://account.withings.com/oauth2/token'
11
+ :token_url => 'https://wbsapi.withings.net/v2/oauth2',
12
+ :auth_scheme => :request_body,
13
+ :access_token_class => OmniAuth::WithingsOauth2::AccessToken
12
14
  }
13
15
 
14
16
  option :scope, 'user.info'
@@ -27,6 +29,21 @@ module OmniAuth
27
29
  full_host + script_name + callback_path
28
30
  end
29
31
 
32
+ def build_access_token
33
+ verifier = request.params["code"]
34
+ response = client.auth_code.get_token(
35
+ verifier,
36
+ {
37
+ :redirect_uri => callback_url,
38
+ action: 'requesttoken',
39
+ client_id: options.client_id,
40
+ client_secret: options.client_secret,
41
+ code: verifier,
42
+ grant_type: 'authorization_code'
43
+ }.merge(token_params.to_hash(:symbolize_keys => true)),
44
+ deep_symbolize(options.auth_token_params))
45
+ end
46
+
30
47
  alias :oauth2_access_token :access_token
31
48
 
32
49
  def access_token
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAuth
4
+ module WithingsOauth2
5
+ class AccessToken # rubocop:disable Metrics/ClassLength
6
+ TOKEN_KEYS_STR = %w[access_token id_token token accessToken idToken].freeze
7
+ TOKEN_KEYS_SYM = %i[access_token id_token token accessToken idToken].freeze
8
+ TOKEN_KEY_LOOKUP = TOKEN_KEYS_STR + TOKEN_KEYS_SYM
9
+
10
+ attr_reader :client, :token, :expires_in, :expires_at, :expires_latency, :params
11
+ attr_accessor :options, :refresh_token, :response
12
+
13
+ class << self
14
+ # Initializes an AccessToken from a Hash
15
+ #
16
+ # @param [Client] client the OAuth2::Client instance
17
+ # @param [Hash] hash a hash of AccessToken property values
18
+ # @option hash [String, Symbol] 'access_token', 'id_token', 'token', :access_token, :id_token, or :token the access token
19
+ # @return [AccessToken] the initialized AccessToken
20
+ def from_hash(client, hash)
21
+ fresh = hash["body"].dup
22
+ supported_keys = TOKEN_KEY_LOOKUP & fresh.keys
23
+ key = supported_keys[0]
24
+ extra_tokens_warning(supported_keys, key)
25
+ token = fresh.delete(key)
26
+ new(client, token, fresh)
27
+ end
28
+
29
+ # Initializes an AccessToken from a key/value application/x-www-form-urlencoded string
30
+ #
31
+ # @param [Client] client the OAuth2::Client instance
32
+ # @param [String] kvform the application/x-www-form-urlencoded string
33
+ # @return [AccessToken] the initialized AccessToken
34
+ def from_kvform(client, kvform)
35
+ from_hash(client, Rack::Utils.parse_query(kvform))
36
+ end
37
+
38
+ private
39
+
40
+ # Having too many is sus, and may lead to bugs. Having none is fine (e.g. refresh flow doesn't need a token).
41
+ def extra_tokens_warning(supported_keys, key)
42
+ return if OAuth2.config.silence_extra_tokens_warning
43
+ return if supported_keys.length <= 1
44
+
45
+ warn("OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key (#{supported_keys}); using #{key.inspect}.")
46
+ end
47
+ end
48
+
49
+ # Initialize an AccessToken
50
+ #
51
+ # @param [Client] client the OAuth2::Client instance
52
+ # @param [String] token the Access Token value (optional, may not be used in refresh flows)
53
+ # @param [Hash] opts the options to create the Access Token with
54
+ # @option opts [String] :refresh_token (nil) the refresh_token value
55
+ # @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire
56
+ # @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire
57
+ # @option opts [FixNum, String] :expires_latency (nil) the number of seconds by which AccessToken validity will be reduced to offset latency, @version 2.0+
58
+ # @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value
59
+ # one of :header, :body or :query
60
+ # @option opts [String] :header_format ('Bearer %s') the string format to use for the Authorization header
61
+ # @option opts [String] :param_name ('access_token') the parameter name to use for transmission of the
62
+ # Access Token value in :body or :query transmission mode
63
+ def initialize(client, token, opts = {})
64
+ @client = client
65
+ @token = token.to_s
66
+
67
+ opts = opts.dup
68
+ %i[refresh_token expires_in expires_at expires_latency].each do |arg|
69
+ instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s))
70
+ end
71
+ no_tokens = (@token.nil? || @token.empty?) && (@refresh_token.nil? || @refresh_token.empty?)
72
+ if no_tokens
73
+ if @client.options[:raise_errors]
74
+ error = Error.new(opts)
75
+ raise(error)
76
+ else
77
+ warn('OAuth2::AccessToken has no token')
78
+ end
79
+ end
80
+ # @option opts [Fixnum, String] :expires is deprecated
81
+ @expires_in ||= opts.delete('expires')
82
+ @expires_in &&= @expires_in.to_i
83
+ @expires_at &&= convert_expires_at(@expires_at)
84
+ @expires_latency &&= @expires_latency.to_i
85
+ @expires_at ||= Time.now.to_i + @expires_in if @expires_in
86
+ @expires_at -= @expires_latency if @expires_latency
87
+ @options = {mode: opts.delete(:mode) || :header,
88
+ header_format: opts.delete(:header_format) || 'Bearer %s',
89
+ param_name: opts.delete(:param_name) || 'access_token'}
90
+ @params = opts
91
+ end
92
+
93
+ # Indexer to additional params present in token response
94
+ #
95
+ # @param [String] key entry key to Hash
96
+ def [](key)
97
+ @params[key]
98
+ end
99
+
100
+ # Whether or not the token expires
101
+ #
102
+ # @return [Boolean]
103
+ def expires?
104
+ !!@expires_at
105
+ end
106
+
107
+ # Whether or not the token is expired
108
+ #
109
+ # @return [Boolean]
110
+ def expired?
111
+ expires? && (expires_at <= Time.now.to_i)
112
+ end
113
+
114
+ # Refreshes the current Access Token
115
+ #
116
+ # @return [AccessToken] a new AccessToken
117
+ # @note options should be carried over to the new AccessToken
118
+ def refresh(params = {}, access_token_opts = {})
119
+ raise('A refresh_token is not available') unless refresh_token
120
+
121
+ params[:grant_type] = 'refresh_token'
122
+ params[:refresh_token] = refresh_token
123
+ new_token = @client.get_token(params, access_token_opts)
124
+ new_token.options = options
125
+ if new_token.refresh_token
126
+ # Keep it, if there is one
127
+ else
128
+ new_token.refresh_token = refresh_token
129
+ end
130
+ new_token
131
+ end
132
+ # A compatibility alias
133
+ # @note does not modify the receiver, so bang is not the default method
134
+ alias refresh! refresh
135
+
136
+ # Convert AccessToken to a hash which can be used to rebuild itself with AccessToken.from_hash
137
+ #
138
+ # @return [Hash] a hash of AccessToken property values
139
+ def to_hash
140
+ params.merge(access_token: token, refresh_token: refresh_token, expires_at: expires_at)
141
+ end
142
+
143
+ # Make a request with the Access Token
144
+ #
145
+ # @param [Symbol] verb the HTTP request method
146
+ # @param [String] path the HTTP URL path of the request
147
+ # @param [Hash] opts the options to make the request with
148
+ # @see Client#request
149
+ def request(verb, path, opts = {}, &block)
150
+ configure_authentication!(opts)
151
+ @client.request(verb, path, opts, &block)
152
+ end
153
+
154
+ # Make a GET request with the Access Token
155
+ #
156
+ # @see AccessToken#request
157
+ def get(path, opts = {}, &block)
158
+ request(:get, path, opts, &block)
159
+ end
160
+
161
+ # Make a POST request with the Access Token
162
+ #
163
+ # @see AccessToken#request
164
+ def post(path, opts = {}, &block)
165
+ request(:post, path, opts, &block)
166
+ end
167
+
168
+ # Make a PUT request with the Access Token
169
+ #
170
+ # @see AccessToken#request
171
+ def put(path, opts = {}, &block)
172
+ request(:put, path, opts, &block)
173
+ end
174
+
175
+ # Make a PATCH request with the Access Token
176
+ #
177
+ # @see AccessToken#request
178
+ def patch(path, opts = {}, &block)
179
+ request(:patch, path, opts, &block)
180
+ end
181
+
182
+ # Make a DELETE request with the Access Token
183
+ #
184
+ # @see AccessToken#request
185
+ def delete(path, opts = {}, &block)
186
+ request(:delete, path, opts, &block)
187
+ end
188
+
189
+ # Get the headers hash (includes Authorization token)
190
+ def headers
191
+ {'Authorization' => options[:header_format] % token}
192
+ end
193
+
194
+ private
195
+
196
+ def configure_authentication!(opts)
197
+ case options[:mode]
198
+ when :header
199
+ opts[:headers] ||= {}
200
+ opts[:headers].merge!(headers)
201
+ when :query
202
+ opts[:params] ||= {}
203
+ opts[:params][options[:param_name]] = token
204
+ when :body
205
+ opts[:body] ||= {}
206
+ if opts[:body].is_a?(Hash)
207
+ opts[:body][options[:param_name]] = token
208
+ else
209
+ opts[:body] += "&#{options[:param_name]}=#{token}"
210
+ end
211
+ # @todo support for multi-part (file uploads)
212
+ else
213
+ raise("invalid :mode option of #{options[:mode]}")
214
+ end
215
+ end
216
+
217
+ def convert_expires_at(expires_at)
218
+ Time.iso8601(expires_at.to_s).to_i
219
+ rescue ArgumentError
220
+ expires_at.to_i
221
+ end
222
+ end
223
+ end
224
+ end
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module WithingsOauth2
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  end
@@ -1,2 +1,3 @@
1
1
  require "omniauth-withings-oauth2/version"
2
+ require "omniauth/withings_oauth2/access_token"
2
3
  require "omniauth/strategies/withings"
@@ -18,7 +18,7 @@ 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-oauth2', '~> 1.2'
21
+ gem.add_runtime_dependency 'omniauth-oauth2', '~> 1.8'
22
22
 
23
23
  gem.add_development_dependency 'bundler', '>= 1.16', '< 3.0'
24
24
  gem.add_development_dependency 'rake', '~> 12.3'
@@ -18,7 +18,7 @@ describe OmniAuth::Strategies::Withings do
18
18
  end
19
19
 
20
20
  it 'has correct `token_url`' do
21
- expect(subject.client.options[:token_url]).to eq('https://account.withings.com/oauth2/token')
21
+ expect(subject.client.options[:token_url]).to eq('https://wbsapi.withings.net/v2/oauth2')
22
22
  end
23
23
  end
24
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-withings-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Shelley
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-04 00:00:00.000000000 Z
11
+ date: 2024-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth-oauth2
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
19
+ version: '1.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.2'
26
+ version: '1.8'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +105,7 @@ files:
105
105
  - lib/omniauth-withings-oauth2.rb
106
106
  - lib/omniauth-withings-oauth2/version.rb
107
107
  - lib/omniauth/strategies/withings.rb
108
+ - lib/omniauth/withings_oauth2/access_token.rb
108
109
  - omniauth-withings-oauth2.gemspec
109
110
  - spec/omniauth/strategies/withings_spec.rb
110
111
  - spec/spec_helper.rb
@@ -112,7 +113,7 @@ homepage: https://github.com/bartimaeus/omniauth-withings-oauth2
112
113
  licenses:
113
114
  - MIT
114
115
  metadata: {}
115
- post_install_message:
116
+ post_install_message:
116
117
  rdoc_options: []
117
118
  require_paths:
118
119
  - lib
@@ -127,9 +128,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
128
  - !ruby/object:Gem::Version
128
129
  version: '0'
129
130
  requirements: []
130
- rubyforge_project:
131
- rubygems_version: 2.5.2.3
132
- signing_key:
131
+ rubygems_version: 3.3.7
132
+ signing_key:
133
133
  specification_version: 4
134
134
  summary: Withings OAuth2 strategy for OmniAuth.
135
135
  test_files: