signet 0.11.0 → 0.14.1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -15
  3. data/Gemfile +5 -4
  4. data/README.md +4 -6
  5. data/Rakefile +107 -37
  6. data/lib/signet.rb +17 -14
  7. data/lib/signet/errors.rb +4 -4
  8. data/lib/signet/oauth_1.rb +129 -154
  9. data/lib/signet/oauth_1/client.rb +309 -343
  10. data/lib/signet/oauth_1/credential.rb +40 -37
  11. data/lib/signet/oauth_1/server.rb +197 -203
  12. data/lib/signet/oauth_1/signature_methods/hmac_sha1.rb +11 -10
  13. data/lib/signet/oauth_1/signature_methods/plaintext.rb +8 -7
  14. data/lib/signet/oauth_1/signature_methods/rsa_sha1.rb +11 -11
  15. data/lib/signet/oauth_2.rb +41 -43
  16. data/lib/signet/oauth_2/client.rb +328 -313
  17. data/lib/signet/version.rb +2 -73
  18. data/signet.gemspec +37 -39
  19. data/spec/signet/oauth_1/client_spec.rb +313 -315
  20. data/spec/signet/oauth_1/credential_spec.rb +64 -56
  21. data/spec/signet/oauth_1/server_spec.rb +362 -362
  22. data/spec/signet/oauth_1/signature_methods/hmac_sha1_spec.rb +26 -26
  23. data/spec/signet/oauth_1/signature_methods/plaintext_spec.rb +28 -28
  24. data/spec/signet/oauth_1/signature_methods/rsa_sha1_spec.rb +34 -35
  25. data/spec/signet/oauth_1_spec.rb +553 -524
  26. data/spec/signet/oauth_2/client_spec.rb +652 -576
  27. data/spec/signet/oauth_2_spec.rb +88 -89
  28. data/spec/signet_spec.rb +41 -41
  29. data/spec/spec_helper.rb +7 -7
  30. data/spec/spec_helper_spec.rb +8 -8
  31. metadata +64 -52
  32. data/tasks/clobber.rake +0 -2
  33. data/tasks/gem.rake +0 -34
  34. data/tasks/git.rake +0 -40
  35. data/tasks/metrics.rake +0 -41
  36. data/tasks/spec.rake +0 -34
  37. data/tasks/wiki.rake +0 -38
  38. data/tasks/yard.rake +0 -21
@@ -1,23 +1,24 @@
1
- require 'openssl'
2
- require 'signet'
1
+ require "openssl"
2
+ require "signet"
3
3
 
4
4
  module Signet #:nodoc:
5
5
  module OAuth1
6
6
  module HMACSHA1
7
- def self.generate_signature(
8
- base_string, client_credential_secret, token_credential_secret)
7
+ def self.generate_signature \
8
+ base_string, client_credential_secret, token_credential_secret
9
+
9
10
  # Both the client secret and token secret must be escaped
10
11
  client_credential_secret =
11
- Signet::OAuth1.encode(client_credential_secret)
12
+ Signet::OAuth1.encode client_credential_secret
12
13
  token_credential_secret =
13
- Signet::OAuth1.encode(token_credential_secret)
14
+ Signet::OAuth1.encode token_credential_secret
14
15
  # The key for the signature is just the client secret and token
15
16
  # secret joined by the '&' character. If the token secret is omitted,
16
17
  # the '&' must still be present.
17
- key = [client_credential_secret, token_credential_secret].join("&")
18
- return Base64.encode64(OpenSSL::HMAC.digest(
19
- OpenSSL::Digest.new('sha1'), key, base_string
20
- )).strip
18
+ key = [client_credential_secret, token_credential_secret].join "&"
19
+ Base64.encode64(OpenSSL::HMAC.digest(
20
+ OpenSSL::Digest.new("sha1"), key, base_string
21
+ )).strip
21
22
  end
22
23
  end
23
24
  end
@@ -1,20 +1,21 @@
1
- require 'signet'
1
+ require "signet"
2
2
 
3
3
  module Signet #:nodoc:
4
4
  module OAuth1
5
5
  module PLAINTEXT
6
- def self.generate_signature(
7
- base_string, client_credential_secret, token_credential_secret)
6
+ def self.generate_signature \
7
+ _base_string, client_credential_secret, token_credential_secret
8
+
8
9
  # Both the client secret and token secret must be escaped
9
10
  client_credential_secret =
10
- Signet::OAuth1.encode(client_credential_secret)
11
+ Signet::OAuth1.encode client_credential_secret
11
12
  token_credential_secret =
12
- Signet::OAuth1.encode(token_credential_secret)
13
+ Signet::OAuth1.encode token_credential_secret
13
14
  # The key for the signature is just the client secret and token
14
15
  # secret joined by the '&' character. If the token secret is omitted,
15
16
  # the '&' must still be present.
16
- key = [client_credential_secret, token_credential_secret].join("&")
17
- return Signet::OAuth1.encode(key).strip
17
+ key = [client_credential_secret, token_credential_secret].join "&"
18
+ Signet::OAuth1.encode(key).strip
18
19
  end
19
20
  end
20
21
  end
@@ -1,20 +1,20 @@
1
- require 'digest/sha1'
2
- require 'base64'
3
- require 'openssl'
4
- require 'signet'
1
+ require "digest/sha1"
2
+ require "base64"
3
+ require "openssl"
4
+ require "signet"
5
5
 
6
6
  module Signet #:nodoc:
7
7
  module OAuth1
8
8
  module RSASHA1
9
- def self.generate_signature(
10
- base_string, client_credential_secret, token_credential_secret)
9
+ def self.generate_signature \
10
+ base_string, client_credential_secret, _token_credential_secret
11
11
 
12
- private_key = OpenSSL::PKey::RSA.new(client_credential_secret)
13
- signature = private_key.sign(OpenSSL::Digest::SHA1.new, base_string)
14
- #using strict_encode64 because the encode64 method adds newline characters after ever 60 chars
15
- return Base64.strict_encode64(signature).strip
16
- end
17
12
 
13
+ private_key = OpenSSL::PKey::RSA.new client_credential_secret
14
+ signature = private_key.sign OpenSSL::Digest::SHA1.new, base_string
15
+ # using strict_encode64 because the encode64 method adds newline characters after ever 60 chars
16
+ Base64.strict_encode64(signature).strip
17
+ end
18
18
  end
19
19
  end
20
20
  end
@@ -12,9 +12,9 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'base64'
16
- require 'signet'
17
- require 'multi_json'
15
+ require "base64"
16
+ require "signet"
17
+ require "multi_json"
18
18
 
19
19
  module Signet #:nodoc:
20
20
  ##
@@ -23,63 +23,61 @@ module Signet #:nodoc:
23
23
  # This module will be updated periodically to support newer drafts of the
24
24
  # specification, as they become widely deployed.
25
25
  module OAuth2
26
- def self.parse_authorization_header(field_value)
26
+ def self.parse_authorization_header field_value
27
27
  auth_scheme = field_value[/^([-._0-9a-zA-Z]+)/, 1]
28
28
  case auth_scheme
29
29
  when /^Basic$/i
30
30
  # HTTP Basic is allowed in OAuth 2
31
- return self.parse_basic_credentials(field_value[/^Basic\s+(.*)$/i, 1])
31
+ return parse_basic_credentials(field_value[/^Basic\s+(.*)$/i, 1])
32
32
  when /^OAuth$/i
33
33
  # Other token types may be supported eventually
34
- return self.parse_bearer_credentials(field_value[/^OAuth\s+(.*)$/i, 1])
34
+ return parse_bearer_credentials(field_value[/^OAuth\s+(.*)$/i, 1])
35
35
  else
36
36
  raise ParseError,
37
- 'Parsing non-OAuth Authorization headers is out of scope.'
37
+ "Parsing non-OAuth Authorization headers is out of scope."
38
38
  end
39
39
  end
40
40
 
41
- def self.parse_www_authenticate_header(field_value)
41
+ def self.parse_www_authenticate_header field_value
42
42
  auth_scheme = field_value[/^([-._0-9a-zA-Z]+)/, 1]
43
43
  case auth_scheme
44
44
  when /^OAuth$/i
45
45
  # Other token types may be supported eventually
46
- return self.parse_oauth_challenge(field_value[/^OAuth\s+(.*)$/i, 1])
46
+ return parse_oauth_challenge(field_value[/^OAuth\s+(.*)$/i, 1])
47
47
  else
48
48
  raise ParseError,
49
- 'Parsing non-OAuth WWW-Authenticate headers is out of scope.'
49
+ "Parsing non-OAuth WWW-Authenticate headers is out of scope."
50
50
  end
51
51
  end
52
52
 
53
- def self.parse_basic_credentials(credential_string)
54
- decoded = Base64.decode64(credential_string)
55
- client_id, client_secret = decoded.split(':', 2)
56
- return [['client_id', client_id], ['client_secret', client_secret]]
53
+ def self.parse_basic_credentials credential_string
54
+ decoded = Base64.decode64 credential_string
55
+ client_id, client_secret = decoded.split ":", 2
56
+ [["client_id", client_id], ["client_secret", client_secret]]
57
57
  end
58
58
 
59
- def self.parse_bearer_credentials(credential_string)
59
+ def self.parse_bearer_credentials credential_string
60
60
  access_token = credential_string[/^([^,\s]+)(?:\s|,|$)/i, 1]
61
61
  parameters = []
62
- parameters << ['access_token', access_token]
62
+ parameters << ["access_token", access_token]
63
63
  auth_param_string = credential_string[/^(?:[^,\s]+)\s*,\s*(.*)$/i, 1]
64
64
  if auth_param_string
65
65
  # This code will rarely get called, but is included for completeness
66
- parameters.concat(Signet.parse_auth_param_list(auth_param_string))
66
+ parameters.concat Signet.parse_auth_param_list(auth_param_string)
67
67
  end
68
- return parameters
68
+ parameters
69
69
  end
70
70
 
71
- def self.parse_oauth_challenge(challenge_string)
72
- return Signet.parse_auth_param_list(challenge_string)
71
+ def self.parse_oauth_challenge challenge_string
72
+ Signet.parse_auth_param_list challenge_string
73
73
  end
74
74
 
75
- def self.parse_credentials(body, content_type)
76
- if !body.kind_of?(String)
77
- raise TypeError, "Expected String, got #{body.class}."
78
- end
75
+ def self.parse_credentials body, content_type
76
+ raise TypeError, "Expected String, got #{body.class}." unless body.is_a? String
79
77
  case content_type
80
- when /^application\/json.*/
81
- return MultiJson.load(body)
82
- when /^application\/x-www-form-urlencoded.*/
78
+ when %r{^application/json.*}
79
+ return MultiJson.load body
80
+ when %r{^application/x-www-form-urlencoded.*}
83
81
  return Hash[Addressable::URI.form_unencode(body)]
84
82
  else
85
83
  raise ArgumentError, "Invalid content type '#{content_type}'"
@@ -97,14 +95,14 @@ module Signet #:nodoc:
97
95
  #
98
96
  # @return [String]
99
97
  # The value for the HTTP Basic Authorization header.
100
- def self.generate_basic_authorization_header(client_id, client_password)
98
+ def self.generate_basic_authorization_header client_id, client_password
101
99
  if client_id =~ /:/
102
100
  raise ArgumentError,
103
- "A client identifier may not contain a ':' character."
101
+ "A client identifier may not contain a ':' character."
104
102
  end
105
- return 'Basic ' + Base64.encode64(
106
- client_id + ':' + client_password
107
- ).gsub(/\n/, '')
103
+ "Basic " + Base64.encode64(
104
+ client_id + ":" + client_password
105
+ ).delete("\n")
108
106
  end
109
107
 
110
108
  ##
@@ -117,19 +115,19 @@ module Signet #:nodoc:
117
115
  #
118
116
  # @return [String]
119
117
  # The value for the HTTP Basic Authorization header.
120
- def self.generate_bearer_authorization_header(
121
- access_token, auth_params=nil)
118
+ def self.generate_bearer_authorization_header \
119
+ access_token, auth_params = nil
120
+
122
121
  # TODO: escaping?
123
122
  header = "Bearer #{access_token}"
124
123
  if auth_params && !auth_params.empty?
125
124
  header += (", " +
126
- (auth_params.inject([]) do |accu, (key, value)|
125
+ (auth_params.each_with_object [] do |(key, value), accu|
127
126
  accu << "#{key}=\"#{value}\""
128
- accu
129
127
  end).join(", ")
130
- )
128
+ )
131
129
  end
132
- return header
130
+ header
133
131
  end
134
132
 
135
133
  ##
@@ -140,15 +138,15 @@ module Signet #:nodoc:
140
138
  # The base authorization endpoint URI.
141
139
  #
142
140
  # @return [String] The authorization URI to redirect the user to.
143
- def self.generate_authorization_uri(authorization_uri, parameters={})
144
- for key, value in parameters
145
- parameters.delete(key) if value.nil?
141
+ def self.generate_authorization_uri authorization_uri, parameters = {}
142
+ parameters.each do |key, value|
143
+ parameters.delete key if value.nil?
146
144
  end
147
145
  parsed_uri = Addressable::URI.parse(authorization_uri).dup
148
146
  query_values = parsed_uri.query_values || {}
149
- query_values = query_values.merge(parameters)
147
+ query_values = query_values.merge parameters
150
148
  parsed_uri.query_values = query_values
151
- return parsed_uri.normalize.to_s
149
+ parsed_uri.normalize.to_s
152
150
  end
153
151
  end
154
152
  end
@@ -12,20 +12,19 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'faraday'
16
- require 'stringio'
17
- require 'addressable/uri'
18
- require 'signet'
19
- require 'signet/errors'
20
- require 'signet/oauth_2'
21
- require 'jwt'
22
- require 'date'
15
+ require "faraday"
16
+ require "stringio"
17
+ require "addressable/uri"
18
+ require "signet"
19
+ require "signet/errors"
20
+ require "signet/oauth_2"
21
+ require "jwt"
22
+ require "date"
23
23
 
24
24
  module Signet
25
25
  module OAuth2
26
26
  class Client
27
-
28
- OOB_MODES = %w(urn:ietf:wg:oauth:2.0:oob:auto urn:ietf:wg:oauth:2.0:oob oob)
27
+ OOB_MODES = ["urn:ietf:wg:oauth:2.0:oob:auto", "urn:ietf:wg:oauth:2.0:oob", "oob"].freeze
29
28
 
30
29
  ##
31
30
  # Creates an OAuth 2.0 client.
@@ -47,6 +46,9 @@ module Signet
47
46
  # - <code>:scope</code> -
48
47
  # The scope of the access request, expressed either as an Array
49
48
  # or as a space-delimited String.
49
+ # - <code>:target_audience</code> -
50
+ # The final target audience for ID tokens fetched by this client,
51
+ # as a String.
50
52
  # - <code>:state</code> -
51
53
  # An arbitrary string designed to allow the client to maintain state.
52
54
  # - <code>:code</code> -
@@ -89,7 +91,7 @@ module Signet
89
91
  # )
90
92
  #
91
93
  # @see Signet::OAuth2::Client#update!
92
- def initialize options={}
94
+ def initialize options = {}
93
95
  @authorization_uri = nil
94
96
  @token_credential_uri = nil
95
97
  @client_id = nil
@@ -102,11 +104,15 @@ module Signet
102
104
  @principal = nil
103
105
  @redirect_uri = nil
104
106
  @scope = nil
107
+ @target_audience = nil
105
108
  @state = nil
106
109
  @username = nil
107
110
  @access_type = nil
108
- self.update!(options)
111
+ update! options
109
112
  end
113
+ # rubocop:disable Metrics/AbcSize
114
+ # rubocop:disable Metrics/CyclomaticComplexity
115
+ # rubocop:disable Metrics/PerceivedComplexity
110
116
 
111
117
  ##
112
118
  # Updates an OAuth 2.0 client.
@@ -128,6 +134,9 @@ module Signet
128
134
  # - <code>:scope</code> -
129
135
  # The scope of the access request, expressed either as an Array
130
136
  # or as a space-delimited String.
137
+ # - <code>:target_audience</code> -
138
+ # The final target audience for ID tokens fetched by this client,
139
+ # as a String.
131
140
  # - <code>:state</code> -
132
141
  # An arbitrary string designed to allow the client to maintain state.
133
142
  # - <code>:code</code> -
@@ -170,32 +179,36 @@ module Signet
170
179
  #
171
180
  # @see Signet::OAuth2::Client#initialize
172
181
  # @see Signet::OAuth2::Client#update_token!
173
- def update!(options={})
182
+ def update! options = {}
174
183
  # Normalize all keys to symbols to allow indifferent access.
175
- options = deep_hash_normalize(options)
176
-
177
- self.authorization_uri = options[:authorization_uri] if options.has_key?(:authorization_uri)
178
- self.token_credential_uri = options[:token_credential_uri] if options.has_key?(:token_credential_uri)
179
- self.client_id = options[:client_id] if options.has_key?(:client_id)
180
- self.client_secret = options[:client_secret] if options.has_key?(:client_secret)
181
- self.scope = options[:scope] if options.has_key?(:scope)
182
- self.state = options[:state] if options.has_key?(:state)
183
- self.code = options[:code] if options.has_key?(:code)
184
- self.redirect_uri = options[:redirect_uri] if options.has_key?(:redirect_uri)
185
- self.username = options[:username] if options.has_key?(:username)
186
- self.password = options[:password] if options.has_key?(:password)
187
- self.issuer = options[:issuer] if options.has_key?(:issuer)
188
- self.person = options[:person] if options.has_key?(:person)
189
- self.sub = options[:sub] if options.has_key?(:sub)
184
+ options = deep_hash_normalize options
185
+
186
+ self.authorization_uri = options[:authorization_uri] if options.key? :authorization_uri
187
+ self.token_credential_uri = options[:token_credential_uri] if options.key? :token_credential_uri
188
+ self.client_id = options[:client_id] if options.key? :client_id
189
+ self.client_secret = options[:client_secret] if options.key? :client_secret
190
+ self.scope = options[:scope] if options.key? :scope
191
+ self.target_audience = options[:target_audience] if options.key? :target_audience
192
+ self.state = options[:state] if options.key? :state
193
+ self.code = options[:code] if options.key? :code
194
+ self.redirect_uri = options[:redirect_uri] if options.key? :redirect_uri
195
+ self.username = options[:username] if options.key? :username
196
+ self.password = options[:password] if options.key? :password
197
+ self.issuer = options[:issuer] if options.key? :issuer
198
+ self.person = options[:person] if options.key? :person
199
+ self.sub = options[:sub] if options.key? :sub
190
200
  self.expiry = options[:expiry] || 60
191
- self.audience = options[:audience] if options.has_key?(:audience)
192
- self.signing_key = options[:signing_key] if options.has_key?(:signing_key)
201
+ self.audience = options[:audience] if options.key? :audience
202
+ self.signing_key = options[:signing_key] if options.key? :signing_key
193
203
  self.extension_parameters = options[:extension_parameters] || {}
194
204
  self.additional_parameters = options[:additional_parameters] || {}
195
205
  self.access_type = options.fetch(:access_type) { :offline }
196
- self.update_token!(options)
197
- return self
206
+ update_token! options
207
+ self
198
208
  end
209
+ # rubocop:enable Metrics/AbcSize
210
+ # rubocop:enable Metrics/CyclomaticComplexity
211
+ # rubocop:enable Metrics/PerceivedComplexity
199
212
 
200
213
  ##
201
214
  # Updates an OAuth 2.0 client.
@@ -225,29 +238,33 @@ module Signet
225
238
  #
226
239
  # @see Signet::OAuth2::Client#initialize
227
240
  # @see Signet::OAuth2::Client#update!
228
- def update_token!(options={})
241
+ def update_token! options = {}
229
242
  # Normalize all keys to symbols to allow indifferent access internally
230
- options = deep_hash_normalize(options)
243
+ options = deep_hash_normalize options
231
244
 
232
- self.expires_in = options[:expires] if options.has_key?(:expires)
233
- self.expires_in = options[:expires_in] if options.has_key?(:expires_in)
234
- self.expires_at = options[:expires_at] if options.has_key?(:expires_at)
245
+ self.expires_in = options[:expires] if options.key? :expires
246
+ self.expires_in = options[:expires_in] if options.key? :expires_in
247
+ self.expires_at = options[:expires_at] if options.key? :expires_at
235
248
 
236
249
  # By default, the token is issued at `Time.now` when `expires_in` is
237
250
  # set, but this can be used to supply a more precise time.
238
- self.issued_at = options[:issued_at] if options.has_key?(:issued_at)
251
+ self.issued_at = options[:issued_at] if options.key? :issued_at
239
252
 
240
253
  # Special case where we want expires_at to be relative to issued_at
241
- if options.has_key?(:issued_at) && options.has_key?(:expires_in)
254
+ if options.key?(:issued_at) && options.key?(:expires_in)
242
255
  set_relative_expires_at options[:issued_at], options[:expires_in]
243
256
  end
244
257
 
245
- self.access_token = options[:access_token] if options.has_key?(:access_token)
246
- self.refresh_token = options[:refresh_token] if options.has_key?(:refresh_token)
247
- self.id_token = options[:id_token] if options.has_key?(:id_token)
258
+ self.access_token = options[:access_token] if options.key? :access_token
259
+ self.refresh_token = options[:refresh_token] if options.key? :refresh_token
260
+ self.id_token = options[:id_token] if options.key? :id_token
248
261
 
249
- return self
262
+ self
250
263
  end
264
+ # rubocop:disable Metrics/AbcSize
265
+ # rubocop:disable Metrics/CyclomaticComplexity
266
+ # rubocop:disable Metrics/MethodLength
267
+ # rubocop:disable Metrics/PerceivedComplexity
251
268
 
252
269
  ##
253
270
  # Returns the authorization URI that the user should be redirected to.
@@ -255,34 +272,24 @@ module Signet
255
272
  # @return [Addressable::URI] The authorization URI.
256
273
  #
257
274
  # @see Signet::OAuth2.generate_authorization_uri
258
- def authorization_uri(options={})
275
+ def authorization_uri options = {}
259
276
  # Normalize external input
260
- options = deep_hash_normalize(options)
277
+ options = deep_hash_normalize options
261
278
 
262
- return nil if @authorization_uri == nil
263
- unless options[:response_type]
264
- options[:response_type] = :code
265
- end
266
- if !options[:access_type] && access_type
267
- options[:access_type] = access_type
268
- end
269
- options[:client_id] ||= self.client_id
270
- options[:redirect_uri] ||= self.redirect_uri
279
+ return nil if @authorization_uri.nil?
280
+ options[:response_type] = :code unless options[:response_type]
281
+ options[:access_type] = access_type if !options[:access_type] && access_type
282
+ options[:client_id] ||= client_id
283
+ options[:redirect_uri] ||= redirect_uri
271
284
  if options[:prompt] && options[:approval_prompt]
272
285
  raise ArgumentError, "prompt and approval_prompt are mutually exclusive parameters"
273
286
  end
274
- if !options[:client_id]
275
- raise ArgumentError, "Missing required client identifier."
276
- end
277
- unless options[:redirect_uri]
278
- raise ArgumentError, "Missing required redirect URI."
279
- end
280
- if !options[:scope] && self.scope
281
- options[:scope] = self.scope.join(' ')
282
- end
283
- options[:state] = self.state unless options[:state]
284
- options.merge!(self.additional_parameters.merge(options[:additional_parameters] || {}))
285
- options.delete(:additional_parameters)
287
+ raise ArgumentError, "Missing required client identifier." unless options[:client_id]
288
+ raise ArgumentError, "Missing required redirect URI." unless options[:redirect_uri]
289
+ options[:scope] = scope.join " " if !options[:scope] && scope
290
+ options[:state] = state unless options[:state]
291
+ options.merge!(additional_parameters.merge(options[:additional_parameters] || {}))
292
+ options.delete :additional_parameters
286
293
  options = Hash[options.map do |key, option|
287
294
  [key.to_s, option]
288
295
  end]
@@ -291,20 +298,24 @@ module Signet
291
298
  @authorization_uri, options
292
299
  )
293
300
  )
294
- if uri.normalized_scheme != 'https'
301
+ if uri.normalized_scheme != "https"
295
302
  raise Signet::UnsafeOperationError,
296
- 'Authorization endpoint must be protected by TLS.'
303
+ "Authorization endpoint must be protected by TLS."
297
304
  end
298
- return uri
305
+ uri
299
306
  end
307
+ # rubocop:enable Metrics/AbcSize
308
+ # rubocop:enable Metrics/CyclomaticComplexity
309
+ # rubocop:enable Metrics/MethodLength
310
+ # rubocop:enable Metrics/PerceivedComplexity
300
311
 
301
312
  ##
302
313
  # Sets the authorization URI for this client.
303
314
  #
304
315
  # @param [Addressable::URI, Hash, String, #to_str] new_authorization_uri
305
316
  # The authorization URI.
306
- def authorization_uri=(new_authorization_uri)
307
- @authorization_uri = coerce_uri(new_authorization_uri)
317
+ def authorization_uri= new_authorization_uri
318
+ @authorization_uri = coerce_uri new_authorization_uri
308
319
  end
309
320
 
310
321
  ##
@@ -312,7 +323,7 @@ module Signet
312
323
  #
313
324
  # @return [Addressable::URI] The token credential URI.
314
325
  def token_credential_uri
315
- return @token_credential_uri
326
+ @token_credential_uri
316
327
  end
317
328
 
318
329
  ##
@@ -320,17 +331,17 @@ module Signet
320
331
  #
321
332
  # @param [Addressable::URI, Hash, String, #to_str] new_token_credential_uri
322
333
  # The token credential URI.
323
- def token_credential_uri=(new_token_credential_uri)
324
- @token_credential_uri = coerce_uri(new_token_credential_uri)
334
+ def token_credential_uri= new_token_credential_uri
335
+ @token_credential_uri = coerce_uri new_token_credential_uri
325
336
  end
326
337
 
327
338
  # Addressable expects URIs formatted as hashes to come in with symbols as keys.
328
339
  # Returns nil implicitly for the nil case.
329
- def coerce_uri(incoming_uri)
340
+ def coerce_uri incoming_uri
330
341
  if incoming_uri.is_a? Hash
331
- Addressable::URI.new(deep_hash_normalize(incoming_uri))
342
+ Addressable::URI.new deep_hash_normalize(incoming_uri)
332
343
  elsif incoming_uri
333
- Addressable::URI.parse(incoming_uri)
344
+ Addressable::URI.parse incoming_uri
334
345
  end
335
346
  end
336
347
 
@@ -339,7 +350,7 @@ module Signet
339
350
  #
340
351
  # @return [String, Symbol] The current access type.
341
352
  def access_type
342
- return @access_type
353
+ @access_type
343
354
  end
344
355
 
345
356
  ##
@@ -347,7 +358,7 @@ module Signet
347
358
  #
348
359
  # @param [String, Symbol] new_access_type
349
360
  # The current access type.
350
- def access_type=(new_access_type)
361
+ def access_type= new_access_type
351
362
  @access_type = new_access_type
352
363
  end
353
364
 
@@ -356,7 +367,7 @@ module Signet
356
367
  #
357
368
  # @return [String] The client identifier.
358
369
  def client_id
359
- return @client_id
370
+ @client_id
360
371
  end
361
372
 
362
373
  ##
@@ -364,7 +375,7 @@ module Signet
364
375
  #
365
376
  # @param [String] new_client_id
366
377
  # The client identifier.
367
- def client_id=(new_client_id)
378
+ def client_id= new_client_id
368
379
  @client_id = new_client_id
369
380
  end
370
381
 
@@ -373,7 +384,7 @@ module Signet
373
384
  #
374
385
  # @return [String] The client secret.
375
386
  def client_secret
376
- return @client_secret
387
+ @client_secret
377
388
  end
378
389
 
379
390
  ##
@@ -381,7 +392,7 @@ module Signet
381
392
  #
382
393
  # @param [String] new_client_secret
383
394
  # The client secret.
384
- def client_secret=(new_client_secret)
395
+ def client_secret= new_client_secret
385
396
  @client_secret = new_client_secret
386
397
  end
387
398
 
@@ -391,7 +402,7 @@ module Signet
391
402
  #
392
403
  # @return [Array] The scope of access the client is requesting.
393
404
  def scope
394
- return @scope
405
+ @scope
395
406
  end
396
407
 
397
408
  ##
@@ -401,18 +412,18 @@ module Signet
401
412
  # The scope of access the client is requesting. This may be
402
413
  # expressed as either an Array of String objects or as a
403
414
  # space-delimited String.
404
- def scope=(new_scope)
415
+ def scope= new_scope
405
416
  case new_scope
406
417
  when Array
407
418
  new_scope.each do |scope|
408
- if scope.include?(' ')
419
+ if scope.include? " "
409
420
  raise ArgumentError,
410
- "Individual scopes cannot contain the space character."
421
+ "Individual scopes cannot contain the space character."
411
422
  end
412
423
  end
413
424
  @scope = new_scope
414
425
  when String
415
- @scope = new_scope.split(' ')
426
+ @scope = new_scope.split " "
416
427
  when nil
417
428
  @scope = nil
418
429
  else
@@ -420,12 +431,28 @@ module Signet
420
431
  end
421
432
  end
422
433
 
434
+ ##
435
+ # Returns the final target audience for ID tokens fetched by this client.
436
+ #
437
+ # @return [String] The target audience.
438
+ def target_audience
439
+ @target_audience
440
+ end
441
+
442
+ ##
443
+ # Sets the final target audience for ID tokens fetched by this client.
444
+ #
445
+ # @param [String] new_target_audience The new target audience.
446
+ def target_audience= new_target_audience
447
+ @target_audience = new_target_audience
448
+ end
449
+
423
450
  ##
424
451
  # Returns the client's current state value.
425
452
  #
426
453
  # @return [String] The state value.
427
454
  def state
428
- return @state
455
+ @state
429
456
  end
430
457
 
431
458
  ##
@@ -433,7 +460,7 @@ module Signet
433
460
  #
434
461
  # @param [String] new_state
435
462
  # The state value.
436
- def state=(new_state)
463
+ def state= new_state
437
464
  @state = new_state
438
465
  end
439
466
 
@@ -443,7 +470,7 @@ module Signet
443
470
  #
444
471
  # @return [String] The authorization code.
445
472
  def code
446
- return @code
473
+ @code
447
474
  end
448
475
 
449
476
  ##
@@ -452,7 +479,7 @@ module Signet
452
479
  #
453
480
  # @param [String] new_code
454
481
  # The authorization code.
455
- def code=(new_code)
482
+ def code= new_code
456
483
  @code = new_code
457
484
  end
458
485
 
@@ -461,7 +488,7 @@ module Signet
461
488
  #
462
489
  # @return [String] The redirect URI.
463
490
  def redirect_uri
464
- return @redirect_uri
491
+ @redirect_uri
465
492
  end
466
493
 
467
494
  ##
@@ -469,14 +496,14 @@ module Signet
469
496
  #
470
497
  # @param [String] new_redirect_uri
471
498
  # The redirect URI.
472
- def redirect_uri=(new_redirect_uri)
473
- new_redirect_uri = Addressable::URI.parse(new_redirect_uri)
474
- #TODO - Better solution to allow google postmessage flow. For now, make an exception to the spec.
475
- if new_redirect_uri == nil|| new_redirect_uri.absolute? || uri_is_postmessage?(new_redirect_uri) || uri_is_oob?(new_redirect_uri)
476
- @redirect_uri = new_redirect_uri
477
- else
499
+ def redirect_uri= new_redirect_uri
500
+ new_redirect_uri = Addressable::URI.parse new_redirect_uri
501
+ # TODO: - Better solution to allow google postmessage flow. For now, make an exception to the spec.
502
+ unless new_redirect_uri.nil? || new_redirect_uri.absolute? || uri_is_postmessage?(new_redirect_uri) ||
503
+ uri_is_oob?(new_redirect_uri)
478
504
  raise ArgumentError, "Redirect URI must be an absolute URI."
479
505
  end
506
+ @redirect_uri = new_redirect_uri
480
507
  end
481
508
 
482
509
  ##
@@ -485,7 +512,7 @@ module Signet
485
512
  #
486
513
  # @return [String] The username.
487
514
  def username
488
- return @username
515
+ @username
489
516
  end
490
517
 
491
518
  ##
@@ -494,7 +521,7 @@ module Signet
494
521
  #
495
522
  # @param [String] new_username
496
523
  # The username.
497
- def username=(new_username)
524
+ def username= new_username
498
525
  @username = new_username
499
526
  end
500
527
 
@@ -504,7 +531,7 @@ module Signet
504
531
  #
505
532
  # @return [String] The password.
506
533
  def password
507
- return @password
534
+ @password
508
535
  end
509
536
 
510
537
  ##
@@ -513,7 +540,7 @@ module Signet
513
540
  #
514
541
  # @param [String] new_password
515
542
  # The password.
516
- def password=(new_password)
543
+ def password= new_password
517
544
  @password = new_password
518
545
  end
519
546
 
@@ -523,7 +550,7 @@ module Signet
523
550
  #
524
551
  # @return [String] Issuer id.
525
552
  def issuer
526
- return @issuer
553
+ @issuer
527
554
  end
528
555
 
529
556
  ##
@@ -532,17 +559,17 @@ module Signet
532
559
  #
533
560
  # @param [String] new_issuer
534
561
  # Issuer ID (typical in email adddress form).
535
- def issuer=(new_issuer)
562
+ def issuer= new_issuer
536
563
  @issuer = new_issuer
537
564
  end
538
565
 
539
566
  ##
540
- # Returns the issuer ID associated with this client.
567
+ # Returns the target audience ID when issuing assertions.
541
568
  # Used only by the assertion grant type.
542
569
  #
543
570
  # @return [String] Target audience ID.
544
571
  def audience
545
- return @audience
572
+ @audience
546
573
  end
547
574
 
548
575
  ##
@@ -551,7 +578,7 @@ module Signet
551
578
  #
552
579
  # @param [String] new_audience
553
580
  # Target audience ID
554
- def audience=(new_audience)
581
+ def audience= new_audience
555
582
  @audience = new_audience
556
583
  end
557
584
 
@@ -561,7 +588,7 @@ module Signet
561
588
  #
562
589
  # @return [String] Target user for impersonation.
563
590
  def principal
564
- return @principal
591
+ @principal
565
592
  end
566
593
 
567
594
  ##
@@ -570,12 +597,12 @@ module Signet
570
597
  #
571
598
  # @param [String] new_person
572
599
  # Target user for impersonation
573
- def principal=(new_person)
600
+ def principal= new_person
574
601
  @principal = new_person
575
602
  end
576
603
 
577
- alias_method :person, :principal
578
- alias_method :person=, :principal=
604
+ alias person principal
605
+ alias person= principal=
579
606
 
580
607
  ##
581
608
  # The target "sub" when issuing assertions.
@@ -589,7 +616,7 @@ module Signet
589
616
  #
590
617
  # @return [Integer] Assertion expiry, in seconds
591
618
  def expiry
592
- return @expiry
619
+ @expiry
593
620
  end
594
621
 
595
622
  ##
@@ -598,18 +625,17 @@ module Signet
598
625
  #
599
626
  # @param [Integer, String] new_expiry
600
627
  # Assertion expiry, in seconds
601
- def expiry=(new_expiry)
628
+ def expiry= new_expiry
602
629
  @expiry = new_expiry ? new_expiry.to_i : nil
603
630
  end
604
631
 
605
-
606
632
  ##
607
633
  # Returns the signing key associated with this client.
608
634
  # Used only by the assertion grant type.
609
635
  #
610
636
  # @return [String,OpenSSL::PKey] Signing key
611
637
  def signing_key
612
- return @signing_key
638
+ @signing_key
613
639
  end
614
640
 
615
641
  ##
@@ -618,7 +644,7 @@ module Signet
618
644
  #
619
645
  # @param [String, OpenSSL::Pkey] new_key
620
646
  # Signing key. Either private key for RSA or string for HMAC algorithm
621
- def signing_key=(new_key)
647
+ def signing_key= new_key
622
648
  @signing_key = new_key
623
649
  end
624
650
 
@@ -626,7 +652,7 @@ module Signet
626
652
  # Algorithm used for signing JWTs
627
653
  # @return [String] Signing algorithm
628
654
  def signing_algorithm
629
- self.signing_key.is_a?(String) ? "HS256" : "RS256"
655
+ signing_key.is_a?(String) ? "HS256" : "RS256"
630
656
  end
631
657
 
632
658
  ##
@@ -635,7 +661,7 @@ module Signet
635
661
  #
636
662
  # @return [Hash] The extension parameters.
637
663
  def extension_parameters
638
- return @extension_parameters ||= {}
664
+ @extension_parameters ||= {}
639
665
  end
640
666
 
641
667
  ##
@@ -644,12 +670,12 @@ module Signet
644
670
  #
645
671
  # @param [Hash] new_extension_parameters
646
672
  # The parameters.
647
- def extension_parameters=(new_extension_parameters)
648
- if new_extension_parameters.respond_to?(:to_hash)
673
+ def extension_parameters= new_extension_parameters
674
+ if new_extension_parameters.respond_to? :to_hash
649
675
  @extension_parameters = new_extension_parameters.to_hash
650
676
  else
651
677
  raise TypeError,
652
- "Expected Hash, got #{new_extension_parameters.class}."
678
+ "Expected Hash, got #{new_extension_parameters.class}."
653
679
  end
654
680
  end
655
681
 
@@ -658,7 +684,7 @@ module Signet
658
684
  #
659
685
  # @return [Hash] The pass through parameters.
660
686
  def additional_parameters
661
- return @additional_parameters ||= {}
687
+ @additional_parameters ||= {}
662
688
  end
663
689
 
664
690
  ##
@@ -666,8 +692,8 @@ module Signet
666
692
  #
667
693
  # @param [Hash] new_additional_parameters
668
694
  # The parameters.
669
- def additional_parameters=(new_additional_parameters)
670
- if new_additional_parameters.respond_to?(:to_hash)
695
+ def additional_parameters= new_additional_parameters
696
+ if new_additional_parameters.respond_to? :to_hash
671
697
  @additional_parameters = new_additional_parameters.to_hash
672
698
  else
673
699
  raise TypeError,
@@ -680,7 +706,7 @@ module Signet
680
706
  #
681
707
  # @return [String] The refresh token.
682
708
  def refresh_token
683
- return @refresh_token ||= nil
709
+ @refresh_token ||= nil
684
710
  end
685
711
 
686
712
  ##
@@ -688,7 +714,7 @@ module Signet
688
714
  #
689
715
  # @param [String] new_refresh_token
690
716
  # The refresh token.
691
- def refresh_token=(new_refresh_token)
717
+ def refresh_token= new_refresh_token
692
718
  @refresh_token = new_refresh_token
693
719
  end
694
720
 
@@ -697,7 +723,7 @@ module Signet
697
723
  #
698
724
  # @return [String] The access token.
699
725
  def access_token
700
- return @access_token ||= nil
726
+ @access_token ||= nil
701
727
  end
702
728
 
703
729
  ##
@@ -705,7 +731,7 @@ module Signet
705
731
  #
706
732
  # @param [String] new_access_token
707
733
  # The access token.
708
- def access_token=(new_access_token)
734
+ def access_token= new_access_token
709
735
  @access_token = new_access_token
710
736
  end
711
737
 
@@ -714,7 +740,7 @@ module Signet
714
740
  #
715
741
  # @return [String] The ID token.
716
742
  def id_token
717
- return @id_token ||= nil
743
+ @id_token ||= nil
718
744
  end
719
745
 
720
746
  ##
@@ -722,7 +748,7 @@ module Signet
722
748
  #
723
749
  # @param [String] new_id_token
724
750
  # The ID token.
725
- def id_token=(new_id_token)
751
+ def id_token= new_id_token
726
752
  @id_token = new_id_token
727
753
  end
728
754
 
@@ -734,17 +760,16 @@ module Signet
734
760
  # omitted.
735
761
  #
736
762
  # @return [String] The decoded ID token.
737
- def decoded_id_token public_key=nil, options = {}, &keyfinder
763
+ def decoded_id_token public_key = nil, options = {}, &keyfinder
738
764
  options[:algorithm] ||= signing_algorithm
739
- verify = !!(public_key || keyfinder)
740
- payload, _header = JWT.decode(self.id_token, public_key, verify, options, &keyfinder)
741
- if !payload.has_key?('aud')
742
- raise Signet::UnsafeOperationError, 'No ID token audience declared.'
743
- elsif payload['aud'] != self.client_id
765
+ verify = !public_key.nil? || block_given?
766
+ payload, _header = JWT.decode(id_token, public_key, verify, options, &keyfinder)
767
+ raise Signet::UnsafeOperationError, "No ID token audience declared." unless payload.key? "aud"
768
+ unless Array(payload["aud"]).include?(client_id)
744
769
  raise Signet::UnsafeOperationError,
745
- 'ID token audience did not match Client ID.'
770
+ "ID token audience did not match Client ID."
746
771
  end
747
- return payload
772
+ payload
748
773
  end
749
774
 
750
775
  ##
@@ -790,8 +815,8 @@ module Signet
790
815
  #
791
816
  # @param [String,Integer,Time] new_issued_at
792
817
  # The access token issuance time.
793
- def issued_at=(new_issued_at)
794
- @issued_at = normalize_timestamp(new_issued_at)
818
+ def issued_at= new_issued_at
819
+ @issued_at = normalize_timestamp new_issued_at
795
820
  end
796
821
 
797
822
  ##
@@ -809,7 +834,7 @@ module Signet
809
834
  # not expire.
810
835
  # @param [String,Integer,Time, nil] new_expires_at
811
836
  # The access token expiration time.
812
- def expires_at=(new_expires_at)
837
+ def expires_at= new_expires_at
813
838
  @expires_at = normalize_timestamp new_expires_at
814
839
  end
815
840
 
@@ -820,7 +845,7 @@ module Signet
820
845
  # @return [TrueClass, FalseClass]
821
846
  # The expiration state of the access token.
822
847
  def expired?
823
- return self.expires_at != nil && Time.now >= self.expires_at
848
+ !expires_at.nil? && Time.now >= expires_at
824
849
  end
825
850
 
826
851
  ##
@@ -832,8 +857,8 @@ module Signet
832
857
  # expired.
833
858
  # @return [TrueClass, FalseClass]
834
859
  # The expiration state of the access token.
835
- def expires_within?(sec)
836
- return self.expires_at != nil && Time.now >= (self.expires_at - sec)
860
+ def expires_within? sec
861
+ !expires_at.nil? && Time.now >= (expires_at - sec)
837
862
  end
838
863
 
839
864
  ##
@@ -849,7 +874,6 @@ module Signet
849
874
  @expires_at = nil
850
875
  end
851
876
 
852
-
853
877
  ##
854
878
  # Returns the inferred grant type, based on the current state of the
855
879
  # client object. Returns `"none"` if the client has insufficient
@@ -859,52 +883,47 @@ module Signet
859
883
  # The inferred grant type.
860
884
  def grant_type
861
885
  @grant_type ||= nil
862
- if @grant_type
863
- return @grant_type
864
- else
865
- if self.code && self.redirect_uri
866
- 'authorization_code'
867
- elsif self.refresh_token
868
- 'refresh_token'
869
- elsif self.username && self.password
870
- 'password'
871
- elsif self.issuer && self.signing_key
872
- 'urn:ietf:params:oauth:grant-type:jwt-bearer'
873
- else
874
- # We don't have sufficient auth information, assume an out-of-band
875
- # authorization arrangement between the client and server, or an
876
- # extension grant type.
877
- nil
878
- end
886
+ return @grant_type if @grant_type
887
+ if code && redirect_uri
888
+ "authorization_code"
889
+ elsif refresh_token
890
+ "refresh_token"
891
+ elsif username && password
892
+ "password"
893
+ elsif issuer && signing_key
894
+ "urn:ietf:params:oauth:grant-type:jwt-bearer"
879
895
  end
880
896
  end
881
897
 
882
- def grant_type=(new_grant_type)
898
+ def grant_type= new_grant_type
883
899
  case new_grant_type
884
- when 'authorization_code', 'refresh_token',
885
- 'password', 'client_credentials'
900
+ when "authorization_code", "refresh_token",
901
+ "password", "client_credentials"
886
902
  @grant_type = new_grant_type
887
903
  else
888
- @grant_type = Addressable::URI.parse(new_grant_type)
904
+ @grant_type = Addressable::URI.parse new_grant_type
889
905
  end
890
906
  end
891
907
 
892
- def to_jwt(options={})
893
- options = deep_hash_normalize(options)
908
+ def to_jwt options = {}
909
+ options = deep_hash_normalize options
894
910
 
895
911
  now = Time.new
896
912
  skew = options[:skew] || 60
897
913
  assertion = {
898
- "iss" => self.issuer,
899
- "aud" => self.audience,
900
- "exp" => (now + self.expiry).to_i,
914
+ "iss" => issuer,
915
+ "aud" => audience,
916
+ "exp" => (now + expiry).to_i,
901
917
  "iat" => (now - skew).to_i
902
918
  }
903
- assertion['scope'] = self.scope.join(' ') unless self.scope.nil?
904
- assertion['prn'] = self.person unless self.person.nil?
905
- assertion['sub'] = self.sub unless self.sub.nil?
906
- JWT.encode(assertion, self.signing_key, self.signing_algorithm)
919
+ assertion["scope"] = scope.join " " unless scope.nil?
920
+ assertion["target_audience"] = target_audience unless target_audience.nil?
921
+ assertion["prn"] = person unless person.nil?
922
+ assertion["sub"] = sub unless sub.nil?
923
+ JWT.encode assertion, signing_key, signing_algorithm
907
924
  end
925
+ # rubocop:disable Style/MethodDefParentheses
926
+ # rubocop:disable Metrics/AbcSize
908
927
 
909
928
  ##
910
929
  # Serialize the client object to JSON.
@@ -913,29 +932,34 @@ module Signet
913
932
  #
914
933
  # @return [String] A serialized JSON representation of the client.
915
934
  def to_json(*)
916
- return MultiJson.dump({
917
- 'authorization_uri' => self.authorization_uri ? self.authorization_uri.to_s : nil,
918
- 'token_credential_uri' => self.token_credential_uri ? self.token_credential_uri.to_s : nil,
919
- 'client_id' => self.client_id,
920
- 'client_secret' => self.client_secret,
921
- 'scope' => self.scope,
922
- 'state' => self.state,
923
- 'code' => self.code,
924
- 'redirect_uri' => self.redirect_uri ? self.redirect_uri.to_s : nil,
925
- 'username' => self.username,
926
- 'password' => self.password,
927
- 'issuer' => self.issuer,
928
- 'audience' => self.audience,
929
- 'person' => self.person,
930
- 'expiry' => self.expiry,
931
- 'expires_at' => self.expires_at ? self.expires_at.to_i : nil,
932
- 'signing_key' => self.signing_key,
933
- 'refresh_token' => self.refresh_token,
934
- 'access_token' => self.access_token,
935
- 'id_token' => self.id_token,
936
- 'extension_parameters' => self.extension_parameters
937
- })
935
+ MultiJson.dump(
936
+ "authorization_uri" => authorization_uri ? authorization_uri.to_s : nil,
937
+ "token_credential_uri" => token_credential_uri ? token_credential_uri.to_s : nil,
938
+ "client_id" => client_id,
939
+ "client_secret" => client_secret,
940
+ "scope" => scope,
941
+ "target_audience" => target_audience,
942
+ "state" => state,
943
+ "code" => code,
944
+ "redirect_uri" => redirect_uri ? redirect_uri.to_s : nil,
945
+ "username" => username,
946
+ "password" => password,
947
+ "issuer" => issuer,
948
+ "audience" => audience,
949
+ "person" => person,
950
+ "expiry" => expiry,
951
+ "expires_at" => expires_at ? expires_at.to_i : nil,
952
+ "signing_key" => signing_key,
953
+ "refresh_token" => refresh_token,
954
+ "access_token" => access_token,
955
+ "id_token" => id_token,
956
+ "extension_parameters" => extension_parameters
957
+ )
938
958
  end
959
+ # rubocop:enable Style/MethodDefParentheses
960
+ # rubocop:disable Metrics/CyclomaticComplexity
961
+ # rubocop:disable Metrics/MethodLength
962
+ # rubocop:disable Metrics/PerceivedComplexity
939
963
 
940
964
  ##
941
965
  # Generates a request for token credentials.
@@ -947,58 +971,58 @@ module Signet
947
971
  #
948
972
  # @private
949
973
  # @return [Array] The request object.
950
- def generate_access_token_request(options={})
951
- options = deep_hash_normalize(options)
952
-
953
- parameters = {"grant_type" => self.grant_type}
954
- case self.grant_type
955
- when 'authorization_code'
956
- parameters['code'] = self.code
957
- parameters['redirect_uri'] = self.redirect_uri
958
- when 'password'
959
- parameters['username'] = self.username
960
- parameters['password'] = self.password
961
- when 'refresh_token'
962
- parameters['refresh_token'] = self.refresh_token
963
- when 'urn:ietf:params:oauth:grant-type:jwt-bearer'
964
- parameters['assertion'] = self.to_jwt(options)
974
+ def generate_access_token_request options = {}
975
+ options = deep_hash_normalize options
976
+
977
+ parameters = { "grant_type" => grant_type }
978
+ case grant_type
979
+ when "authorization_code"
980
+ parameters["code"] = code
981
+ parameters["redirect_uri"] = redirect_uri
982
+ when "password"
983
+ parameters["username"] = username
984
+ parameters["password"] = password
985
+ when "refresh_token"
986
+ parameters["refresh_token"] = refresh_token
987
+ when "urn:ietf:params:oauth:grant-type:jwt-bearer"
988
+ parameters["assertion"] = to_jwt options
965
989
  else
966
- if self.redirect_uri
990
+ if redirect_uri
967
991
  # Grant type was intended to be `authorization_code` because of
968
992
  # the presence of the redirect URI.
969
- raise ArgumentError, 'Missing authorization code.'
993
+ raise ArgumentError, "Missing authorization code."
970
994
  end
971
- parameters.merge!(self.extension_parameters)
995
+ parameters.merge! extension_parameters
972
996
  end
973
- parameters['client_id'] = self.client_id unless self.client_id.nil?
974
- parameters['client_secret'] = self.client_secret unless self.client_secret.nil?
997
+ parameters["client_id"] = client_id unless client_id.nil?
998
+ parameters["client_secret"] = client_secret unless client_secret.nil?
975
999
  if options[:scope]
976
- parameters['scope'] = options[:scope]
977
- elsif options[:use_configured_scope] && !self.scope.nil?
978
- parameters['scope'] = self.scope
1000
+ parameters["scope"] = options[:scope]
1001
+ elsif options[:use_configured_scope] && !scope.nil?
1002
+ parameters["scope"] = scope
979
1003
  end
980
- additional = self.additional_parameters.merge(options[:additional_parameters] || {})
1004
+ additional = additional_parameters.merge(options[:additional_parameters] || {})
981
1005
  additional.each { |k, v| parameters[k.to_s] = v }
982
1006
  parameters
983
1007
  end
1008
+ # rubocop:enable Metrics/CyclomaticComplexity
1009
+ # rubocop:enable Metrics/PerceivedComplexity
984
1010
 
985
- def fetch_access_token(options={})
986
- if self.token_credential_uri.nil?
987
- raise ArgumentError, 'Missing token endpoint URI.'
988
- end
1011
+ def fetch_access_token options = {}
1012
+ raise ArgumentError, "Missing token endpoint URI." if token_credential_uri.nil?
989
1013
 
990
- options = deep_hash_normalize(options)
1014
+ options = deep_hash_normalize options
991
1015
 
992
1016
  client = options[:connection] ||= Faraday.default_connection
993
- url = Addressable::URI.parse(self.token_credential_uri).normalize.to_s
994
- parameters = self.generate_access_token_request(options)
995
- if client.is_a?(Faraday::Connection)
1017
+ url = Addressable::URI.parse(token_credential_uri).normalize.to_s
1018
+ parameters = generate_access_token_request options
1019
+ if client.is_a? Faraday::Connection
996
1020
  response = client.post url,
997
- Addressable::URI.form_encode(parameters),
998
- { 'Content-Type' => 'application/x-www-form-urlencoded' }
1021
+ Addressable::URI.form_encode(parameters),
1022
+ "Content-Type" => "application/x-www-form-urlencoded"
999
1023
  status = response.status.to_i
1000
1024
  body = response.body
1001
- content_type = response.headers['Content-type']
1025
+ content_type = response.headers["Content-type"]
1002
1026
  else
1003
1027
  # Hurley
1004
1028
  response = client.post url, parameters
@@ -1007,49 +1031,46 @@ module Signet
1007
1031
  content_type = response.header[:content_type]
1008
1032
  end
1009
1033
 
1010
- if status == 200
1011
- return ::Signet::OAuth2.parse_credentials(body, content_type)
1012
- elsif [400, 401, 403].include?(status)
1013
- message = 'Authorization failed.'
1014
- if body.to_s.strip.length > 0
1015
- message += " Server message:\n#{response.body.to_s.strip}"
1016
- end
1034
+ return ::Signet::OAuth2.parse_credentials body, content_type if status == 200
1035
+
1036
+ message = " Server message:\n#{response.body.to_s.strip}" unless body.to_s.strip.empty?
1037
+ if [400, 401, 403].include? status
1038
+ message = "Authorization failed." + message
1017
1039
  raise ::Signet::AuthorizationError.new(
1018
- message, :response => response
1040
+ message, response: response
1019
1041
  )
1020
1042
  elsif status.to_s[0] == "5"
1021
- message = 'Remote server error.'
1022
- if body.to_s.strip.length > 0
1023
- message += " Server message:\n#{response.body.to_s.strip}"
1024
- end
1025
- raise ::Signet::RemoteServerError.new(message)
1043
+ message = "Remote server error." + message
1044
+ raise ::Signet::RemoteServerError, message
1026
1045
  else
1027
- message = "Unexpected status code: #{response.status}."
1028
- if body.to_s.strip.length > 0
1029
- message += " Server message:\n#{response.body.to_s.strip}"
1030
- end
1031
- raise ::Signet::UnexpectedStatusError.new(message)
1046
+ message = "Unexpected status code: #{response.status}." + message
1047
+ raise ::Signet::UnexpectedStatusError, message
1032
1048
  end
1033
1049
  end
1050
+ # rubocop:enable Metrics/AbcSize
1051
+ # rubocop:enable Metrics/MethodLength
1034
1052
 
1035
- def fetch_access_token!(options={})
1036
- token_hash = self.fetch_access_token(options)
1053
+ def fetch_access_token! options = {}
1054
+ token_hash = fetch_access_token options
1037
1055
  if token_hash
1038
1056
  # No-op for grant types other than `authorization_code`.
1039
1057
  # An authorization code is a one-time use token and is immediately
1040
1058
  # revoked after usage.
1041
1059
  self.code = nil
1042
1060
  self.issued_at = Time.now
1043
- self.update_token!(token_hash)
1061
+ update_token! token_hash
1044
1062
  end
1045
- return token_hash
1063
+ token_hash
1046
1064
  end
1047
1065
 
1048
1066
  ##
1049
1067
  # Refresh the access token, if possible
1050
- def refresh!(options={})
1051
- self.fetch_access_token!(options)
1068
+ def refresh! options = {}
1069
+ fetch_access_token! options
1052
1070
  end
1071
+ # rubocop:disable Metrics/AbcSize
1072
+ # rubocop:disable Metrics/MethodLength
1073
+ # rubocop:disable Metrics/PerceivedComplexity
1053
1074
 
1054
1075
  ##
1055
1076
  # Generates an authenticated request for protected resources.
@@ -1071,55 +1092,54 @@ module Signet
1071
1092
  # - <code>:realm</code> -
1072
1093
  # The Authorization realm. See RFC 2617.
1073
1094
  # @return [Faraday::Request] The request object.
1074
- def generate_authenticated_request(options={})
1075
- options = deep_hash_normalize(options)
1095
+ def generate_authenticated_request options = {}
1096
+ options = deep_hash_normalize options
1076
1097
 
1077
- if self.access_token == nil
1078
- raise ArgumentError, 'Missing access token.'
1079
- end
1098
+ raise ArgumentError, "Missing access token." if access_token.nil?
1080
1099
  options = {
1081
- :realm => nil
1100
+ realm: nil
1082
1101
  }.merge(options)
1083
1102
 
1084
- if options[:request].kind_of?(Faraday::Request)
1103
+ if options[:request].is_a? Faraday::Request
1085
1104
  request = options[:request]
1086
1105
  else
1087
- if options[:request].kind_of?(Array)
1106
+ if options[:request].is_a? Array
1088
1107
  method, uri, headers, body = options[:request]
1089
1108
  else
1090
1109
  method = options[:method] || :get
1091
1110
  uri = options[:uri]
1092
1111
  headers = options[:headers] || []
1093
- body = options[:body] || ''
1112
+ body = options[:body] || ""
1094
1113
  end
1095
- headers = headers.to_a if headers.kind_of?(Hash)
1114
+ headers = headers.to_a if headers.is_a? Hash
1096
1115
  request_components = {
1097
- :method => method,
1098
- :uri => uri,
1099
- :headers => headers,
1100
- :body => body
1116
+ method: method,
1117
+ uri: uri,
1118
+ headers: headers,
1119
+ body: body
1101
1120
  }
1102
1121
  # Verify that we have all pieces required to return an HTTP request
1103
1122
  request_components.each do |(key, value)|
1104
- unless value
1105
- raise ArgumentError, "Missing :#{key} parameter."
1106
- end
1123
+ raise ArgumentError, "Missing :#{key} parameter." unless value
1107
1124
  end
1108
1125
  method = method.to_s.downcase.to_sym
1109
- request = options[:connection].build_request(method.to_s.downcase.to_sym) do |req|
1110
- req.url(Addressable::URI.parse(uri).normalize.to_s)
1111
- req.headers = Faraday::Utils::Headers.new(headers)
1126
+ request = options[:connection].build_request method.to_s.downcase.to_sym do |req|
1127
+ req.url Addressable::URI.parse(uri).normalize.to_s
1128
+ req.headers = Faraday::Utils::Headers.new headers
1112
1129
  req.body = body
1113
1130
  end
1114
1131
  end
1115
1132
 
1116
- request['Authorization'] = ::Signet::OAuth2.generate_bearer_authorization_header(
1117
- self.access_token,
1118
- options[:realm] ? [['realm', options[:realm]]] : nil
1133
+ request["Authorization"] = ::Signet::OAuth2.generate_bearer_authorization_header(
1134
+ access_token,
1135
+ options[:realm] ? [["realm", options[:realm]]] : nil
1119
1136
  )
1120
- request['Cache-Control'] = 'no-store'
1121
- return request
1137
+ request["Cache-Control"] = "no-store"
1138
+ request
1122
1139
  end
1140
+ # rubocop:enable Metrics/AbcSize
1141
+ # rubocop:enable Metrics/MethodLength
1142
+ # rubocop:enable Metrics/PerceivedComplexity
1123
1143
 
1124
1144
  ##
1125
1145
  # Transmits a request for a protected resource.
@@ -1151,27 +1171,22 @@ module Signet
1151
1171
  # )
1152
1172
  #
1153
1173
  # @return [Array] The response object.
1154
- def fetch_protected_resource(options={})
1155
- options = deep_hash_normalize(options)
1174
+ def fetch_protected_resource options = {}
1175
+ options = deep_hash_normalize options
1156
1176
 
1157
1177
  options[:connection] ||= Faraday.default_connection
1158
- request = self.generate_authenticated_request(options)
1159
- request_env = request.to_env(options[:connection])
1178
+ request = generate_authenticated_request options
1179
+ request_env = request.to_env options[:connection]
1160
1180
  request_env[:request] ||= request
1161
- response = options[:connection].app.call(request_env)
1162
- if response.status.to_i == 401
1163
- # When accessing a protected resource, we only want to raise an
1164
- # error for 401 responses.
1165
- message = 'Authorization failed.'
1166
- if response.body.to_s.strip.length > 0
1167
- message += " Server message:\n#{response.body.to_s.strip}"
1168
- end
1169
- raise ::Signet::AuthorizationError.new(
1170
- message, :request => request, :response => response
1171
- )
1172
- else
1173
- return response
1174
- end
1181
+ response = options[:connection].app.call request_env
1182
+ return response unless response.status.to_i == 401
1183
+ # When accessing a protected resource, we only want to raise an
1184
+ # error for 401 responses.
1185
+ message = "Authorization failed."
1186
+ message += " Server message:\n#{response.body.to_s.strip}" unless response.body.to_s.strip.empty?
1187
+ raise ::Signet::AuthorizationError.new(
1188
+ message, request: request, response: response
1189
+ )
1175
1190
  end
1176
1191
 
1177
1192
  private
@@ -1179,33 +1194,33 @@ module Signet
1179
1194
  ##
1180
1195
  # Check if URI is Google's postmessage flow (not a valid redirect_uri by spec, but allowed)
1181
1196
  # @private
1182
- def uri_is_postmessage?(uri)
1183
- return uri.to_s.casecmp('postmessage') == 0
1197
+ def uri_is_postmessage? uri
1198
+ uri.to_s.casecmp("postmessage").zero?
1184
1199
  end
1185
1200
 
1186
1201
  ##
1187
1202
  # Check if the URI is a out-of-band
1188
1203
  # @private
1189
- def uri_is_oob?(uri)
1190
- return OOB_MODES.include?(uri.to_s)
1204
+ def uri_is_oob? uri
1205
+ OOB_MODES.include? uri.to_s
1191
1206
  end
1192
1207
 
1193
1208
  # Convert all keys in this hash (nested) to symbols for uniform retrieval
1194
- def recursive_hash_normalize_keys(val)
1209
+ def recursive_hash_normalize_keys val
1195
1210
  if val.is_a? Hash
1196
- deep_hash_normalize(val)
1211
+ deep_hash_normalize val
1197
1212
  else
1198
1213
  val
1199
1214
  end
1200
1215
  end
1201
1216
 
1202
- def deep_hash_normalize(old_hash)
1217
+ def deep_hash_normalize old_hash
1203
1218
  sym_hash = {}
1204
- old_hash and old_hash.each {|k,v| sym_hash[k.to_sym] = recursive_hash_normalize_keys(v)}
1219
+ old_hash&.each { |k, v| sym_hash[k.to_sym] = recursive_hash_normalize_keys v }
1205
1220
  sym_hash
1206
1221
  end
1207
1222
 
1208
- def normalize_timestamp(time)
1223
+ def normalize_timestamp time
1209
1224
  case time
1210
1225
  when NilClass
1211
1226
  nil
@@ -1214,15 +1229,15 @@ module Signet
1214
1229
  when DateTime
1215
1230
  time.to_time
1216
1231
  when String
1217
- Time.parse(time)
1232
+ Time.parse time
1218
1233
  when Integer
1219
- Time.at(time)
1234
+ Time.at time
1220
1235
  else
1221
- fail "Invalid time value #{time}"
1236
+ raise "Invalid time value #{time}"
1222
1237
  end
1223
1238
  end
1224
1239
 
1225
- def set_relative_expires_at(issued_at, expires_in)
1240
+ def set_relative_expires_at issued_at, expires_in
1226
1241
  self.issued_at = issued_at
1227
1242
  # Using local expires_in because if self.expires_in is used, it returns
1228
1243
  # the time left before the token expires