signet 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a90553898c900b623be7bcd66492052606823e88
4
- data.tar.gz: 79d812b9a1bf1c00a548b48a5434dd8a3f40cb39
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODJiNTkyYjQ1OGRkNDY2Y2RjNDZiY2U1YjJhNWI3MWFmNmU5OTNiNw==
5
+ data.tar.gz: !binary |-
6
+ MGUyODYzMjdmODI4Y2U4YjE5YTMyYzY2ZDU1ZWE3ZGFlYjZmNjRlMw==
5
7
  SHA512:
6
- metadata.gz: b41031268b8c1e10cea6cc132edcb85954c398927ecd7c364c401fab64930758c47a87d4ffb4b1c196f6c6e9dedd3a2cf893d939910440649f560c39555b0546
7
- data.tar.gz: be0549ccf4f39e5d7d0a67b209884c798bfcec5bda4618a27e6e96579cec21ff54d76f08c64cf606925cf9c04015c72c678f3066b3cfa75daf60648ae8bb6c29
8
+ metadata.gz: !binary |-
9
+ YTIyZGY5MDFjYmM4OWQwOWQzNTBjM2ZmNTNiNjg2ODBlYzAzMTdkOWQ4MWRh
10
+ OGQ4NTcxMjhkMGYxZmQyZGVhZTk5YzI3N2IyN2JmYjM0OTIyYTc2Yzc2ZTAw
11
+ MmRiZDRjZjM2NzFkMjdhYTEyNzQ5YTBlMjljZGU5NDA0YzRjZTc=
12
+ data.tar.gz: !binary |-
13
+ MWY0ZWJhNDg2MWQ1YjlkODQ5ZmQzMzBjNmRjZWVhYjA5N2JkZjU5YjRkMjU2
14
+ ZTBkNzNmZGQ5NDU4YjgyZjMxM2FiODdhZjM3YjE4OWZkYzBhZTk2ZGMxZWM5
15
+ YmE4YzU2YzI2M2E0NGIzZDI5ODMzYWJhMzM5MjkzMmQ5MjM5NTM=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # 0.6.0
2
+
3
+ * Drop support for ruby versions < 1.9.3
4
+ * Update gem dependencies and lock down versions tighter
5
+ * Allow form encoded responses when exchanging OAuth 2 authorization codes
6
+ * Normalize options keys for indifferent access
7
+
1
8
  # 0.5.1
2
9
 
3
10
  * Allow Hash objects to be used to initialize authorization URI
data/Gemfile CHANGED
@@ -1,22 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'addressable', '>= 2.3.1'
4
- gem 'faraday', '>= 0.9.0.rc5'
5
- gem 'multi_json', '>= 1.0.0'
6
- gem 'jwt', '>= 0.1.5'
7
- gem 'extlib', '>= 0.9.15'
8
- gem 'jruby-openssl', :platforms => :jruby
9
-
10
- group :development do
11
- gem 'launchy', '>= 2.1.1'
12
- gem 'yard'
13
- gem 'kramdown'
14
- end
3
+ gemspec
15
4
 
16
-
17
- group :test, :development do
18
- gem 'json', '~> 1.7.7'
19
- gem 'rake', '>= 0.9.0'
20
- gem 'rspec', '>= 2.11.0'
21
- gem 'rcov', '>= 0.9.9', :platform => :mri_18
22
- end
5
+ gem 'jruby-openssl', :platforms => :jruby
@@ -153,26 +153,27 @@ module Signet
153
153
  # @see Signet::OAuth2::Client#initialize
154
154
  # @see Signet::OAuth2::Client#update_token!
155
155
  def update!(options={})
156
- # Normalize key to String to allow indifferent access.
157
- options = options.inject({}) { |accu, (k, v)| accu[k.to_s] = v; accu }
158
- self.authorization_uri = options["authorization_uri"] if options.has_key?("authorization_uri")
159
- self.token_credential_uri = options["token_credential_uri"] if options.has_key?("token_credential_uri")
160
- self.client_id = options["client_id"] if options.has_key?("client_id")
161
- self.client_secret = options["client_secret"] if options.has_key?("client_secret")
162
- self.scope = options["scope"] if options.has_key?("scope")
163
- self.state = options["state"] if options.has_key?("state")
164
- self.code = options["code"] if options.has_key?("code")
165
- self.redirect_uri = options["redirect_uri"] if options.has_key?("redirect_uri")
166
- self.username = options["username"] if options.has_key?("username")
167
- self.password = options["password"] if options.has_key?("password")
168
- self.issuer = options["issuer"] if options.has_key?("issuer")
169
- self.person = options["person"] if options.has_key?("person")
170
- self.sub = options["sub"] if options.has_key?("sub")
171
- self.expiry = options["expiry"] || 60
172
- self.audience = options["audience"] if options.has_key?("audience")
173
- self.signing_key = options["signing_key"] if options.has_key?("signing_key")
174
- self.extension_parameters = options["extension_parameters"] || {}
175
- self.additional_parameters = options["additional_parameters"] || {}
156
+ # Normalize all keys to symbols to allow indifferent access.
157
+ options = deep_hash_normalize(options)
158
+
159
+ self.authorization_uri = options[:authorization_uri] if options.has_key?(:authorization_uri)
160
+ self.token_credential_uri = options[:token_credential_uri] if options.has_key?(:token_credential_uri)
161
+ self.client_id = options[:client_id] if options.has_key?(:client_id)
162
+ self.client_secret = options[:client_secret] if options.has_key?(:client_secret)
163
+ self.scope = options[:scope] if options.has_key?(:scope)
164
+ self.state = options[:state] if options.has_key?(:state)
165
+ self.code = options[:code] if options.has_key?(:code)
166
+ self.redirect_uri = options[:redirect_uri] if options.has_key?(:redirect_uri)
167
+ self.username = options[:username] if options.has_key?(:username)
168
+ self.password = options[:password] if options.has_key?(:password)
169
+ self.issuer = options[:issuer] if options.has_key?(:issuer)
170
+ self.person = options[:person] if options.has_key?(:person)
171
+ self.sub = options[:sub] if options.has_key?(:sub)
172
+ self.expiry = options[:expiry] || 60
173
+ self.audience = options[:audience] if options.has_key?(:audience)
174
+ self.signing_key = options[:signing_key] if options.has_key?(:signing_key)
175
+ self.extension_parameters = options[:extension_parameters] || {}
176
+ self.additional_parameters = options[:additional_parameters] || {}
176
177
  self.update_token!(options)
177
178
  return self
178
179
  end
@@ -206,19 +207,20 @@ module Signet
206
207
  # @see Signet::OAuth2::Client#initialize
207
208
  # @see Signet::OAuth2::Client#update!
208
209
  def update_token!(options={})
209
- # Normalize key to String to allow indifferent access.
210
- options = options.inject({}) { |accu, (k, v)| accu[k.to_s] = v; accu }
210
+ # Normalize all keys to symbols to allow indifferent access internally
211
+ options = deep_hash_normalize(options)
211
212
 
212
- self.expires_in = options["expires_in"] if options.has_key?("expires_in")
213
- self.expires_at = options["expires_at"] if options.has_key?("expires_at")
213
+ self.expires_in = options[:expires] if options.has_key?(:expires)
214
+ self.expires_in = options[:expires_in] if options.has_key?(:expires_in)
215
+ self.expires_at = options[:expires_at] if options.has_key?(:expires_at)
214
216
 
215
217
  # By default, the token is issued at `Time.now` when `expires_in` is
216
218
  # set, but this can be used to supply a more precise time.
217
- self.issued_at = options["issued_at"] if options.has_key?("issued_at")
219
+ self.issued_at = options[:issued_at] if options.has_key?(:issued_at)
218
220
 
219
- self.access_token = options["access_token"] if options.has_key?("access_token")
220
- self.refresh_token = options["refresh_token"] if options.has_key?("refresh_token")
221
- self.id_token = options["id_token"] if options.has_key?("id_token")
221
+ self.access_token = options[:access_token] if options.has_key?(:access_token)
222
+ self.refresh_token = options[:refresh_token] if options.has_key?(:refresh_token)
223
+ self.id_token = options[:id_token] if options.has_key?(:id_token)
222
224
 
223
225
  return self
224
226
  end
@@ -230,6 +232,9 @@ module Signet
230
232
  #
231
233
  # @see Signet::OAuth2.generate_authorization_uri
232
234
  def authorization_uri(options={})
235
+ # Normalize external input
236
+ options = deep_hash_normalize(options)
237
+
233
238
  return nil if @authorization_uri == nil
234
239
  unless options[:response_type]
235
240
  options[:response_type] = :code
@@ -272,15 +277,7 @@ module Signet
272
277
  # @param [Addressable::URI, Hash, String, #to_str] new_authorization_uri
273
278
  # The authorization URI.
274
279
  def authorization_uri=(new_authorization_uri)
275
- if new_authorization_uri != nil
276
- new_authorization_uri = Addressable::URI.send(
277
- new_authorization_uri.kind_of?(Hash) ? :new : :parse,
278
- new_authorization_uri
279
- )
280
- @authorization_uri = new_authorization_uri
281
- else
282
- @authorization_uri = nil
283
- end
280
+ @authorization_uri = coerce_uri(new_authorization_uri)
284
281
  end
285
282
 
286
283
  ##
@@ -297,14 +294,16 @@ module Signet
297
294
  # @param [Addressable::URI, Hash, String, #to_str] new_token_credential_uri
298
295
  # The token credential URI.
299
296
  def token_credential_uri=(new_token_credential_uri)
300
- if new_token_credential_uri != nil
301
- new_token_credential_uri = Addressable::URI.send(
302
- new_token_credential_uri.kind_of?(Hash) ? :new : :parse,
303
- new_token_credential_uri
304
- )
305
- @token_credential_uri = new_token_credential_uri
306
- else
307
- @token_credential_uri = nil
297
+ @token_credential_uri = coerce_uri(new_token_credential_uri)
298
+ end
299
+
300
+ # Addressable expects URIs formatted as hashes to come in with symbols as keys.
301
+ # Returns nil implicitly for the nil case.
302
+ def coerce_uri(incoming_uri)
303
+ if incoming_uri.is_a? Hash
304
+ Addressable::URI.new(deep_hash_normalize(incoming_uri))
305
+ elsif incoming_uri
306
+ Addressable::URI.parse(incoming_uri)
308
307
  end
309
308
  end
310
309
 
@@ -692,14 +691,14 @@ module Signet
692
691
  #
693
692
  # @return [String] The decoded ID token.
694
693
  def decoded_id_token(public_key=nil)
695
- decoded = JWT.decode(self.id_token, public_key, !!public_key)
696
- if !decoded.has_key?('aud')
694
+ payload, header = JWT.decode(self.id_token, public_key, !!public_key)
695
+ if !payload.has_key?('aud')
697
696
  raise Signet::UnsafeOperationError, 'No ID token audience declared.'
698
- elsif decoded['aud'] != self.client_id
697
+ elsif payload['aud'] != self.client_id
699
698
  raise Signet::UnsafeOperationError,
700
699
  'ID token audience did not match Client ID.'
701
700
  end
702
- return decoded
701
+ return payload
703
702
  end
704
703
 
705
704
  ##
@@ -827,6 +826,8 @@ module Signet
827
826
  end
828
827
 
829
828
  def to_jwt(options={})
829
+ options = deep_hash_normalize(options)
830
+
830
831
  now = Time.new
831
832
  skew = options[:skew] || 60
832
833
  assertion = {
@@ -881,6 +882,8 @@ module Signet
881
882
  #
882
883
  # @return [Array] The request object.
883
884
  def generate_access_token_request(options={})
885
+ options = deep_hash_normalize(options)
886
+
884
887
  if self.token_credential_uri == nil
885
888
  raise ArgumentError, 'Missing token endpoint URI.'
886
889
  end
@@ -926,13 +929,16 @@ module Signet
926
929
  end
927
930
 
928
931
  def fetch_access_token(options={})
932
+ options = deep_hash_normalize(options)
933
+
929
934
  options[:connection] ||= Faraday.default_connection
930
935
  request = self.generate_access_token_request(options)
931
936
  request_env = request.to_env(options[:connection])
932
937
  request_env[:request] ||= request
933
938
  response = options[:connection].app.call(request_env)
934
939
  if response.status.to_i == 200
935
- return ::Signet::OAuth2.parse_json_credentials(response.body)
940
+ content_type = response.headers['content-type']
941
+ return ::Signet::OAuth2.parse_credentials(response.body, content_type)
936
942
  elsif [400, 401, 403].include?(response.status.to_i)
937
943
  message = 'Authorization failed.'
938
944
  if response.body.to_s.strip.length > 0
@@ -953,6 +959,8 @@ module Signet
953
959
  end
954
960
 
955
961
  def fetch_access_token!(options={})
962
+ options = deep_hash_normalize(options)
963
+
956
964
  token_hash = self.fetch_access_token(options)
957
965
  if token_hash
958
966
  # No-op for grant types other than `authorization_code`.
@@ -968,6 +976,8 @@ module Signet
968
976
  ##
969
977
  # Refresh the access token, if possible
970
978
  def refresh!(options={})
979
+ options = deep_hash_normalize(options)
980
+
971
981
  self.fetch_access_token!(options)
972
982
  end
973
983
 
@@ -993,6 +1003,8 @@ module Signet
993
1003
  #
994
1004
  # @return [Faraday::Request] The request object.
995
1005
  def generate_authenticated_request(options={})
1006
+ options = deep_hash_normalize(options)
1007
+
996
1008
  if self.access_token == nil
997
1009
  raise ArgumentError, 'Missing access token.'
998
1010
  end
@@ -1081,6 +1093,8 @@ module Signet
1081
1093
  #
1082
1094
  # @return [Array] The response object.
1083
1095
  def fetch_protected_resource(options={})
1096
+ options = deep_hash_normalize(options)
1097
+
1084
1098
  options[:connection] ||= Faraday.default_connection
1085
1099
  request = self.generate_authenticated_request(options)
1086
1100
  request_env = request.to_env(options[:connection])
@@ -1116,7 +1130,25 @@ module Signet
1116
1130
  def uri_is_oob?(uri)
1117
1131
  return uri.to_s == 'urn:ietf:wg:oauth:2.0:oob' || uri.to_s == 'oob'
1118
1132
  end
1133
+
1134
+ # Convert all keys in this hash (nested) to symbols for uniform retrieval
1135
+ def recursive_hash_normalize_keys(val)
1136
+ if val.is_a? Hash
1137
+ deep_hash_normalize(val)
1138
+ else
1139
+ val
1140
+ end
1141
+ end
1142
+
1143
+ def deep_hash_normalize(old_hash)
1144
+ old_hash.inject(formatted_hash={}) do |formatted_hash,(k,v)|
1119
1145
 
1146
+ formatted_hash[k.to_sym] = recursive_hash_normalize_keys(v)
1147
+ formatted_hash
1148
+ end
1149
+
1150
+ formatted_hash
1151
+ end
1120
1152
  end
1121
1153
  end
1122
1154
  end
@@ -74,11 +74,18 @@ module Signet #:nodoc:
74
74
  return Signet.parse_auth_param_list(challenge_string)
75
75
  end
76
76
 
77
- def self.parse_json_credentials(body)
77
+ def self.parse_credentials(body, content_type)
78
78
  if !body.kind_of?(String)
79
79
  raise TypeError, "Expected String, got #{body.class}."
80
80
  end
81
- return MultiJson.load(body)
81
+ case content_type
82
+ when /^application\/json.*/
83
+ return MultiJson.load(body)
84
+ when /^application\/x-www-form-urlencoded.*/
85
+ return Hash[Addressable::URI.form_unencode(body)]
86
+ else
87
+ raise ArgumentError, "Invalid content type '#{content_type}'"
88
+ end
82
89
  end
83
90
 
84
91
  ##
@@ -17,8 +17,8 @@ unless defined? Signet::VERSION
17
17
  module Signet
18
18
  module VERSION
19
19
  MAJOR = 0
20
- MINOR = 5
21
- TINY = 1
20
+ MINOR = 6
21
+ TINY = 0
22
22
 
23
23
  STRING = [MAJOR, MINOR, TINY].join('.')
24
24
  end
data/signet.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: signet 0.5.1 ruby lib
3
+ require File.join(File.dirname(__FILE__), 'lib/signet', 'version')
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "signet"
7
+ s.version = Signet::VERSION::STRING
8
+
9
+ s.required_rubygems_version = ">= 1.3.5"
10
+ s.require_paths = ["lib"]
11
+ s.authors = ["Bob Aman", "Steven Bazyl"]
12
+ s.license = "Apache-2.0"
13
+ s.description = "Signet is an OAuth 1.0 / OAuth 2.0 implementation.\n"
14
+ s.email = "sbazyl@google.com"
15
+ s.extra_rdoc_files = ["README.md"]
16
+ s.files = %w(signet.gemspec Rakefile LICENSE CHANGELOG.md README.md Gemfile)
17
+ s.files += Dir.glob("lib/**/*.rb")
18
+ s.files += Dir.glob("spec/**/*.{rb,opts}")
19
+ s.files += Dir.glob("vendor/**/*.rb")
20
+ s.files += Dir.glob("tasks/**/*")
21
+ s.files += Dir.glob("website/**/*")
22
+ s.homepage = "https://github.com/google/signet/"
23
+ s.rdoc_options = ["--main", "README.md"]
24
+ s.summary = "Signet is an OAuth 1.0 / OAuth 2.0 implementation."
25
+
26
+ s.add_runtime_dependency 'addressable', '~> 2.3'
27
+ s.add_runtime_dependency 'faraday', '~> 0.9'
28
+ s.add_runtime_dependency 'multi_json', '~> 1.10'
29
+ s.add_runtime_dependency 'jwt', '~> 1.0'
30
+ s.add_runtime_dependency 'extlib', '~> 0.9'
31
+
32
+ s.add_development_dependency 'rake', '~> 10.0'
33
+ s.add_development_dependency 'yard', '~> 0.8'
34
+ s.add_development_dependency 'rspec', '~> 3.1'
35
+ s.add_development_dependency 'launchy', '~> 2.4'
36
+ s.add_development_dependency 'kramdown', '~> 1.5'
37
+ s.add_development_dependency 'simplecov', '~> 0.9'
38
+ end