cf-uaa-lib 4.0.9 → 4.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1bef252c395d0a9dfbd30cb9b4e60be278d01ae09b496d97d7f8665ff273ba5
4
- data.tar.gz: 0bfd4b2af11ca2261e399bf2c73e4710ba49de67fed16766e22ac110cac19ad9
3
+ metadata.gz: 1c58cae634831cdd1f201b726d1f6ea95155b41cdc4a39731292ca9e4857852e
4
+ data.tar.gz: c48636814742c86d34a2869e9810d5c8d4a1ef13e9319c0686db109dbb742dc9
5
5
  SHA512:
6
- metadata.gz: c7ebce508854b456f17ca0980cbaa10326cc472c81008d0956d5c70401bd671a17a959ab41e6e3d1a4829819985daa9076f4a627c399726249fad9104aa9c787
7
- data.tar.gz: 0d2a4528589995a7e5b9cf4badef1e8612232fdc07fa1af02bc5ee8d7211ad2e94489af2332f2a4e7271ea0d2bb0e8000361d6f8a446596c070618cc7e8974c9
6
+ metadata.gz: 18704cf4ebeba101c2525df2ba5639ef162442f31fa8bc5640324daf8ff28b319074a787eb61ea552a00add0c2c4ce1777ef1d44a0a15f0d310bdb55441e03b0
7
+ data.tar.gz: bb592b860bca147025efa396ae66c4254dc2ff2eddcb16dc75043a3dbef9c1d3c22fe38192be2358c9c2c864b5dab5b6758cd89845948d761fb6111224398512
@@ -13,7 +13,7 @@ jobs:
13
13
 
14
14
  steps:
15
15
  # Set up
16
- - uses: actions/checkout@v4
16
+ - uses: actions/checkout@v7
17
17
  - name: Set up Ruby
18
18
  uses: ruby/setup-ruby@v1
19
19
  with:
@@ -11,11 +11,12 @@ jobs:
11
11
 
12
12
  runs-on: ubuntu-latest
13
13
  strategy:
14
+ fail-fast: false
14
15
  matrix:
15
- ruby-version: ['2.5', '2.7', '3.1', '3.2', '3.3', '3.4']
16
+ ruby-version: ['3.3', '3.4', '4.0']
16
17
 
17
18
  steps:
18
- - uses: actions/checkout@v4
19
+ - uses: actions/checkout@v7
19
20
  - name: Set up Ruby
20
21
  uses: ruby/setup-ruby@v1
21
22
  with:
data/cf-uaa-lib.gemspec CHANGED
@@ -25,22 +25,24 @@ Gem::Specification.new do |s|
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.license = "Apache-2.0"
28
+ s.required_ruby_version = '>= 3.3'
28
29
  s.files = `git ls-files`.split("\n")
29
30
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
31
  s.executables = `git ls-files -- bin/*`.split('\n').map{ |f| File.basename(f) }
31
32
  s.require_paths = ['lib']
32
33
 
33
34
  # dependencies
34
- s.add_dependency 'json', '~>2.7'
35
+ s.add_dependency 'json', '>=2.7', '<4.0'
35
36
  s.add_dependency 'mutex_m'
36
37
  s.add_dependency 'base64'
38
+ s.add_dependency 'logger'
37
39
  s.add_dependency 'httpclient', '~> 2.8', '>= 2.8.2.4'
38
40
  s.add_dependency 'addressable', '~> 2.8', '>= 2.8.0'
39
41
 
40
- s.add_development_dependency 'bundler', '~> 2.2'
42
+ s.add_development_dependency 'bundler', '>= 2.2'
41
43
  s.add_development_dependency 'rake', '>= 10.3.2', '~> 13.0'
42
44
  s.add_development_dependency 'rspec', '>= 2.14.1', '~> 3.9'
43
- s.add_development_dependency 'simplecov', '~> 0.22.0'
45
+ s.add_development_dependency 'simplecov', '~> 1.3.0'
44
46
  s.add_development_dependency 'simplecov-rcov', '~> 0.3.0'
45
47
  s.add_development_dependency 'ci_reporter', '>= 1.9.2', '~> 2.0'
46
48
  s.add_development_dependency 'ci_reporter_rspec', '~> 1.0'
data/lib/uaa/http.rb CHANGED
@@ -184,7 +184,7 @@ module Http
184
184
  raise SSLException, "Invalid SSL Cert for #{url}. Use '--skip-ssl-validation' to continue with an insecure target"
185
185
  rescue URI::Error, SocketError, SystemCallError => e
186
186
  raise BadTarget, "error: #{e.message}"
187
- rescue HTTPClient::ConnectTimeoutError => e
187
+ rescue HTTPClient::ConnectTimeoutError, HTTPClient::ReceiveTimeoutError
188
188
  raise HTTPException.new "http timeout"
189
189
  end
190
190
 
@@ -75,6 +75,8 @@ class TokenIssuer
75
75
  if scope = Util.arglist(params.delete(:scope))
76
76
  params[:scope] = Util.strlist(scope)
77
77
  end
78
+ client_assertion = params[:client_assertion]
79
+ params.delete(:client_assertion)
78
80
  headers = {'content-type' => FORM_UTF8, 'accept' => JSON_UTF8}
79
81
  if @client_auth_method == 'client_secret_basic' && @client_secret && @client_id
80
82
  if @basic_auth
@@ -88,6 +90,10 @@ class TokenIssuer
88
90
  params[:client_secret] = @client_secret
89
91
  elsif @client_id && params[:code_verifier]
90
92
  params[:client_id] = @client_id
93
+ elsif client_assertion && @client_id && @client_secret.nil?
94
+ params[:client_id] = @client_id
95
+ params[:client_assertion] = client_assertion
96
+ params[:client_assertion_type] = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
91
97
  else
92
98
  headers['X-CF-ENCODED-CREDENTIALS'] = 'true'
93
99
  headers['authorization'] = Http.basic_auth(CGI.escape(@client_id || ''), CGI.escape(@client_secret || ''))
@@ -129,6 +135,7 @@ class TokenIssuer
129
135
  # * +:symbolize_keys+, if true, returned hash keys are symbols.
130
136
  def initialize(target, client_id, client_secret = nil, options = {})
131
137
  @target, @client_id, @client_secret = target, client_id, client_secret
138
+ @client_assertion = options[:client_assertion] || nil
132
139
  @token_target = options[:token_target] || target
133
140
  @key_style = options[:symbolize_keys] ? :sym : nil
134
141
  @basic_auth = options[:basic_auth] == true ? true : false
@@ -310,8 +317,8 @@ class TokenIssuer
310
317
  # Uses the instance client credentials to get a token with a client
311
318
  # credentials grant. See http://tools.ietf.org/html/rfc6749#section-4.4
312
319
  # @return [TokenInfo]
313
- def client_credentials_grant(scope = nil)
314
- request_token(grant_type: 'client_credentials', scope: scope)
320
+ def client_credentials_grant(scope = nil, client_assertion = nil)
321
+ request_token(grant_type: 'client_credentials', scope: scope, client_assertion: client_assertion)
315
322
  end
316
323
 
317
324
  # Uses the instance client credentials and the given +refresh_token+ to get
@@ -321,6 +328,15 @@ class TokenIssuer
321
328
  request_token(grant_type: 'refresh_token', refresh_token: refresh_token, scope: scope)
322
329
  end
323
330
 
331
+ # Gets an access token with the user assertion used for authentication
332
+ # via the jwt bearer authorization grant.
333
+ # See {http://tools.ietf.org/html/rfc7523#section-2.1}.
334
+ # @param assertion should be an id_token from a previous IdP token request
335
+ # @return [TokenInfo]
336
+ def jwt_bearer_grant(assertion, scope = nil, client_assertion = nil)
337
+ request_token(grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: assertion, scope: scope, client_assertion: client_assertion)
338
+ end
339
+
324
340
  end
325
341
 
326
342
  end
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 = '4.0.9'
17
+ VERSION = '4.0.11'
18
18
  end
19
19
  end
data/spec/scim_spec.rb CHANGED
@@ -297,9 +297,9 @@ describe Scim do
297
297
  method.should == :get
298
298
  check_headers(headers, nil, :json, nil)
299
299
 
300
- query_params = CGI::parse(URI.parse(url).query)
301
- start_index = query_params['startIndex'].first
302
- count = query_params['count'].first
300
+ query_params = URI.decode_www_form(URI.parse(url).query).to_h
301
+ start_index = query_params['startIndex']
302
+ count = query_params['count']
303
303
 
304
304
  start_index.should == '3'
305
305
  count.should == '10'
@@ -345,6 +345,37 @@ describe TokenIssuer do
345
345
  end
346
346
  end
347
347
 
348
+ context 'with client_assertion using client credentials grant' do
349
+ let(:client_id) { 'test_client' }
350
+ let(:client_secret) { nil }
351
+
352
+ it 'use client_secret_post in authorization code and expect client_id and secret in body' do
353
+ subject.set_request_handler do |url, method, body, headers|
354
+ headers['content-type'].should =~ /application\/x-www-form-urlencoded/
355
+ headers['accept'].should =~ /application\/json/
356
+ headers['X-CF-ENCODED-CREDENTIALS'].should_not
357
+ headers['authorization'].should_not
358
+ params = Util.decode_form(body)
359
+ params['grant_type'].should == 'client_credentials'
360
+ params['client_id'].should == 'test_client'
361
+ params['client_assertion'].should == 'any-jwt-token'
362
+ params['client_assertion_type'].should == 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
363
+ params['client_secret'].should_not
364
+ url.should match 'http://test.uaa.target/oauth/token'
365
+ method.should == :post
366
+ reply = {access_token: 'test_access_token', token_type: 'BEARER',
367
+ scope: 'logs.read', expires_in: 98765}
368
+ [200, Util.json(reply), {'content-type' => 'application/json'}]
369
+ end
370
+ token = subject.client_credentials_grant('logs.read', 'any-jwt-token')
371
+ token.should be_an_instance_of TokenInfo
372
+ token.info['access_token'].should == 'test_access_token'
373
+ token.info['token_type'].should =~ /^bearer$/i
374
+ token.info['scope'].should == 'logs.read'
375
+ token.info['expires_in'].should == 98765
376
+ end
377
+ end
378
+
348
379
  context 'pkce with own code verifier' do
349
380
  let(:options) { {basic_auth: false, code_verifier: 'umoq1e_4XMYXvfHlaO9mSlSI17OKfxnwfR5ZD-oYreFxyn8yQZ-ZHPZfUZ4n3WjY_tkOB_MAisSy4ddqsa6aoTU5ZOcX4ps3de933PczYlC8pZpKL8EQWaDZOnpOyB2W'} }
350
381
 
@@ -439,6 +470,55 @@ describe TokenIssuer do
439
470
  end
440
471
  end
441
472
 
473
+ context 'with jwt bearer grant' do
474
+
475
+ it 'gets a token with jwt bearer' do
476
+ subject.set_request_handler do |url, method, body, headers|
477
+ headers['content-type'].should =~ /application\/x-www-form-urlencoded/
478
+ headers['accept'].should =~ /application\/json/
479
+ headers['X-CF-ENCODED-CREDENTIALS'].should == 'true'
480
+ headers['authorization'].should == 'Basic dGVzdF9jbGllbnQ6dGVzdCUyMXNlY3JldA=='
481
+ url.should == 'http://test.uaa.target/oauth/token'
482
+ method.should == :post
483
+ reply = {access_token: 'test_access_token', token_type: 'BEARER',
484
+ scope: 'openid', expires_in: 98765}
485
+ [200, Util.json(reply), {'content-type' => 'application/json'}]
486
+ end
487
+ token = subject.jwt_bearer_grant('assertion', 'openid')
488
+ token.should be_an_instance_of TokenInfo
489
+ token.info['access_token'].should == 'test_access_token'
490
+ token.info['token_type'].should =~ /^bearer$/i
491
+ token.info['scope'].should == 'openid'
492
+ token.info['expires_in'].should == 98765
493
+ end
494
+
495
+ context "when client & client secret are nil" do
496
+ let(:client_id) { nil }
497
+ let(:client_secret) { nil }
498
+
499
+ it 'does not error' do
500
+ subject.set_request_handler do |url, method, body, headers|
501
+ headers['content-type'].should =~ /application\/x-www-form-urlencoded/
502
+ headers['accept'].should =~ /application\/json/
503
+ headers['X-CF-ENCODED-CREDENTIALS'].should == 'true'
504
+ headers['authorization'].should == 'Basic Og=='
505
+ url.should == 'http://test.uaa.target/oauth/token'
506
+ method.should == :post
507
+ reply = {access_token: 'test_access_token', token_type: 'BEARER',
508
+ scope: 'openid', expires_in: 98765}
509
+ [200, Util.json(reply), {'content-type' => 'application/json'}]
510
+ end
511
+ token = subject.jwt_bearer_grant('assertion', 'openid')
512
+ token.should be_an_instance_of TokenInfo
513
+ token.info['access_token'].should == 'test_access_token'
514
+ token.info['token_type'].should =~ /^bearer$/i
515
+ token.info['scope'].should == 'openid'
516
+ token.info['expires_in'].should == 98765
517
+ end
518
+ end
519
+
520
+ end
521
+
442
522
  end
443
523
 
444
524
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cf-uaa-lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.9
4
+ version: 4.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Syer
@@ -11,22 +11,28 @@ authors:
11
11
  - Luke Taylor
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2025-02-19 00:00:00.000000000 Z
14
+ date: 1980-01-02 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - "~>"
20
+ - - ">="
21
21
  - !ruby/object:Gem::Version
22
22
  version: '2.7'
23
+ - - "<"
24
+ - !ruby/object:Gem::Version
25
+ version: '4.0'
23
26
  type: :runtime
24
27
  prerelease: false
25
28
  version_requirements: !ruby/object:Gem::Requirement
26
29
  requirements:
27
- - - "~>"
30
+ - - ">="
28
31
  - !ruby/object:Gem::Version
29
32
  version: '2.7'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '4.0'
30
36
  - !ruby/object:Gem::Dependency
31
37
  name: mutex_m
32
38
  requirement: !ruby/object:Gem::Requirement
@@ -55,6 +61,20 @@ dependencies:
55
61
  - - ">="
56
62
  - !ruby/object:Gem::Version
57
63
  version: '0'
64
+ - !ruby/object:Gem::Dependency
65
+ name: logger
66
+ requirement: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: httpclient
60
80
  requirement: !ruby/object:Gem::Requirement
@@ -99,14 +119,14 @@ dependencies:
99
119
  name: bundler
100
120
  requirement: !ruby/object:Gem::Requirement
101
121
  requirements:
102
- - - "~>"
122
+ - - ">="
103
123
  - !ruby/object:Gem::Version
104
124
  version: '2.2'
105
125
  type: :development
106
126
  prerelease: false
107
127
  version_requirements: !ruby/object:Gem::Requirement
108
128
  requirements:
109
- - - "~>"
129
+ - - ">="
110
130
  - !ruby/object:Gem::Version
111
131
  version: '2.2'
112
132
  - !ruby/object:Gem::Dependency
@@ -155,14 +175,14 @@ dependencies:
155
175
  requirements:
156
176
  - - "~>"
157
177
  - !ruby/object:Gem::Version
158
- version: 0.22.0
178
+ version: 1.3.0
159
179
  type: :development
160
180
  prerelease: false
161
181
  version_requirements: !ruby/object:Gem::Requirement
162
182
  requirements:
163
183
  - - "~>"
164
184
  - !ruby/object:Gem::Version
165
- version: 0.22.0
185
+ version: 1.3.0
166
186
  - !ruby/object:Gem::Dependency
167
187
  name: simplecov-rcov
168
188
  requirement: !ruby/object:Gem::Requirement
@@ -266,14 +286,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
266
286
  requirements:
267
287
  - - ">="
268
288
  - !ruby/object:Gem::Version
269
- version: '0'
289
+ version: '3.3'
270
290
  required_rubygems_version: !ruby/object:Gem::Requirement
271
291
  requirements:
272
292
  - - ">="
273
293
  - !ruby/object:Gem::Version
274
294
  version: '0'
275
295
  requirements: []
276
- rubygems_version: 3.6.2
296
+ rubygems_version: 4.0.20
277
297
  specification_version: 4
278
298
  summary: Client library for CloudFoundry UAA
279
299
  test_files: []