oauth2 1.2.0 → 1.3.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
2
  SHA1:
3
- metadata.gz: 64323d2b66a74a3aba80fa955d23d280e64ede95
4
- data.tar.gz: b5d9c12d616a0ccd67d15eed3b887cd6b1e174ec
3
+ metadata.gz: 0de0695b29bf1d20066a08a8536d70a9bea3e827
4
+ data.tar.gz: 184943366118bf412220fbde4ac0d1becdfa2055
5
5
  SHA512:
6
- metadata.gz: d0c36b6f6f2a2b8db5d8aae0f7897ffa6de5321ee06064f757f523ca144a119befde42d13943f4507848999adc0f68b011534ddd64258210dbabbcfa6c83e34b
7
- data.tar.gz: 8aef0531493683b4b9fc390a545e297e1107611d76363486acc473925264337438992b3f7b288a546e17685a7d198e306fc8b2d4f3dc153c1acd1f20f7e6cca7
6
+ metadata.gz: 8fe7c101b47debe6489b4bad62211d774079f599749fcc7e36fddd076f305db8ae3baab500877656a5a698b1484da1467d3a9b60fff07b9520d9cc314e542f8b
7
+ data.tar.gz: da02d83327a1c147bd6cf28cc416bcb4c82168c723f17871fcc1a3b16cb42e35726672055a2829234d6e8b565e1d576fc339b747467f38f728e9559cb087b3cc
@@ -1,4 +1,5 @@
1
1
  require 'oauth2/error'
2
+ require 'oauth2/authenticator'
2
3
  require 'oauth2/client'
3
4
  require 'oauth2/strategy/base'
4
5
  require 'oauth2/strategy/auth_code'
@@ -81,8 +81,6 @@ module OAuth2
81
81
  # @note options should be carried over to the new AccessToken
82
82
  def refresh!(params = {})
83
83
  raise('A refresh_token is not available') unless refresh_token
84
- params[:client_id] = @client.id
85
- params[:client_secret] = @client.secret
86
84
  params[:grant_type] = 'refresh_token'
87
85
  params[:refresh_token] = refresh_token
88
86
  new_token = @client.get_token(params)
@@ -105,7 +103,7 @@ module OAuth2
105
103
  # @param [Hash] opts the options to make the request with
106
104
  # @see Client#request
107
105
  def request(verb, path, opts = {}, &block)
108
- self.token = opts
106
+ configure_authentication!(opts)
109
107
  @client.request(verb, path, opts, &block)
110
108
  end
111
109
 
@@ -151,7 +149,7 @@ module OAuth2
151
149
 
152
150
  private
153
151
 
154
- def token=(opts) # rubocop:disable MethodLength, Metrics/AbcSize
152
+ def configure_authentication!(opts) # rubocop:disable MethodLength, Metrics/AbcSize
155
153
  case options[:mode]
156
154
  when :header
157
155
  opts[:headers] ||= {}
@@ -0,0 +1,58 @@
1
+ require 'base64'
2
+
3
+ module OAuth2
4
+ class Authenticator
5
+ attr_reader :mode, :id, :secret
6
+
7
+ def initialize(id, secret, mode)
8
+ @id = id
9
+ @secret = secret
10
+ @mode = mode
11
+ end
12
+
13
+ # Apply the request credentials used to authenticate to the Authorization Server
14
+ #
15
+ # Depending on configuration, this might be as request params or as an
16
+ # Authorization header.
17
+ #
18
+ # User-provided params and header take precedence.
19
+ #
20
+ # @param [Hash] params a Hash of params for the token endpoint
21
+ # @return [Hash] params amended with appropriate authentication details
22
+ def apply(params)
23
+ case mode.to_sym
24
+ when :basic_auth
25
+ apply_basic_auth(params)
26
+ when :request_body
27
+ apply_params_auth(params)
28
+ else
29
+ raise NotImplementedError
30
+ end
31
+ end
32
+
33
+ def self.encode_basic_auth(user, password)
34
+ 'Basic ' + Base64.encode64(user + ':' + password).delete("\n")
35
+ end
36
+
37
+ private
38
+
39
+ # Adds client_id and client_secret request parameters if they are not
40
+ # already set.
41
+ def apply_params_auth(params)
42
+ {'client_id' => id, 'client_secret' => secret}.merge(params)
43
+ end
44
+
45
+ # Adds an `Authorization` header with Basic Auth credentials if and only if
46
+ # it is not already set in the params.
47
+ def apply_basic_auth(params)
48
+ headers = params.fetch(:headers, {})
49
+ headers = basic_auth_header.merge(headers)
50
+ params.merge(:headers => headers)
51
+ end
52
+
53
+ # @see https://tools.ietf.org/html/rfc2617#section-2
54
+ def basic_auth_header
55
+ {'Authorization' => self.class.encode_basic_auth(id, secret)}
56
+ end
57
+ end
58
+ end
@@ -3,7 +3,7 @@ require 'logger'
3
3
 
4
4
  module OAuth2
5
5
  # The OAuth2::Client class
6
- class Client
6
+ class Client # rubocop:disable Metrics/ClassLength
7
7
  attr_reader :id, :secret, :site
8
8
  attr_accessor :options
9
9
  attr_writer :connection
@@ -16,9 +16,11 @@ module OAuth2
16
16
  # @param [String] client_secret the client_secret value
17
17
  # @param [Hash] opts the options to create the client with
18
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
19
20
  # @option opts [String] :authorize_url ('/oauth/authorize') absolute or relative URL path to the Authorization endpoint
20
21
  # @option opts [String] :token_url ('/oauth/token') absolute or relative URL path to the Token endpoint
21
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)
22
24
  # @option opts [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday with
23
25
  # @option opts [FixNum] :max_redirects (5) maximum number of redirects to follow
24
26
  # @option opts [Boolean] :raise_errors (true) whether or not to raise an OAuth2::Error
@@ -33,6 +35,7 @@ module OAuth2
33
35
  @options = {:authorize_url => '/oauth/authorize',
34
36
  :token_url => '/oauth/token',
35
37
  :token_method => :post,
38
+ :auth_scheme => :request_body,
36
39
  :connection_opts => {},
37
40
  :connection_build => block,
38
41
  :max_redirects => 5,
@@ -52,9 +55,11 @@ module OAuth2
52
55
  def connection
53
56
  @connection ||= begin
54
57
  conn = Faraday.new(site, options[:connection_opts])
55
- conn.build do |b|
56
- options[:connection_build].call(b)
57
- end if options[:connection_build]
58
+ if options[:connection_build]
59
+ conn.build do |b|
60
+ options[:connection_build].call(b)
61
+ end
62
+ end
58
63
  conn
59
64
  end
60
65
  end
@@ -62,7 +67,8 @@ module OAuth2
62
67
  # The authorize endpoint URL of the OAuth2 provider
63
68
  #
64
69
  # @param [Hash] params additional query parameters
65
- def authorize_url(params = nil)
70
+ def authorize_url(params = {})
71
+ params = (params || {}).merge(redirection_params)
66
72
  connection.build_url(options[:authorize_url], params).to_s
67
73
  end
68
74
 
@@ -125,19 +131,23 @@ module OAuth2
125
131
  # @param [Hash] access token options, to pass to the AccessToken object
126
132
  # @param [Class] class of access token for easier subclassing OAuth2::AccessToken
127
133
  # @return [AccessToken] the initalized AccessToken
128
- def get_token(params, access_token_opts = {}, access_token_class = AccessToken) # rubocop:disable Metrics/AbcSize
134
+ def get_token(params, access_token_opts = {}, access_token_class = AccessToken) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
135
+ params = Authenticator.new(id, secret, options[:auth_scheme]).apply(params)
129
136
  opts = {:raise_errors => options[:raise_errors], :parse => params.delete(:parse)}
137
+ headers = params.delete(:headers) || {}
130
138
  if options[:token_method] == :post
131
- headers = params.delete(:headers)
132
139
  opts[:body] = params
133
140
  opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
134
- opts[:headers].merge!(headers) if headers
135
141
  else
136
142
  opts[:params] = params
143
+ opts[:headers] = {}
137
144
  end
145
+ opts[:headers].merge!(headers)
138
146
  response = request(options[:token_method], token_url, opts)
139
- error = Error.new(response)
140
- raise(error) if options[:raise_errors] && !(response.parsed.is_a?(Hash) && response.parsed['access_token'])
147
+ if options[:raise_errors] && !(response.parsed.is_a?(Hash) && response.parsed['access_token'])
148
+ error = Error.new(response)
149
+ raise(error)
150
+ end
141
151
  access_token_class.from_hash(self, response.parsed.merge(access_token_opts))
142
152
  end
143
153
 
@@ -172,5 +182,29 @@ module OAuth2
172
182
  def assertion
173
183
  @assertion ||= OAuth2::Strategy::Assertion.new(self)
174
184
  end
185
+
186
+ # The redirect_uri parameters, if configured
187
+ #
188
+ # The redirect_uri query parameter is OPTIONAL (though encouraged) when
189
+ # requesting authorization. If it is provided at authorization time it MUST
190
+ # also be provided with the token exchange request.
191
+ #
192
+ # Providing the :redirect_uri to the OAuth2::Client instantiation will take
193
+ # care of managing this.
194
+ #
195
+ # @api semipublic
196
+ #
197
+ # @see https://tools.ietf.org/html/rfc6749#section-4.1
198
+ # @see https://tools.ietf.org/html/rfc6749#section-4.1.3
199
+ # @see https://tools.ietf.org/html/rfc6749#section-4.2.1
200
+ # @see https://tools.ietf.org/html/rfc6749#section-10.6
201
+ # @return [Hash] the params to add to a request or URL
202
+ def redirection_params
203
+ if options[:redirect_uri]
204
+ {'redirect_uri' => options[:redirect_uri]}
205
+ else
206
+ {}
207
+ end
208
+ end
175
209
  end
176
210
  end
@@ -27,7 +27,7 @@ module OAuth2
27
27
 
28
28
  error_message = if opts[:error_description] && opts[:error_description].respond_to?(:encoding)
29
29
  script_encoding = opts[:error_description].encoding
30
- response_body.encode(script_encoding)
30
+ response_body.encode(script_encoding, :invalid => :replace, :undef => :replace)
31
31
  else
32
32
  response_body
33
33
  end
@@ -27,7 +27,7 @@ module OAuth2
27
27
  # Adds a new content type parser.
28
28
  #
29
29
  # @param [Symbol] key A descriptive symbol key such as :json or :query.
30
- # @param [Array] One or more mime types to which this parser applies.
30
+ # @param [Array] mime_types One or more mime types to which this parser applies.
31
31
  # @yield [String] A block returning parsed content.
32
32
  def self.register_parser(key, mime_types, &block)
33
33
  key = key.to_sym
@@ -54,7 +54,7 @@ module OAuth2
54
54
  :assertion_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
55
55
  :assertion => assertion,
56
56
  :scope => params[:scope],
57
- }.merge(client_params)
57
+ }
58
58
  end
59
59
 
60
60
  def build_assertion(params)
@@ -25,7 +25,8 @@ module OAuth2
25
25
  # @param [Hash] opts options
26
26
  # @note that you must also provide a :redirect_uri with most OAuth 2.0 providers
27
27
  def get_token(code, params = {}, opts = {})
28
- params = {'grant_type' => 'authorization_code', 'code' => code}.merge(client_params).merge(params)
28
+ params = {'grant_type' => 'authorization_code', 'code' => code}.merge(@client.redirection_params).merge(params)
29
+
29
30
  @client.get_token(params, opts)
30
31
  end
31
32
  end
@@ -4,13 +4,6 @@ module OAuth2
4
4
  def initialize(client)
5
5
  @client = client
6
6
  end
7
-
8
- # The OAuth client_id and client_secret
9
- #
10
- # @return [Hash]
11
- def client_params
12
- {'client_id' => @client.id, 'client_secret' => @client.secret}
13
- end
14
7
  end
15
8
  end
16
9
  end
@@ -1,5 +1,3 @@
1
- require 'base64'
2
-
3
1
  module OAuth2
4
2
  module Strategy
5
3
  # The Client Credentials Strategy
@@ -18,19 +16,9 @@ module OAuth2
18
16
  # @param [Hash] params additional params
19
17
  # @param [Hash] opts options
20
18
  def get_token(params = {}, opts = {})
21
- request_body = opts.delete('auth_scheme') == 'request_body'
22
- params['grant_type'] = 'client_credentials'
23
- params.merge!(request_body ? client_params : {:headers => {'Authorization' => authorization(client_params['client_id'], client_params['client_secret'])}})
19
+ params = params.merge('grant_type' => 'client_credentials')
24
20
  @client.get_token(params, opts.merge('refresh_token' => nil))
25
21
  end
26
-
27
- # Returns the Authorization header value for Basic Authentication
28
- #
29
- # @param [String] The client ID
30
- # @param [String] the client secret
31
- def authorization(client_id, client_secret)
32
- 'Basic ' + Base64.encode64(client_id + ':' + client_secret).delete("\n")
33
- end
34
22
  end
35
23
  end
36
24
  end
@@ -19,7 +19,7 @@ module OAuth2
19
19
  def get_token(username, password, params = {}, opts = {})
20
20
  params = {'grant_type' => 'password',
21
21
  'username' => username,
22
- 'password' => password}.merge(client_params).merge(params)
22
+ 'password' => password}.merge(params)
23
23
  @client.get_token(params, opts)
24
24
  end
25
25
  end
@@ -13,7 +13,7 @@ module OAuth2
13
13
  #
14
14
  # @return [Integer]
15
15
  def minor
16
- 2
16
+ 3
17
17
  end
18
18
 
19
19
  # The patch version
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'oauth2/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.add_dependency 'faraday', ['>= 0.8', '< 0.10']
7
+ spec.add_dependency 'faraday', ['>= 0.8', '< 0.11']
8
8
  spec.add_dependency 'jwt', '~> 1.0'
9
9
  spec.add_dependency 'multi_json', '~> 1.3'
10
10
  spec.add_dependency 'multi_xml', '~> 0.5'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-07-01 00:00:00.000000000 Z
12
+ date: 2016-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -20,7 +20,7 @@ dependencies:
20
20
  version: '0.8'
21
21
  - - "<"
22
22
  - !ruby/object:Gem::Version
23
- version: '0.10'
23
+ version: '0.11'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -30,7 +30,7 @@ dependencies:
30
30
  version: '0.8'
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.10'
33
+ version: '0.11'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: jwt
36
36
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +122,7 @@ files:
122
122
  - README.md
123
123
  - lib/oauth2.rb
124
124
  - lib/oauth2/access_token.rb
125
+ - lib/oauth2/authenticator.rb
125
126
  - lib/oauth2/client.rb
126
127
  - lib/oauth2/error.rb
127
128
  - lib/oauth2/mac_token.rb
@@ -154,9 +155,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
155
  version: 1.3.5
155
156
  requirements: []
156
157
  rubyforge_project:
157
- rubygems_version: 2.2.5
158
+ rubygems_version: 2.5.2
158
159
  signing_key:
159
160
  specification_version: 4
160
161
  summary: A Ruby wrapper for the OAuth 2.0 protocol.
161
162
  test_files: []
162
- has_rdoc: