omniauth-withings-oauth2 1.0.0 → 1.1.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: 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: