cf-uaa-lib 3.6.0 → 3.14.3

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: cbf0e4c510eb02fb7e828ffbe7f227c10fdc9e45
4
- data.tar.gz: e5718846645aabe80e2ab0e4bb581e2146110ed4
3
+ metadata.gz: 903c34141ef900eafea69aa67eac6e998ff8ed4d
4
+ data.tar.gz: e994669699594790f50be50a10d7c8a1b1c38dc7
5
5
  SHA512:
6
- metadata.gz: 08568f7f4c4763e269e39e52768c3d738a1c3df347b7d911e63fa48158ccfdc81c53d8c69cdc2b78f19a3fab3c82b5f7f12f42ab8a5f84c3c013e3e3270d5d10
7
- data.tar.gz: 72cc5995de5569c12f5e8a0b3a88890bef8df65b424fbccd038ec0d9c673ffaa62291f0ba39cc064b7a43f52f2c21588fd74c2a5784640b7d7514529cbcfe81a
6
+ metadata.gz: a8c4455646d340f50b5338481bf51f8d00daf6bf8bcce5c189761bb7f43f3b5c44a93e925266632b04aed9cdd0abc6a04df53110805ab94942410e503b68a49d
7
+ data.tar.gz: 98340c72c9201bea70d77f1dd3df5fc0a7f5ca2138e0534107cdda121dd26b6f512b127ed6c628ae10e02e1257e91c0027973390c83a132c5d0de746608c7877
data/.travis.yml CHANGED
@@ -5,7 +5,6 @@ before_install:
5
5
  - gem install bundler
6
6
 
7
7
  rvm:
8
- - 1.9.3
9
-
10
-
11
-
8
+ - 2.2.7
9
+ - 2.3.4
10
+ - 2.4.1
data/NOTICE ADDED
@@ -0,0 +1,12 @@
1
+
2
+ Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved.
3
+
4
+ This project contains software that is Copyright (c) 2012-2015 Pivotal Software, Inc.
5
+
6
+ This project is licensed to you under the Apache License, Version 2.0 (the "License").
7
+
8
+ You may not use this project except in compliance with the License.
9
+
10
+ This project may include a number of subcomponents with separate copyright notices
11
+ and license terms. Your use of these subcomponents is subject to the terms and
12
+ conditions of the subcomponent's license, as noted in the LICENSE file.
data/README.md CHANGED
@@ -23,7 +23,7 @@ For documentation see: https://rubygems.org/gems/cf-uaa-lib
23
23
  token_issuer = CF::UAA::TokenIssuer.new("https://uaa.cloudfoundry.com", "vmc")
24
24
  puts token_issuer.prompts.inspect
25
25
  token = token_issuer.implicit_grant_with_creds(username: "<your_username>", password: "<your_password>")
26
- token_info = TokenCoder.decode(token.info["access_token"], nil, nil, false) #token signature not verified
26
+ token_info = CF::UAA::TokenCoder.decode(token.info["access_token"], nil, nil, false) #token signature not verified
27
27
  puts token_info["user_name"]
28
28
 
29
29
  ## Tests
data/cf-uaa-lib.gemspec CHANGED
@@ -16,31 +16,32 @@ $:.push File.expand_path("../lib", __FILE__)
16
16
  require "uaa/version"
17
17
 
18
18
  Gem::Specification.new do |s|
19
- s.name = "cf-uaa-lib"
19
+ s.name = 'cf-uaa-lib'
20
20
  s.version = CF::UAA::VERSION
21
- s.authors = ["Dave Syer", "Dale Olds", "Joel D'sa", "Vidya Valmikinathan", "Luke Taylor"]
22
- s.email = ["dsyer@vmware.com", "olds@vmware.com", "jdsa@vmware.com", "vidya@vmware.com", "ltaylor@vmware.com"]
23
- s.homepage = "https://github.com/cloudfoundry/cf-uaa-lib"
21
+ s.authors = ['Dave Syer', 'Dale Olds', 'Joel D\'sa', 'Vidya Valmikinathan', 'Luke Taylor']
22
+ s.email = ['dsyer@vmware.com', 'olds@vmware.com', 'jdsa@vmware.com', 'vidya@vmware.com', 'ltaylor@vmware.com']
23
+ s.homepage = 'https://github.com/cloudfoundry/cf-uaa-lib'
24
24
  s.summary = %q{Client library for CloudFoundry UAA}
25
25
  s.description = %q{Client library for interacting with the CloudFoundry User Account and Authorization (UAA) server. The UAA is an OAuth2 Authorization Server so it can be used by webapps and command line apps to obtain access tokens to act on behalf of users. The tokens can then be used to access protected resources in a Resource Server. This library is for use by UAA client applications or resource servers.}
26
26
 
27
27
  s.rubyforge_project = "cf-uaa-lib"
28
28
 
29
- s.license = "Apache 2.0"
29
+ s.license = "Apache-2.0"
30
30
  s.files = `git ls-files`.split("\n")
31
31
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
33
- s.require_paths = ["lib"]
32
+ s.executables = `git ls-files -- bin/*`.split('\n').map{ |f| File.basename(f) }
33
+ s.require_paths = ['lib']
34
34
 
35
35
  # dependencies
36
- s.add_dependency "multi_json"
36
+ s.add_dependency 'multi_json', '~> 1.12.0', '>= 1.12.1'
37
+ s.add_dependency 'httpclient', '~> 2.8', '>= 2.8.2.4'
37
38
 
38
- s.add_development_dependency "bundler"
39
- s.add_development_dependency "rake", "~> 10.3.2"
40
- s.add_development_dependency "rspec", "~> 2.14.1"
41
- s.add_development_dependency "simplecov", "~> 0.8.2"
42
- s.add_development_dependency "simplecov-rcov", "~> 0.2.3"
43
- s.add_development_dependency "ci_reporter", "~> 1.9.2"
44
- s.add_development_dependency "json_pure", "~> 1.8.1"
39
+ s.add_development_dependency 'bundler', '~> 1.14'
40
+ s.add_development_dependency 'rake', '~> 10.3', '>= 10.3.2'
41
+ s.add_development_dependency 'rspec', '~> 2.14', '>= 2.14.1'
42
+ s.add_development_dependency 'simplecov', '~> 0.8.2'
43
+ s.add_development_dependency 'simplecov-rcov', '~> 0.2.3'
44
+ s.add_development_dependency 'ci_reporter', '~> 1.9', '>= 1.9.2'
45
+ s.add_development_dependency 'json_pure', '~> 1.8', '>= 1.8.1'
45
46
 
46
47
  end
data/lib/uaa/http.rb CHANGED
@@ -12,9 +12,8 @@
12
12
  #++
13
13
 
14
14
  require 'base64'
15
- require 'net/http'
16
15
  require 'uaa/util'
17
- require 'uaa/proxy_options'
16
+ require 'httpclient'
18
17
 
19
18
  module CF::UAA
20
19
 
@@ -46,14 +45,20 @@ class InvalidToken < TargetError; end
46
45
 
47
46
  # Utility accessors and methods for objects that want to access JSON web APIs.
48
47
  module Http
49
- include ProxyOptions
50
48
 
51
49
  def self.included(base)
52
50
  base.class_eval do
53
- attr_accessor :http_proxy, :https_proxy, :skip_ssl_validation, :ssl_ca_file, :ssl_cert_store, :zone
51
+ attr_reader :skip_ssl_validation, :ssl_ca_file, :ssl_cert_store, :http_timeout
54
52
  end
55
53
  end
56
54
 
55
+ def initialize_http_options(options)
56
+ @skip_ssl_validation = options[:skip_ssl_validation]
57
+ @ssl_ca_file = options[:ssl_ca_file]
58
+ @ssl_cert_store = options[:ssl_cert_store]
59
+ @http_timeout = options[:http_timeout]
60
+ end
61
+
57
62
  # Sets the current logger instance to recieve error messages.
58
63
  # @param [Logger] logr
59
64
  # @return [Logger]
@@ -78,30 +83,30 @@ module Http
78
83
  # @return [String]
79
84
  def self.basic_auth(name, password)
80
85
  str = "#{name}:#{password}"
81
- "Basic " + (Base64.respond_to?(:strict_encode64)?
82
- Base64.strict_encode64(str): [str].pack("m").gsub(/\n/, ''))
86
+ 'Basic ' + (Base64.respond_to?(:strict_encode64)?
87
+ Base64.strict_encode64(str): [str].pack('m').gsub(/\n/, ''))
83
88
  end
84
89
 
85
- JSON_UTF8 = "application/json;charset=utf-8"
86
- FORM_UTF8 = "application/x-www-form-urlencoded;charset=utf-8"
90
+ JSON_UTF8 = 'application/json;charset=utf-8'
91
+ FORM_UTF8 = 'application/x-www-form-urlencoded;charset=utf-8'
87
92
 
88
93
  private
89
94
 
90
95
  def json_get(target, path = nil, style = nil, headers = {})
91
96
  raise ArgumentError unless style.nil? || style.is_a?(Symbol)
92
- json_parse_reply(style, *http_get(target, path, headers.merge("accept" => JSON_UTF8)))
97
+ json_parse_reply(style, *http_get(target, path, headers.merge('accept' => JSON_UTF8)))
93
98
  end
94
99
 
95
100
  def json_post(target, path, body, headers = {})
96
- http_post(target, path, Util.json(body), headers.merge("content-type" => JSON_UTF8))
101
+ http_post(target, path, Util.json(body), headers.merge('content-type' => JSON_UTF8))
97
102
  end
98
103
 
99
104
  def json_put(target, path, body, headers = {})
100
- http_put(target, path, Util.json(body), headers.merge("content-type" => JSON_UTF8))
105
+ http_put(target, path, Util.json(body), headers.merge('content-type' => JSON_UTF8))
101
106
  end
102
107
 
103
108
  def json_patch(target, path, body, headers = {})
104
- http_patch(target, path, Util.json(body), headers.merge("content-type" => JSON_UTF8))
109
+ http_patch(target, path, Util.json(body), headers.merge('content-type' => JSON_UTF8))
105
110
  end
106
111
 
107
112
  def json_parse_reply(style, status, body, headers)
@@ -110,17 +115,17 @@ module Http
110
115
  raise (status == 404 ? NotFound : BadResponse), "invalid status response: #{status}"
111
116
  end
112
117
  if body && !body.empty? && (status == 204 || headers.nil? ||
113
- headers["content-type"] !~ /application\/json/i)
114
- raise BadResponse, "received invalid response content or type"
118
+ headers['content-type'] !~ /application\/json/i)
119
+ raise BadResponse, 'received invalid response content or type'
115
120
  end
116
121
  parsed_reply = Util.json_parse(body, style)
117
122
  if status >= 400
118
- raise parsed_reply && parsed_reply["error"] == "invalid_token" ?
119
- InvalidToken.new(parsed_reply) : TargetError.new(parsed_reply), "error response"
123
+ raise parsed_reply && parsed_reply['error'] == 'invalid_token' ?
124
+ InvalidToken.new(parsed_reply) : TargetError.new(parsed_reply), 'error response'
120
125
  end
121
126
  parsed_reply
122
127
  rescue DecodeError
123
- raise BadResponse, "invalid JSON response"
128
+ raise BadResponse, 'invalid JSON response'
124
129
  end
125
130
 
126
131
  def http_get(target, path = nil, headers = {}) request(target, :get, path, nil, headers) end
@@ -129,7 +134,7 @@ module Http
129
134
  def http_patch(target, path, body, headers = {}) request(target, :patch, path, body, headers) end
130
135
 
131
136
  def http_delete(target, path, authorization, zone = nil)
132
- hdrs = { "authorization" => authorization }
137
+ hdrs = { 'authorization' => authorization }
133
138
  hdrs['X-Identity-Zone-Subdomain'] = zone if zone
134
139
  status = request(target, :delete, path, nil, hdrs)[0]
135
140
  unless [200, 204].include?(status)
@@ -138,7 +143,7 @@ module Http
138
143
  end
139
144
 
140
145
  def request(target, method, path, body = nil, headers = {})
141
- headers["accept"] = headers["content-type"] if headers["content-type"] && !headers["accept"]
146
+ headers['accept'] = headers['content-type'] if headers['content-type'] && !headers['accept']
142
147
  url = "#{target}#{path}"
143
148
 
144
149
  logger.debug { "--->\nrequest: #{method} #{url}\n" +
@@ -156,44 +161,59 @@ module Http
156
161
  end
157
162
 
158
163
  def net_http_request(url, method, body, headers)
159
- raise ArgumentError unless reqtype = {:delete => Net::HTTP::Delete,
160
- :get => Net::HTTP::Get, :post => Net::HTTP::Post, :put => Net::HTTP::Put, :patch => Net::HTTP::Patch}[method]
161
- headers["content-length"] = body.length if body
162
164
  uri = URI.parse(url)
163
- req = reqtype.new(uri.request_uri)
164
- headers.each { |k, v| req[k] = v }
165
165
  http = http_request(uri)
166
- reply, outhdrs = http.request(req, body), {}
167
- reply.each_header { |k, v| outhdrs[k] = v }
168
- [reply.code.to_i, reply.body, outhdrs]
166
+ headers['content-length'] = body.length.to_s if body
167
+ case method
168
+ when :get, :delete
169
+ response = http.send(method, uri, nil, headers)
170
+ when :post, :put, :patch
171
+ response = http.send(method, uri, body, headers)
172
+ else
173
+ raise ArgumentError
174
+ end
169
175
 
176
+ unless response.status
177
+ raise HTTPException.new "Can't parse response from the server #{response.content}"
178
+ end
179
+ response_headers = {}
180
+ response.header.all.each { |k, v| response_headers[k.downcase] = v }
181
+ return [response.status.to_i, response.content, response_headers]
170
182
  rescue OpenSSL::SSL::SSLError => e
171
183
  raise SSLException, "Invalid SSL Cert for #{url}. Use '--skip-ssl-validation' to continue with an insecure target"
172
184
  rescue URI::Error, SocketError, SystemCallError => e
173
185
  raise BadTarget, "error: #{e.message}"
174
- rescue Net::HTTPBadResponse => e
175
- raise HTTPException, "HTTP exception: #{e.class}: #{e}"
186
+ rescue HTTPClient::ConnectTimeoutError => e
187
+ raise HTTPException.new "http timeout"
176
188
  end
177
189
 
178
190
  def http_request(uri)
179
- cache_key = URI.join(uri.to_s, "/")
191
+ cache_key = URI.join(uri.to_s, '/')
180
192
  @http_cache ||= {}
181
193
  return @http_cache[cache_key] if @http_cache[cache_key]
182
194
 
183
- http = Net::HTTP.new(uri.host, uri.port, *proxy_options_for(uri))
184
-
185
195
  if uri.is_a?(URI::HTTPS)
186
- http.use_ssl = true
187
-
188
- if skip_ssl_validation
189
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
190
- elsif ssl_ca_file
191
- http.ca_file = File.expand_path(ssl_ca_file)
192
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
193
- elsif ssl_cert_store
194
- http.cert_store = ssl_cert_store
195
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
196
+ http = HTTPClient.new.tap do |c|
197
+ if skip_ssl_validation
198
+ c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
199
+ elsif ssl_ca_file
200
+ c.ssl_config.set_trust_ca File.expand_path(ssl_ca_file)
201
+ c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
202
+ elsif ssl_cert_store
203
+ c.ssl_config.cert_store = ssl_cert_store
204
+ c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
205
+ else
206
+ c.ssl_config.set_default_paths
207
+ end
196
208
  end
209
+ else
210
+ http = HTTPClient.new
211
+ end
212
+
213
+ if http_timeout
214
+ http.connect_timeout = http_timeout
215
+ http.send_timeout = http_timeout
216
+ http.receive_timeout = http_timeout
197
217
  end
198
218
 
199
219
  @http_cache[cache_key] = http
data/lib/uaa/info.rb CHANGED
@@ -31,12 +31,8 @@ class Info
31
31
  # string keys are returned.
32
32
  def initialize(target, options = {})
33
33
  self.target = target
34
- self.skip_ssl_validation = options[:skip_ssl_validation]
35
- self.ssl_ca_file = options[:ssl_ca_file]
36
- self.ssl_cert_store = options[:ssl_cert_store]
37
34
  self.symbolize_keys = options[:symbolize_keys]
38
- self.http_proxy = options[:http_proxy]
39
- self.https_proxy = options[:https_proxy]
35
+ initialize_http_options(options)
40
36
  end
41
37
 
42
38
  # sets whether the keys in returned hashes should be symbols.
@@ -132,8 +128,11 @@ class Info
132
128
  # @param [String] token_type as retrieved by {TokenIssuer}. See {TokenInfo}.
133
129
  # @return [Hash] contents of the token
134
130
  def decode_token(client_id, client_secret, token, token_type = "bearer", audience_ids = nil)
135
- reply = json_get(target, "/check_token?token_type=#{token_type}&token=#{token}",
136
- key_style, "authorization" => Http.basic_auth(client_id, client_secret))
131
+ reply = json_parse_reply(key_style, *request(target, :post, '/check_token',
132
+ Util.encode_form(:token => token),
133
+ "authorization" => Http.basic_auth(client_id, client_secret),
134
+ "content-type" => Http::FORM_UTF8,"accept" => Http::JSON_UTF8))
135
+
137
136
  auds = Util.arglist(reply[:aud] || reply['aud'])
138
137
  if audience_ids && (!auds || (auds & audience_ids).empty?)
139
138
  raise AuthError, "invalid audience: #{auds.join(' ')}"
data/lib/uaa/scim.rb CHANGED
@@ -42,16 +42,28 @@ class Scim
42
42
 
43
43
  def force_attr(k)
44
44
  kd = k.to_s.downcase
45
- kc = {"username" => "userName", "familyname" => "familyName",
46
- "givenname" => "givenName", "middlename" => "middleName",
47
- "honorificprefix" => "honorificPrefix",
48
- "honorificsuffix" => "honorificSuffix", "displayname" => "displayName",
49
- "nickname" => "nickName", "profileurl" => "profileUrl",
50
- "streetaddress" => "streetAddress", "postalcode" => "postalCode",
51
- "usertype" => "userType", "preferredlanguage" => "preferredLanguage",
52
- "x509certificates" => "x509Certificates", "lastmodified" => "lastModified",
53
- "externalid" => "externalId", "phonenumbers" => "phoneNumbers",
54
- "startindex" => "startIndex"}[kd]
45
+ kc = {
46
+ 'username' => 'userName',
47
+ 'familyname' => 'familyName',
48
+ 'givenname' => 'givenName',
49
+ 'middlename' => 'middleName',
50
+ 'honorificprefix' => 'honorificPrefix',
51
+ 'honorificsuffix' => 'honorificSuffix',
52
+ 'displayname' => 'displayName',
53
+ 'nickname' => 'nickName',
54
+ 'profileurl' => 'profileUrl',
55
+ 'streetaddress' => 'streetAddress',
56
+ 'postalcode' => 'postalCode',
57
+ 'usertype' => 'userType',
58
+ 'preferredlanguage' => 'preferredLanguage',
59
+ 'x509certificates' => 'x509Certificates',
60
+ 'lastmodified' => 'lastModified',
61
+ 'externalid' => 'externalId',
62
+ 'phonenumbers' => 'phoneNumbers',
63
+ 'startindex' => 'startIndex',
64
+ 'zoneid' => 'zoneId',
65
+ 'includeinactive' => 'includeInactive'
66
+ }[kd]
55
67
  kc || kd
56
68
  end
57
69
 
@@ -76,15 +88,46 @@ class Scim
76
88
 
77
89
  # an attempt to hide some scim and uaa oddities
78
90
  def type_info(type, elem)
79
- scimfo = {:user => ["/Users", "userName"], :group => ["/Groups", "displayName"],
80
- :client => ["/oauth/clients", 'client_id'], :user_id => ["/ids/Users", 'userName'], :group_mapping => ["/Groups/External", "externalGroup"]}
81
- unless elem == :path || elem == :name_attr
82
- raise ArgumentError, "scim schema element must be :path or :name_attr"
83
- end
84
- unless ary = scimfo[type]
91
+ scimfo = {
92
+ user: {
93
+ path: '/Users',
94
+ name_attr: 'userName',
95
+ origin_attr: 'origin'
96
+ },
97
+ group: {
98
+ path: '/Groups',
99
+ name_attr: 'displayName',
100
+ origin_attr: 'zoneid'
101
+ },
102
+ client: {
103
+ path: '/oauth/clients',
104
+ name_attr: 'client_id'
105
+ },
106
+ user_id: {
107
+ path: '/ids/Users',
108
+ name_attr: 'userName',
109
+ origin_attr: 'origin',
110
+ },
111
+ group_mapping: {
112
+ path: '/Groups/External',
113
+ name_attr: 'externalGroup',
114
+ origin_attr: 'origin'
115
+ }
116
+ }
117
+
118
+ type_info = scimfo[type]
119
+
120
+ unless type_info
85
121
  raise ArgumentError, "scim resource type must be one of #{scimfo.keys.inspect}"
86
122
  end
87
- ary[elem == :path ? 0 : 1]
123
+
124
+ value = type_info[elem]
125
+
126
+ unless value
127
+ raise ArgumentError, "scim schema element must be one of #{type_info.keys.inspect}"
128
+ end
129
+
130
+ value
88
131
  end
89
132
 
90
133
  def jkey(k) @key_style == :down ? k.to_s : k end
@@ -106,12 +149,8 @@ class Scim
106
149
  def initialize(target, auth_header, options = {})
107
150
  @target, @auth_header = target, auth_header
108
151
  @key_style = options[:symbolize_keys] ? :downsym : :down
109
- self.skip_ssl_validation = options[:skip_ssl_validation]
110
- self.ssl_ca_file = options[:ssl_ca_file]
111
- self.ssl_cert_store = options[:ssl_cert_store]
112
- self.http_proxy = options[:http_proxy]
113
- self.https_proxy = options[:https_proxy]
114
152
  @zone = options[:zone]
153
+ initialize_http_options(options)
115
154
  end
116
155
 
117
156
  # Convenience method to get the naming attribute, e.g. userName for user,
@@ -226,6 +265,14 @@ class Scim
226
265
  info
227
266
  end
228
267
 
268
+ # Get meta information about client
269
+ # @param client_id
270
+ # @return (client meta)
271
+ def get_client_meta(client_id)
272
+ path = type_info(:client, :path)
273
+ json_get(@target, "#{path}/#{URI.encode(client_id)}/meta", @key_style, headers)
274
+ end
275
+
229
276
  # Collects all pages of entries from a query
230
277
  # @param type (see #query)
231
278
  # @param [Hash] query may contain the following keys:
@@ -256,9 +303,16 @@ class Scim
256
303
  # @param type (see #add)
257
304
  # @return [Array] array of name/id hashes for each object found
258
305
  def ids(type, *names)
259
- na = type_info(type, :name_attr)
260
- filter = names.map { |n| "#{na} eq \"#{n}\""}
261
- all_pages(type, :attributes => "id,#{na}", :filter => filter.join(" or "))
306
+ name_attr = type_info(type, :name_attr)
307
+ origin_attr = type_info(type, :origin_attr)
308
+
309
+ filter = names.map do |n|
310
+ "#{name_attr} eq \"#{n}\""
311
+ end
312
+
313
+ attributes = ['id', name_attr, origin_attr]
314
+
315
+ all_pages(type, attributes: attributes.join(','), filter: filter.join(' or '))
262
316
  end
263
317
 
264
318
  # Convenience method to query for single object by name.
@@ -113,7 +113,7 @@ class TokenCoder
113
113
  signature = Util.decode64(crypto_segment)
114
114
  if ["HS256", "HS384", "HS512"].include?(algo)
115
115
  raise InvalidSignature, "Signature verification failed" unless
116
- options[:skey] && signature == OpenSSL::HMAC.digest(init_digest(algo), options[:skey], signing_input)
116
+ options[:skey] && constant_time_compare(signature, OpenSSL::HMAC.digest(init_digest(algo), options[:skey], signing_input))
117
117
  elsif ["RS256", "RS384", "RS512"].include?(algo)
118
118
  raise InvalidSignature, "Signature verification failed" unless
119
119
  options[:pkey] && options[:pkey].verify(init_digest(algo), signature, signing_input)
@@ -123,6 +123,24 @@ class TokenCoder
123
123
  payload
124
124
  end
125
125
 
126
+ # Takes constant time to compare 2 strings (HMAC digests in this case)
127
+ # to avoid timing attacks while comparing the HMAC digests
128
+ # @param [String] a: the first digest to compare
129
+ # @param [String] b: the second digest to compare
130
+ # @return [boolean] true if they are equal, false otherwise
131
+ def self.constant_time_compare(a, b)
132
+ if a.length != b.length
133
+ return false
134
+ end
135
+
136
+ result = 0
137
+ a.chars.zip(b.chars).each do |x, y|
138
+ result |= x.ord ^ y.ord
139
+ end
140
+
141
+ result == 0
142
+ end
143
+
126
144
  # Creates a new token en/decoder for a service that is associated with
127
145
  # the the audience_ids, the symmetrical token validation key, and the
128
146
  # public and/or private keys.
@@ -109,11 +109,7 @@ class TokenIssuer
109
109
  @target, @client_id, @client_secret = target, client_id, client_secret
110
110
  @token_target = options[:token_target] || target
111
111
  @key_style = options[:symbolize_keys] ? :sym : nil
112
- self.skip_ssl_validation = options[:skip_ssl_validation]
113
- self.ssl_ca_file = options[:ssl_ca_file]
114
- self.ssl_cert_store = options[:ssl_cert_store]
115
- self.http_proxy = options[:http_proxy]
116
- self.https_proxy = options[:https_proxy]
112
+ initialize_http_options(options)
117
113
  end
118
114
 
119
115
  # Allows an app to discover what credentials are required for
data/lib/uaa/version.rb CHANGED
@@ -14,6 +14,6 @@
14
14
  # Cloud Foundry namespace
15
15
  module CF
16
16
  module UAA
17
- VERSION = "3.6.0"
17
+ VERSION = '3.14.3'
18
18
  end
19
19
  end