Skip to content

Commit 39a86c0

Browse files
committed
Adds support for provider-uri
1 parent 541f533 commit 39a86c0

File tree

3 files changed

+42
-30
lines changed

3 files changed

+42
-30
lines changed

app/domain/authentication/authn_jwt/v2/strategy.rb

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ def initialize(
1212
jwt: JWT,
1313
http: Net::HTTP, # check that this is needed
1414
json: JSON,
15-
cache: Rails.cache
15+
cache: Rails.cache,
16+
oidc_discovery_configuration: ::OpenIDConnect::Discovery::Provider::Config
1617
)
1718
@authenticator = authenticator
1819
@logger = logger
@@ -21,6 +22,7 @@ def initialize(
2122
@json = json
2223
@http = http
2324
@cache = cache
25+
@oidc_discovery_configuration = oidc_discovery_configuration
2426
end
2527

2628
def callback(parameters:, request_body:)
@@ -53,14 +55,32 @@ def callback(parameters:, request_body:)
5355
hash[:aud] = @authenticator.audience
5456
hash[:verify_aud] = true
5557
end
56-
hash[:jwks] = jwk_loader
58+
hash[:jwks] = jwk_loader(@authenticator.jwks_uri)
5759
elsif @authenticator.public_keys.present?
5860
hash[:iss] = @authenticator.issuer
5961
hash[:verify_iss] = true
6062
# Looks like loading from the public key is really just injesting
6163
# a JWKS endpoint from a local source.
6264
keys = @json.parse(@authenticator.public_keys)&.deep_symbolize_keys
6365
hash[:jwks] = keys[:value]
66+
elsif @authenticator.provider_uri.present?
67+
begin
68+
if @authenticator.issuer.present?
69+
hash[:iss] = @authenticator.issuer
70+
hash[:verify_iss] = true
71+
end
72+
if @authenticator.audience.present?
73+
hash[:aud] = @authenticator.audience
74+
hash[:verify_aud] = true
75+
end
76+
hash[:jwks] = jwk_loader(
77+
@oidc_discovery_configuration.discover!(
78+
@authenticator.provider_uri
79+
)&.jwks_uri
80+
)
81+
rescue Exception => e
82+
raise Errors::Authentication::OAuth::ProviderDiscoveryFailed.new(@authenticator.provider_uri, e.inspect)
83+
end
6484
else
6585
raise Errors::Authentication::AuthnJwt::InvalidSigningKeySettings,
6686
'Failed to find a JWT decode option. Either `jwks-uri` or `public-keys` variable must be set.'
@@ -92,9 +112,9 @@ def callback(parameters:, request_body:)
92112
# Looks like only the "malformed JWT" decode error has a unique custom exception
93113
if e.message == 'Not enough or too many segments'
94114
raise Errors::Authentication::Jwt::RequestBodyMissingJWTToken
95-
else
96-
raise Errors::Authentication::Jwt::TokenDecodeFailed, e.inspect
97115
end
116+
117+
raise Errors::Authentication::Jwt::TokenDecodeFailed, e.inspect
98118
rescue => e
99119
raise Errors::Authentication::Jwt::TokenVerificationFailed, e.inspect
100120
end
@@ -115,14 +135,14 @@ def callback(parameters:, request_body:)
115135

116136
private
117137

118-
def jwk_loader
138+
def jwk_loader(jwks_url)
119139
->(options) do
120-
jwks(force: options[:invalidate]) || {}
140+
jwks(jwks_url: jwks_url, force: options[:invalidate]) || {}
121141
end
122142
end
123143

124-
def fetch_jwks
125-
uri = URI(@authenticator.jwks_uri)
144+
def fetch_jwks(url)
145+
uri = URI(url)
126146
http = @http.new(uri.host, uri.port)
127147
if uri.instance_of?(URI::HTTPS)
128148
# Enable SSL support
@@ -140,11 +160,13 @@ def fetch_jwks
140160
http.cert_store = store
141161
end
142162

163+
# If path is an empty string, the get request will fail. We set it default to a slash.
164+
path = uri.path.empty? ? '/' : uri.path
143165
begin
144-
response = http.request(@http::Get.new(uri.path))
166+
response = http.request(@http::Get.new(path))
145167
rescue Exception => e
146168
raise Errors::Authentication::AuthnJwt::FetchJwksKeysFailed.new(
147-
@authenticator.jwks_uri,
169+
url,
148170
e.inspect
149171
)
150172
end
@@ -154,14 +176,14 @@ def fetch_jwks
154176
@json.parse(response.body)
155177
end
156178

157-
def jwks(force: false)
179+
def jwks(jwks_url:, force: false)
158180
# TODO: Need a mechanism to allow us to expire cache from Cucumber tests
159181
# so that we can include tests with different JWKS certificates.
160182
#
161183
# @cache.fetch(@cache_key, force: force, skip_nil: true) do
162-
# fetch_jwks
184+
# fetch_jwks(jwks_url)
163185
# end&.deep_symbolize_keys
164-
fetch_jwks&.deep_symbolize_keys
186+
fetch_jwks(jwks_url)&.deep_symbolize_keys
165187
end
166188
end
167189
end

app/domain/authentication/handler/authentication_handler.rb

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def call(request_ip:, parameters: nil, request_body: nil, action: nil)
6565
)
6666
end
6767

68-
# binding.pry
6968
begin
7069
role = @identity_resolver.new(authenticator: authenticator).call(
7170
identifier: @strategy.new(
@@ -115,24 +114,16 @@ def call(request_ip:, parameters: nil, request_body: nil, action: nil)
115114

116115
TokenFactory.new.signed_token(
117116
account: parameters[:account],
118-
username: role.login, # role.role_id.split(':').last,
117+
username: role.login,
119118
user_ttl: authenticator.token_ttl
120119
)
121120
rescue => e
122-
# binding.pry
123-
# log_audit_failure(
124-
# authn_params: authenticator_input,
125-
# audit_event_class: Audit::Event::Authn::Authenticate,
126-
# error: e
127-
# )
128-
129121
log_audit_failure(authenticator, role&.role_id, request_ip, @authenticator_type, e)
130122
handle_error(e)
131123
end
132124

133125
def handle_error(err)
134126
@logger.info("#{err.class.name}: #{err.message}")
135-
# binding.pry
136127
err.backtrace.each {|l| @logger.info(l) }
137128

138129
case err
@@ -183,7 +174,6 @@ def log_audit_success(service, role_id, client_ip, type)
183174
end
184175

185176
def log_audit_failure(service, role_id, client_ip, type, error)
186-
# binding.pry
187177
@audit_logger.log(
188178
::Audit::Event::Authn::Authenticate.new(
189179
authenticator_name: type,

cucumber/authenticators_jwt/features/authn_jwt_fetch_signing_key.feature

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Feature: JWT Authenticator - Fetch signing key
6363
When I authenticate via authn-jwt with the ID token
6464
Then host "alice" has been authorized by Conjur
6565

66-
@negative @acceptance @skip
66+
@negative @acceptance
6767
Scenario: ONYX-8704: provider uri configured with bad value
6868
Given I load a policy:
6969
"""
@@ -265,7 +265,7 @@ Feature: JWT Authenticator - Fetch signing key
265265
cucumber:host:alice successfully authenticated with authenticator authn-jwt service cucumber:webservice:conjur/authn-jwt/keycloak
266266
"""
267267

268-
@acceptance @skip
268+
@acceptance
269269
Scenario: jwks uri configured dynamically changed to provider uri
270270
Given I load a policy:
271271
"""
@@ -364,7 +364,7 @@ Feature: JWT Authenticator - Fetch signing key
364364
And I authenticate via authn-jwt with the ID token
365365
Then host "alice" has been authorized by Conjur
366366

367-
@sanity @acceptance @skip
367+
@sanity @acceptance
368368
Scenario: ONYX-8709: provider-uri dynamically changed, 502 ERROR resolves to 200 OK
369369
Given I load a policy:
370370
"""
@@ -607,7 +607,7 @@ Feature: JWT Authenticator - Fetch signing key
607607
CONJ00035E Failed to decode token (3rdPartyError ='#<JWT::VerificationError: Signature verification raised>')
608608
"""
609609

610-
@negative @acceptance @skip
610+
@negative @acceptance
611611
Scenario: ONYX-8914: provider-uri with untrusted self sign certificate
612612
Given I load a policy:
613613
"""
@@ -632,7 +632,7 @@ Feature: JWT Authenticator - Fetch signing key
632632
CONJ00011E Failed to discover Identity Provider (Provider URI: 'https://jwks'). Reason: '#<OpenIDConnect::Discovery::DiscoveryFailed: SSL_connect returned=1 errno=0 state=error: certificate verify failed (self signed certificate)>
633633
"""
634634

635-
@negative @acceptance @skip
635+
@negative @acceptance
636636
Scenario: ONYX-8913: jwks-uri with untrusted self sign certificate
637637
Given I load a policy:
638638
"""
@@ -728,7 +728,7 @@ Feature: JWT Authenticator - Fetch signing key
728728
CONJ00035E Failed to decode token (3rdPartyError ='#<JWT::DecodeError: No key id (kid) found from token headers>')
729729
"""
730730

731-
@sanity @smoke @skip
731+
@sanity @smoke
732732
Scenario: ONYX-15322: public-keys happy path
733733
Given I load a policy:
734734
"""

0 commit comments

Comments
 (0)