cf-uaa-lib 4.0.9 → 4.0.10
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 +4 -4
- data/.github/workflows/gem-push.yml +1 -1
- data/.github/workflows/ruby.yml +3 -2
- data/cf-uaa-lib.gemspec +3 -1
- data/lib/uaa/http.rb +1 -1
- data/lib/uaa/token_issuer.rb +18 -2
- data/lib/uaa/version.rb +1 -1
- data/spec/scim_spec.rb +3 -3
- data/spec/token_issuer_spec.rb +80 -0
- metadata +20 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 749fd6ab4d2b12f32a72cd0b15a573c051c42c779676c9c4a0f9582a74d13836
|
|
4
|
+
data.tar.gz: acbdddc308c40af517a356ffa492160ca39c5b97c84da512b2be966f184c329c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8f1f81e5eff52915a9cb233b56dc00ead5ff773c4311f76434e516cce33277afa13c3956212686e43e781333451085a259c5fa7a816d2eb6e8c5b439c57e8868
|
|
7
|
+
data.tar.gz: 451e6cb18fdd7226f320bca418a5e243c6c6e9768dafa57063f6236217178d23f775fb72a176dfa7f750469a0e25c7c4524ff7598c2a5f50f0b113aad31b1497
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -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: ['
|
|
16
|
+
ruby-version: ['3.3', '3.4', '4.0']
|
|
16
17
|
|
|
17
18
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
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,6 +25,7 @@ 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) }
|
|
@@ -34,10 +35,11 @@ Gem::Specification.new do |s|
|
|
|
34
35
|
s.add_dependency 'json', '~>2.7'
|
|
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', '
|
|
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
45
|
s.add_development_dependency 'simplecov', '~> 0.22.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
|
|
187
|
+
rescue HTTPClient::ConnectTimeoutError, HTTPClient::ReceiveTimeoutError
|
|
188
188
|
raise HTTPException.new "http timeout"
|
|
189
189
|
end
|
|
190
190
|
|
data/lib/uaa/token_issuer.rb
CHANGED
|
@@ -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
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 =
|
|
301
|
-
start_index = query_params['startIndex']
|
|
302
|
-
count = query_params['count']
|
|
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'
|
data/spec/token_issuer_spec.rb
CHANGED
|
@@ -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.
|
|
4
|
+
version: 4.0.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dave Syer
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
- Luke Taylor
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date:
|
|
14
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: json
|
|
@@ -55,6 +55,20 @@ dependencies:
|
|
|
55
55
|
- - ">="
|
|
56
56
|
- !ruby/object:Gem::Version
|
|
57
57
|
version: '0'
|
|
58
|
+
- !ruby/object:Gem::Dependency
|
|
59
|
+
name: logger
|
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '0'
|
|
65
|
+
type: :runtime
|
|
66
|
+
prerelease: false
|
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0'
|
|
58
72
|
- !ruby/object:Gem::Dependency
|
|
59
73
|
name: httpclient
|
|
60
74
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -99,14 +113,14 @@ dependencies:
|
|
|
99
113
|
name: bundler
|
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
|
101
115
|
requirements:
|
|
102
|
-
- - "
|
|
116
|
+
- - ">="
|
|
103
117
|
- !ruby/object:Gem::Version
|
|
104
118
|
version: '2.2'
|
|
105
119
|
type: :development
|
|
106
120
|
prerelease: false
|
|
107
121
|
version_requirements: !ruby/object:Gem::Requirement
|
|
108
122
|
requirements:
|
|
109
|
-
- - "
|
|
123
|
+
- - ">="
|
|
110
124
|
- !ruby/object:Gem::Version
|
|
111
125
|
version: '2.2'
|
|
112
126
|
- !ruby/object:Gem::Dependency
|
|
@@ -266,14 +280,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
266
280
|
requirements:
|
|
267
281
|
- - ">="
|
|
268
282
|
- !ruby/object:Gem::Version
|
|
269
|
-
version: '
|
|
283
|
+
version: '3.3'
|
|
270
284
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
271
285
|
requirements:
|
|
272
286
|
- - ">="
|
|
273
287
|
- !ruby/object:Gem::Version
|
|
274
288
|
version: '0'
|
|
275
289
|
requirements: []
|
|
276
|
-
rubygems_version:
|
|
290
|
+
rubygems_version: 4.0.10
|
|
277
291
|
specification_version: 4
|
|
278
292
|
summary: Client library for CloudFoundry UAA
|
|
279
293
|
test_files: []
|