oauth2 1.4.4 → 1.4.11

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -63
  3. data/CODE_OF_CONDUCT.md +105 -46
  4. data/CONTRIBUTING.md +27 -1
  5. data/LICENSE +1 -1
  6. data/README.md +331 -123
  7. data/SECURITY.md +26 -0
  8. data/lib/oauth2/access_token.rb +11 -8
  9. data/lib/oauth2/authenticator.rb +4 -2
  10. data/lib/oauth2/client.rb +131 -50
  11. data/lib/oauth2/error.rb +3 -1
  12. data/lib/oauth2/mac_token.rb +19 -11
  13. data/lib/oauth2/response.rb +7 -3
  14. data/lib/oauth2/strategy/assertion.rb +6 -4
  15. data/lib/oauth2/strategy/auth_code.rb +3 -1
  16. data/lib/oauth2/strategy/base.rb +2 -0
  17. data/lib/oauth2/strategy/client_credentials.rb +3 -1
  18. data/lib/oauth2/strategy/implicit.rb +3 -1
  19. data/lib/oauth2/strategy/password.rb +5 -3
  20. data/lib/oauth2/version.rb +9 -3
  21. data/lib/oauth2.rb +2 -0
  22. metadata +70 -103
  23. data/.document +0 -5
  24. data/.gitignore +0 -19
  25. data/.jrubyrc +0 -1
  26. data/.rspec +0 -2
  27. data/.rubocop.yml +0 -80
  28. data/.rubocop_rspec.yml +0 -26
  29. data/.rubocop_todo.yml +0 -15
  30. data/.ruby-version +0 -1
  31. data/.travis.yml +0 -87
  32. data/Gemfile +0 -40
  33. data/Rakefile +0 -45
  34. data/gemfiles/jruby_1.7.gemfile +0 -11
  35. data/gemfiles/jruby_9.0.gemfile +0 -7
  36. data/gemfiles/jruby_9.1.gemfile +0 -3
  37. data/gemfiles/jruby_9.2.gemfile +0 -3
  38. data/gemfiles/jruby_head.gemfile +0 -3
  39. data/gemfiles/ruby_1.9.gemfile +0 -11
  40. data/gemfiles/ruby_2.0.gemfile +0 -6
  41. data/gemfiles/ruby_2.1.gemfile +0 -6
  42. data/gemfiles/ruby_2.2.gemfile +0 -3
  43. data/gemfiles/ruby_2.3.gemfile +0 -3
  44. data/gemfiles/ruby_2.4.gemfile +0 -3
  45. data/gemfiles/ruby_2.5.gemfile +0 -3
  46. data/gemfiles/ruby_2.6.gemfile +0 -9
  47. data/gemfiles/ruby_2.7.gemfile +0 -9
  48. data/gemfiles/ruby_head.gemfile +0 -9
  49. data/gemfiles/truffleruby.gemfile +0 -3
  50. data/oauth2.gemspec +0 -52
data/lib/oauth2/client.rb CHANGED
@@ -1,9 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'logger'
3
5
 
4
6
  module OAuth2
7
+ ConnectionError = Class.new(Faraday::ConnectionFailed)
5
8
  # The OAuth2::Client class
6
9
  class Client # rubocop:disable Metrics/ClassLength
10
+ RESERVED_PARAM_KEYS = %w[headers parse].freeze
11
+
7
12
  attr_reader :id, :secret, :site
8
13
  attr_accessor :options
9
14
  attr_writer :connection
@@ -14,17 +19,18 @@ module OAuth2
14
19
  #
15
20
  # @param [String] client_id the client_id value
16
21
  # @param [String] client_secret the client_secret value
17
- # @param [Hash] opts the options to create the client with
18
- # @option opts [String] :site the OAuth2 provider site host
19
- # @option opts [String] :redirect_uri the absolute URI to the Redirection Endpoint for use in authorization grants and token exchange
20
- # @option opts [String] :authorize_url ('/oauth/authorize') absolute or relative URL path to the Authorization endpoint
21
- # @option opts [String] :token_url ('/oauth/token') absolute or relative URL path to the Token endpoint
22
- # @option opts [Symbol] :token_method (:post) HTTP method to use to request token (:get or :post)
23
- # @option opts [Symbol] :auth_scheme (:basic_auth) HTTP method to use to authorize request (:basic_auth or :request_body)
24
- # @option opts [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday with
25
- # @option opts [FixNum] :max_redirects (5) maximum number of redirects to follow
26
- # @option opts [Boolean] :raise_errors (true) whether or not to raise an OAuth2::Error
27
- # on responses with 400+ status codes
22
+ # @param [Hash] options the options to create the client with
23
+ # @option options [String] :site the OAuth2 provider site host
24
+ # @option options [String] :redirect_uri the absolute URI to the Redirection Endpoint for use in authorization grants and token exchange
25
+ # @option options [String] :authorize_url ('oauth/authorize') absolute or relative URL path to the Authorization endpoint
26
+ # @option options [String] :token_url ('oauth/token') absolute or relative URL path to the Token endpoint
27
+ # @option options [Symbol] :token_method (:post) HTTP method to use to request token (:get or :post)
28
+ # @option options [Symbol] :auth_scheme (:basic_auth) HTTP method to use to authorize request (:basic_auth or :request_body)
29
+ # @option options [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday with
30
+ # @option options [FixNum] :max_redirects (5) maximum number of redirects to follow
31
+ # @option options [Boolean] :raise_errors (true) whether or not to raise an OAuth2::Error on responses with 400+ status codes
32
+ # @option options [Logger] :logger (::Logger.new($stdout)) which logger to use when OAUTH_DEBUG is enabled
33
+ # @option options [Proc] (DEPRECATED) :extract_access_token proc that extracts the access token from the response
28
34
  # @yield [builder] The Faraday connection builder
29
35
  def initialize(client_id, client_secret, options = {}, &block)
30
36
  opts = options.dup
@@ -32,20 +38,22 @@ module OAuth2
32
38
  @secret = client_secret
33
39
  @site = opts.delete(:site)
34
40
  ssl = opts.delete(:ssl)
35
- @options = {:authorize_url => '/oauth/authorize',
36
- :token_url => '/oauth/token',
37
- :token_method => :post,
38
- :auth_scheme => :request_body,
39
- :connection_opts => {},
41
+ @options = {:authorize_url => 'oauth/authorize',
42
+ :token_url => 'oauth/token',
43
+ :token_method => :post,
44
+ :auth_scheme => :request_body,
45
+ :connection_opts => {},
40
46
  :connection_build => block,
41
- :max_redirects => 5,
42
- :raise_errors => true}.merge(opts)
47
+ :max_redirects => 5,
48
+ :raise_errors => true,
49
+ :extract_access_token => DEFAULT_EXTRACT_ACCESS_TOKEN, # DEPRECATED
50
+ :logger => ::Logger.new($stdout)}.merge(opts)
43
51
  @options[:connection_opts][:ssl] = ssl if ssl
44
52
  end
45
53
 
46
54
  # Set the site host
47
55
  #
48
- # @param [String] the OAuth2 provider site host
56
+ # @param value [String] the OAuth2 provider site host
49
57
  def site=(value)
50
58
  @connection = nil
51
59
  @site = value
@@ -53,15 +61,16 @@ module OAuth2
53
61
 
54
62
  # The Faraday connection object
55
63
  def connection
56
- @connection ||= begin
57
- conn = Faraday.new(site, options[:connection_opts])
58
- if options[:connection_build]
59
- conn.build do |b|
60
- options[:connection_build].call(b)
64
+ @connection ||=
65
+ Faraday.new(site, options[:connection_opts]) do |builder|
66
+ oauth_debug_logging(builder)
67
+ if options[:connection_build]
68
+ options[:connection_build].call(builder)
69
+ else
70
+ builder.request :url_encoded # form-encode POST params
71
+ builder.adapter Faraday.default_adapter # make requests with Net::HTTP
61
72
  end
62
73
  end
63
- conn
64
- end
65
74
  end
66
75
 
67
76
  # The authorize endpoint URL of the OAuth2 provider
@@ -91,15 +100,18 @@ module OAuth2
91
100
  # code response for this request. Will default to client option
92
101
  # @option opts [Symbol] :parse @see Response::initialize
93
102
  # @yield [req] The Faraday request
94
- def request(verb, url, opts = {}) # rubocop:disable CyclomaticComplexity, MethodLength, Metrics/AbcSize
95
- connection.response :logger, ::Logger.new($stdout) if ENV['OAUTH_DEBUG'] == 'true'
96
-
103
+ def request(verb, url, opts = {}) # rubocop:disable Metrics/AbcSize
97
104
  url = connection.build_url(url).to_s
98
105
 
99
- response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req|
100
- req.params.update(opts[:params]) if opts[:params]
101
- yield(req) if block_given?
106
+ begin
107
+ response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req|
108
+ req.params.update(opts[:params]) if opts[:params]
109
+ yield(req) if block_given?
110
+ end
111
+ rescue Faraday::ConnectionFailed => e
112
+ raise ConnectionError, e
102
113
  end
114
+
103
115
  response = Response.new(response, :parse => opts[:parse])
104
116
 
105
117
  case response.status
@@ -107,17 +119,25 @@ module OAuth2
107
119
  opts[:redirect_count] ||= 0
108
120
  opts[:redirect_count] += 1
109
121
  return response if opts[:redirect_count] > options[:max_redirects]
122
+
110
123
  if response.status == 303
111
124
  verb = :get
112
125
  opts.delete(:body)
113
126
  end
114
- request(verb, response.headers['location'], opts)
127
+ location = response.headers['location']
128
+ if location
129
+ request(verb, location, opts)
130
+ else
131
+ error = Error.new(response)
132
+ raise(error, "Got #{response.status} status code, but no Location header was present")
133
+ end
115
134
  when 200..299, 300..399
116
135
  # on non-redirecting 3xx statuses, just return the response
117
136
  response
118
137
  when 400..599
119
138
  error = Error.new(response)
120
139
  raise(error) if opts.fetch(:raise_errors, options[:raise_errors])
140
+
121
141
  response.error = error
122
142
  response
123
143
  else
@@ -128,12 +148,21 @@ module OAuth2
128
148
 
129
149
  # Initializes an AccessToken by making a request to the token endpoint
130
150
  #
131
- # @param [Hash] params a Hash of params for the token endpoint
132
- # @param [Hash] access token options, to pass to the AccessToken object
133
- # @param [Class] class of access token for easier subclassing OAuth2::AccessToken
151
+ # @param params [Hash] a Hash of params for the token endpoint
152
+ # @param access_token_opts [Hash] access token options, to pass to the AccessToken object
153
+ # @param access_token_class [Class] class of access token for easier subclassing OAuth2::AccessToken
134
154
  # @return [AccessToken] the initialized AccessToken
135
- def get_token(params, access_token_opts = {}, access_token_class = AccessToken) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
136
- params = Authenticator.new(id, secret, options[:auth_scheme]).apply(params)
155
+ def get_token(params, access_token_opts = {}, extract_access_token = options[:extract_access_token]) # # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity Metrics/AbcSize, Metrics/MethodLength
156
+ params = params.map do |key, value|
157
+ if RESERVED_PARAM_KEYS.include?(key)
158
+ [key.to_sym, value]
159
+ else
160
+ [key, value]
161
+ end
162
+ end
163
+ params = Hash[params]
164
+
165
+ params = authenticator.apply(params)
137
166
  opts = {:raise_errors => options[:raise_errors], :parse => params.delete(:parse)}
138
167
  headers = params.delete(:headers) || {}
139
168
  if options[:token_method] == :post
@@ -143,39 +172,55 @@ module OAuth2
143
172
  opts[:params] = params
144
173
  opts[:headers] = {}
145
174
  end
146
- opts[:headers].merge!(headers)
147
- response = request(options[:token_method], token_url, opts)
148
- if options[:raise_errors] && !(response.parsed.is_a?(Hash) && response.parsed['access_token'])
175
+ opts[:headers] = opts[:headers].merge(headers)
176
+ http_method = options[:token_method]
177
+ response = request(http_method, token_url, opts)
178
+
179
+ access_token = begin
180
+ build_access_token(response, access_token_opts, extract_access_token)
181
+ rescue StandardError
182
+ nil
183
+ end
184
+
185
+ response_contains_token = access_token || (
186
+ response.parsed.is_a?(Hash) &&
187
+ (response.parsed['access_token'] || response.parsed['id_token'])
188
+ )
189
+
190
+ if options[:raise_errors] && !response_contains_token
149
191
  error = Error.new(response)
150
192
  raise(error)
193
+ elsif !response_contains_token
194
+ return nil
151
195
  end
152
- access_token_class.from_hash(self, response.parsed.merge(access_token_opts))
196
+
197
+ access_token
153
198
  end
154
199
 
155
200
  # The Authorization Code strategy
156
201
  #
157
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.1
202
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.1
158
203
  def auth_code
159
204
  @auth_code ||= OAuth2::Strategy::AuthCode.new(self)
160
205
  end
161
206
 
162
207
  # The Implicit strategy
163
208
  #
164
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2
209
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2
165
210
  def implicit
166
211
  @implicit ||= OAuth2::Strategy::Implicit.new(self)
167
212
  end
168
213
 
169
214
  # The Resource Owner Password Credentials strategy
170
215
  #
171
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.3
216
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.3
172
217
  def password
173
218
  @password ||= OAuth2::Strategy::Password.new(self)
174
219
  end
175
220
 
176
221
  # The Client Credentials strategy
177
222
  #
178
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
223
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.4
179
224
  def client_credentials
180
225
  @client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self)
181
226
  end
@@ -195,10 +240,10 @@ module OAuth2
195
240
  #
196
241
  # @api semipublic
197
242
  #
198
- # @see https://tools.ietf.org/html/rfc6749#section-4.1
199
- # @see https://tools.ietf.org/html/rfc6749#section-4.1.3
200
- # @see https://tools.ietf.org/html/rfc6749#section-4.2.1
201
- # @see https://tools.ietf.org/html/rfc6749#section-10.6
243
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1
244
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
245
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.1
246
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-10.6
202
247
  # @return [Hash] the params to add to a request or URL
203
248
  def redirection_params
204
249
  if options[:redirect_uri]
@@ -207,5 +252,41 @@ module OAuth2
207
252
  {}
208
253
  end
209
254
  end
255
+
256
+ DEFAULT_EXTRACT_ACCESS_TOKEN = proc do |client, hash|
257
+ token = hash.delete('access_token') || hash.delete(:access_token)
258
+ token && AccessToken.new(client, token, hash)
259
+ end
260
+
261
+ private
262
+
263
+ # Returns the authenticator object
264
+ #
265
+ # @return [Authenticator] the initialized Authenticator
266
+ def authenticator
267
+ Authenticator.new(id, secret, options[:auth_scheme])
268
+ end
269
+
270
+ # Builds the access token from the response of the HTTP call
271
+ #
272
+ # @return [AccessToken] the initialized AccessToken
273
+ def build_access_token(response, access_token_opts, extract_access_token)
274
+ parsed_response = response.parsed.dup
275
+ return unless parsed_response.is_a?(Hash)
276
+
277
+ hash = parsed_response.merge(access_token_opts)
278
+
279
+ # Provide backwards compatibility for old AccessToken.form_hash pattern
280
+ # Will be deprecated in 2.x
281
+ if extract_access_token.is_a?(Class) && extract_access_token.respond_to?(:from_hash)
282
+ extract_access_token.from_hash(self, hash)
283
+ else
284
+ extract_access_token.call(self, hash)
285
+ end
286
+ end
287
+
288
+ def oauth_debug_logging(builder)
289
+ builder.response :logger, options[:logger], :bodies => true if ENV['OAUTH_DEBUG'] == 'true'
290
+ end
210
291
  end
211
292
  end
data/lib/oauth2/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  class Error < StandardError
3
5
  attr_reader :response, :code, :description
@@ -23,7 +25,7 @@ module OAuth2
23
25
  def error_message(response_body, opts = {})
24
26
  message = []
25
27
 
26
- opts[:error_description] && message << opts[:error_description]
28
+ opts[:error_description] && (message << opts[:error_description])
27
29
 
28
30
  error_message = if opts[:error_description] && opts[:error_description].respond_to?(:encoding)
29
31
  script_encoding = opts[:error_description].encoding
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  require 'digest'
3
5
  require 'openssl'
@@ -60,7 +62,7 @@ module OAuth2
60
62
  # @param [String] url the HTTP URL path of the request
61
63
  def header(verb, url)
62
64
  timestamp = Time.now.utc.to_i
63
- nonce = Digest::MD5.hexdigest([timestamp, SecureRandom.hex].join(':'))
65
+ nonce = Digest::SHA256.hexdigest([timestamp, SecureRandom.hex].join(':'))
64
66
 
65
67
  uri = URI.parse(url)
66
68
 
@@ -95,16 +97,22 @@ module OAuth2
95
97
  #
96
98
  # @param [String] alg the algorithm to use (one of 'hmac-sha-1', 'hmac-sha-256')
97
99
  def algorithm=(alg)
98
- @algorithm = begin
99
- case alg.to_s
100
- when 'hmac-sha-1'
101
- OpenSSL::Digest::SHA1.new
102
- when 'hmac-sha-256'
103
- OpenSSL::Digest::SHA256.new
104
- else
105
- raise(ArgumentError, 'Unsupported algorithm')
106
- end
107
- end
100
+ @algorithm = case alg.to_s
101
+ when 'hmac-sha-1'
102
+ begin
103
+ OpenSSL::Digest('SHA1').new
104
+ rescue StandardError
105
+ OpenSSL::Digest.new('SHA1')
106
+ end
107
+ when 'hmac-sha-256'
108
+ begin
109
+ OpenSSL::Digest('SHA256').new
110
+ rescue StandardError
111
+ OpenSSL::Digest.new('SHA256')
112
+ end
113
+ else
114
+ raise(ArgumentError, 'Unsupported algorithm')
115
+ end
108
116
  end
109
117
 
110
118
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'multi_json'
2
4
  require 'multi_xml'
3
5
  require 'rack'
@@ -11,9 +13,9 @@ module OAuth2
11
13
  # Procs that, when called, will parse a response body according
12
14
  # to the specified format.
13
15
  @@parsers = {
14
- :json => lambda { |body| MultiJson.load(body) rescue body }, # rubocop:disable RescueModifier
16
+ :json => lambda { |body| MultiJson.load(body) rescue body }, # rubocop:disable Style/RescueModifier
15
17
  :query => lambda { |body| Rack::Utils.parse_query(body) },
16
- :text => lambda { |body| body },
18
+ :text => lambda { |body| body },
17
19
  }
18
20
 
19
21
  # Content type assignments for various potential HTTP content types.
@@ -68,6 +70,7 @@ module OAuth2
68
70
  # application/json Content-Type response bodies
69
71
  def parsed
70
72
  return nil unless @@parsers.key?(parser)
73
+
71
74
  @parsed ||= @@parsers[parser].call(body)
72
75
  end
73
76
 
@@ -79,11 +82,12 @@ module OAuth2
79
82
  # Determines the parser that will be used to supply the content of #parsed
80
83
  def parser
81
84
  return options[:parse].to_sym if @@parsers.key?(options[:parse])
85
+
82
86
  @@content_types[content_type]
83
87
  end
84
88
  end
85
89
  end
86
90
 
87
91
  OAuth2::Response.register_parser(:xml, ['text/xml', 'application/rss+xml', 'application/rdf+xml', 'application/atom+xml']) do |body|
88
- MultiXml.parse(body) rescue body # rubocop:disable RescueModifier
92
+ MultiXml.parse(body) rescue body # rubocop:disable Style/RescueModifier
89
93
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jwt'
2
4
 
3
5
  module OAuth2
4
6
  module Strategy
5
7
  # The Client Assertion Strategy
6
8
  #
7
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.3
9
+ # @see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-10#section-4.1.3
8
10
  #
9
11
  # Sample usage:
10
12
  # client = OAuth2::Client.new(client_id, client_secret,
@@ -50,10 +52,10 @@ module OAuth2
50
52
  def build_request(params)
51
53
  assertion = build_assertion(params)
52
54
  {
53
- :grant_type => 'assertion',
55
+ :grant_type => 'assertion',
54
56
  :assertion_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
55
- :assertion => assertion,
56
- :scope => params[:scope],
57
+ :assertion => assertion,
58
+ :scope => params[:scope],
57
59
  }
58
60
  end
59
61
 
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Authorization Code Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.1
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.1
6
8
  class AuthCode < Base
7
9
  # The required query parameters for the authorize URL
8
10
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  class Base
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Client Credentials Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.4
6
8
  class ClientCredentials < Base
7
9
  # Not used for this strategy
8
10
  #
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Implicit Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2
6
8
  class Implicit < Base
7
9
  # The required query parameters for the authorize URL
8
10
  #
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Strategy
3
5
  # The Resource Owner Password Credentials Authorization Strategy
4
6
  #
5
- # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.3
7
+ # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.3
6
8
  class Password < Base
7
9
  # Not used for this strategy
8
10
  #
@@ -18,8 +20,8 @@ module OAuth2
18
20
  # @param [Hash] params additional params
19
21
  def get_token(username, password, params = {}, opts = {})
20
22
  params = {'grant_type' => 'password',
21
- 'username' => username,
22
- 'password' => password}.merge(params)
23
+ 'username' => username,
24
+ 'password' => password}.merge(params)
23
25
  @client.get_token(params, opts)
24
26
  end
25
27
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
4
  module Version
5
+ VERSION = to_s
6
+
3
7
  module_function
4
8
 
5
9
  # The major version
@@ -20,12 +24,12 @@ module OAuth2
20
24
  #
21
25
  # @return [Integer]
22
26
  def patch
23
- 4
27
+ 11
24
28
  end
25
29
 
26
30
  # The pre-release version, if any
27
31
  #
28
- # @return [Integer, NilClass]
32
+ # @return [String, NilClass]
29
33
  def pre
30
34
  nil
31
35
  end
@@ -53,7 +57,9 @@ module OAuth2
53
57
  #
54
58
  # @return [String]
55
59
  def to_s
56
- to_a.join('.')
60
+ v = [major, minor, patch].compact.join('.')
61
+ v += "-#{pre}" if pre
62
+ v
57
63
  end
58
64
  end
59
65
  end
data/lib/oauth2.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'oauth2/error'
2
4
  require 'oauth2/authenticator'
3
5
  require 'oauth2/client'