Skip to content

Commit

Permalink
Merge pull request #747 from abellotti/support_optional_oidc_parameters
Browse files Browse the repository at this point in the history
Adding support for OIDCProviderTokenEndpoint, OIDCOAuthIntrospectionEndpoint and OIDCScope

(cherry picked from commit 7677117)

https://bugzilla.redhat.com/show_bug.cgi?id=1805914
  • Loading branch information
chessbyte authored and simaishi committed Feb 24, 2020
1 parent 5d48298 commit 32158db
Showing 1 changed file with 58 additions and 17 deletions.
75 changes: 58 additions & 17 deletions app/controllers/api/base_controller/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def require_api_user_or_token
begin
timeout = ::Settings.api.authentication_timeout.to_i_with_method

if oidc_configuration?
if !User.admin?(u) && oidc_configuration?
# Basic auth, user/password but configured against OpenIDC.
# Let's authenticate as such and get a JWT for that user.
#
Expand Down Expand Up @@ -200,21 +200,44 @@ def httpd_oidc_config
end

def httpd_oidc_config_param(name)
param_spec = httpd_oidc_config.find { |line| line =~ /#{name} .*/i }
param_spec = httpd_oidc_config.find { |line| line =~ /^#{name} .*/i }
return "" if param_spec.blank?

param_match = param_spec.match(/^#{name} (.*)/i)
param_match ? param_match[1].strip : ""
end

def oidc_provider_metadata
@oidc_provider_metadata ||= begin
oidc_provider_metadata_url = httpd_oidc_config_param("OIDCProviderMetadataURL")
uri = URI.parse(oidc_provider_metadata_url)
http = Net::HTTP.new(uri.host, uri.port)
response = http.request(Net::HTTP::Get.new(uri.request_uri))
JSON.parse(response.body)
if oidc_provider_metadata_url.blank?
{}
else
uri = URI.parse(oidc_provider_metadata_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == "https")
response = http.request(Net::HTTP::Get.new(uri.request_uri))
JSON.parse(response.body)
end
end
end

def oidc_metadata_url_endpoint(oidc_param, metadata_url_key)
endpoint = httpd_oidc_config_param(oidc_param)
endpoint = oidc_provider_metadata[metadata_url_key] if endpoint.blank?
raise AuthenticationError, "Invalid #{HTTPD_OPENIDC_CONF} configuration, missing #{oidc_param} or OIDCProviderMetadataURL #{metadata_url_key} entry" if endpoint.blank?

endpoint
end

def oidc_token_endpoint
@oidc_token_endpoint ||= oidc_metadata_url_endpoint("OIDCProviderTokenEndpoint", "token_endpoint")
end

def oidc_token_introspection_endpoint
@oidc_token_introspection_endpoint ||= oidc_metadata_url_endpoint("OIDCOAuthIntrospectionEndpoint", "token_introspection_endpoint")
end

def oidc_client_id
@oidc_client_id ||= httpd_oidc_config_param("OIDCClientId")
end
Expand All @@ -223,14 +246,25 @@ def oidc_client_secret
@oidc_client_secret ||= httpd_oidc_config_param("OIDCClientSecret")
end

def oidc_scope
@oidc_scope ||= httpd_oidc_config_param("OIDCScope")
end

def get_jwt_token(username, password)
uri = URI.parse(oidc_provider_metadata["token_endpoint"])
response = Net::HTTP.post_form(uri, "grant_type" => "password",
"client_id" => oidc_client_id,
"client_secret" => oidc_client_secret,
"username" => username,
"password" => password)
uri = URI.parse(oidc_token_endpoint)
request_params = {
"grant_type" => "password",
"username" => username,
"password" => password
}
request_params["scope"] = oidc_scope if oidc_scope.present?

request = Net::HTTP::Post.new(uri)
request.basic_auth(oidc_client_id, oidc_client_secret)
request.form_data = request_params

http_params = {:use_ssl => (uri.scheme == "https")}
response = Net::HTTP.start(uri.hostname, uri.port, http_params) { |http| http.request(request) }
parsed_response = JSON.parse(response.body)
raise parsed_response["error_description"] if parsed_response["error"].present?

Expand All @@ -240,11 +274,18 @@ def get_jwt_token(username, password)
end

def validate_jwt_token(jwt_token)
uri = URI.parse(oidc_provider_metadata["token_introspection_endpoint"])
response = Net::HTTP.post_form(uri, "client_id" => oidc_client_id,
"client_secret" => oidc_client_secret,
"token" => jwt_token)
uri = URI.parse(oidc_token_introspection_endpoint)
request_params = {
"token" => jwt_token
}
request_params["scope"] = oidc_scope if oidc_scope.present?

request = Net::HTTP::Post.new(uri)
request.basic_auth(oidc_client_id, oidc_client_secret)
request.form_data = request_params

http_params = {:use_ssl => (uri.scheme == "https")}
response = Net::HTTP.start(uri.hostname, uri.port, http_params) { |http| http.request(request) }
parsed_response = JSON.parse(response.body)
raise "Invalid access token, JWT is inactive" if parsed_response["active"] != true

Expand All @@ -256,7 +297,7 @@ def validate_jwt_token(jwt_token)

def user_details_from_jwt(token_info)
user_attrs = {
:username => token_info["username"],
:username => token_info["preferred_username"],
:fullname => token_info["name"],
:firstname => token_info["given_name"],
:lastname => token_info["family_name"],
Expand Down

0 comments on commit 32158db

Please sign in to comment.