lib/keycloak.rb in keycloak-2.3.2 vs lib/keycloak.rb in keycloak-2.4.0
- old
+ new
@@ -4,134 +4,159 @@
require 'jwt'
require 'base64'
require 'uri'
module Keycloak
+ OLD_KEYCLOAK_JSON_FILE = 'keycloak.json'
+ KEYCLOAK_JSON_FILE = 'config/keycloak.json'
+
class << self
attr_accessor :proxy, :generate_request_exception, :keycloak_controller,
:proc_cookie_token, :proc_external_attributes,
:realm, :auth_server_url
end
-
def self.explode_exception
- if Keycloak.generate_request_exception == nil
- Keycloak.generate_request_exception = true
- end
+ Keycloak.generate_request_exception = true if Keycloak.generate_request_exception.nil?
Keycloak.generate_request_exception
end
+ def self.installation_file
+ if File.exists?(KEYCLOAK_JSON_FILE)
+ @installation_file ||= KEYCLOAK_JSON_FILE
+ else
+ @installation_file ||= OLD_KEYCLOAK_JSON_FILE
+ end
+ end
+
+ def self.installation_file=(file = nil)
+ raise InstallationFileNotFound unless file.instance_of?(String) && File.exists?(file)
+ @installation_file = file || KEYCLOAK_JSON_FILE
+ end
+
module Client
class << self
attr_accessor :realm, :auth_server_url
attr_reader :client_id, :secret, :configuration, :public_key
end
- KEYCLOAK_JSON_FILE = 'keycloak.json'
-
- def self.get_token(user, password)
+ def self.get_token(user, password, client_id = '', secret = '')
setup_module
- payload = { 'client_id' => @client_id,
- 'client_secret' => @secret,
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+
+ payload = { 'client_id' => client_id,
+ 'client_secret' => secret,
'username' => user,
'password' => password,
'grant_type' => 'password' }
mount_request_token(payload)
end
- def self.get_token_by_code(code, redirect_uri)
+ def self.get_token_by_code(code, redirect_uri, client_id = '', secret = '')
verify_setup
- payload = { 'client_id' => @client_id,
- 'client_secret' => @secret,
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+
+ payload = { 'client_id' => client_id,
+ 'client_secret' => secret,
'code' => code,
'grant_type' => 'authorization_code',
'redirect_uri' => redirect_uri }
mount_request_token(payload)
end
- def self.get_token_by_exchange(issuer, issuer_token)
- setup_module
-
- payload = { 'client_id' => @client_id, 'client_secret' => @secret, 'audience' => @client_id, 'grant_type' => 'urn:ietf:params:oauth:grant-type:token-exchange', 'subject_token_type' => 'urn:ietf:params:oauth:token-type:access_token', 'subject_issuer' => issuer, 'subject_token' => issuer_token }
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
- _request = -> do
- RestClient.post(@configuration['token_endpoint'], payload, header){|response, request, result|
- # case response.code
- # when 200
- # response.body
- # else
- # response.return!
- # end
- response.body
- }
+ def self.get_token_by_exchange(issuer, issuer_token, client_id = '', secret = '', token_endpoint = '')
+ setup_module
+
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+ token_endpoint = @configuration['token_endpoint'] if token_endpoint.blank?
+
+ payload = { 'client_id' => client_id, 'client_secret' => secret, 'audience' => client_id, 'grant_type' => 'urn:ietf:params:oauth:grant-type:token-exchange', 'subject_token_type' => 'urn:ietf:params:oauth:token-type:access_token', 'subject_issuer' => issuer, 'subject_token' => issuer_token }
+ header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
+ _request = -> do
+ RestClient.post(token_endpoint, payload, header){|response, request, result|
+ # case response.code
+ # when 200
+ # response.body
+ # else
+ # response.return!
+ # end
+ response.body
+ }
end
-
- exec_request _request
+ exec_request _request
end
- def self.get_userinfo_issuer(access_token = '')
+ def self.get_userinfo_issuer(access_token = '', userinfo_endpoint = '')
verify_setup
-
+
+ userinfo_endpoint = @configuration['userinfo_endpoint'] if userinfo_endpoint.blank?
+
access_token = self.token["access_token"] if access_token.empty?
payload = { 'access_token' => access_token }
header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
_request = -> do
- RestClient.post(@configuration['userinfo_endpoint'], payload, header){ |response, request, result|
- response.body
- }
+ RestClient.post(userinfo_endpoint, payload, header){ |response, request, result|
+ response.body
+ }
end
-
- exec_request _request
+
+ exec_request _request
end
- def self.get_token_by_refresh_token(refresh_token = '')
+ def self.get_token_by_refresh_token(refresh_token = '', client_id = '', secret = '')
verify_setup
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
refresh_token = self.token['refresh_token'] if refresh_token.empty?
- payload = { 'client_id' => @client_id,
- 'client_secret' => @secret,
+ payload = { 'client_id' => client_id,
+ 'client_secret' => secret,
'refresh_token' => refresh_token,
'grant_type' => 'refresh_token' }
mount_request_token(payload)
end
def self.get_token_by_client_credentials(client_id = '', secret = '')
setup_module
- client_id = @client_id if client_id.empty?
- secret = @secret if secret.empty?
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
payload = { 'client_id' => client_id,
'client_secret' => secret,
'grant_type' => 'client_credentials' }
mount_request_token(payload)
end
- def self.get_token_introspection(token = '', client_id = '', secret = '')
+ def self.get_token_introspection(token = '', client_id = '', secret = '', token_introspection_endpoint = '')
verify_setup
- token = self.token["access_token"] if token.empty?
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+ token = self.token["access_token"] if token.blank?
+ token_introspection_endpoint = @configuration['token_introspection_endpoint'] if token_introspection_endpoint.blank?
+
payload = { 'token' => token }
- client_id = @client_id if client_id.empty?
- secret = @secret if secret.empty?
-
authorization = Base64.strict_encode64("#{client_id}:#{secret}")
authorization = "Basic #{authorization}"
- header = {'Content-Type' => 'application/x-www-form-urlencoded',
- 'authorization' => authorization}
+ header = { 'Content-Type' => 'application/x-www-form-urlencoded',
+ 'authorization' => authorization }
_request = -> do
- RestClient.post(@configuration['token_introspection_endpoint'], payload, header){|response, request, result|
+ RestClient.post(token_introspection_endpoint, payload, header){|response, request, result|
case response.code
when 200..399
response.body
else
response.return!
@@ -140,35 +165,40 @@
end
exec_request _request
end
- def self.url_login_redirect(redirect_uri, response_type = 'code')
+ def self.url_login_redirect(redirect_uri, response_type = 'code', client_id = '', authorization_endpoint = '')
verify_setup
- p = URI.encode_www_form({ response_type: response_type, client_id: @client_id, redirect_uri: redirect_uri })
- "#{@configuration['authorization_endpoint']}?#{p}"
+ client_id = @client_id if client_id.blank?
+ authorization_endpoint = @configuration['authorization_endpoint'] if authorization_endpoint.blank?
+
+ p = URI.encode_www_form({ response_type: response_type, client_id: client_id, redirect_uri: redirect_uri })
+ "#{authorization_endpoint}?#{p}"
end
- def self.logout(redirect_uri = '', refresh_token = '')
+ def self.logout(redirect_uri = '', refresh_token = '', client_id = '', secret = '', end_session_endpoint = '')
verify_setup
if self.token || !refresh_token.empty?
refresh_token = self.token['refresh_token'] if refresh_token.empty?
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+ end_session_endpoint = @configuration['end_session_endpoint'] if end_session_endpoint.blank?
- payload = { 'client_id' => @client_id,
- 'client_secret' => @secret,
- 'refresh_token' => refresh_token
- }
+ payload = { 'client_id' => client_id,
+ 'client_secret' => secret,
+ 'refresh_token' => refresh_token }
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
+ header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
if redirect_uri.empty?
- final_url = @configuration['end_session_endpoint']
+ final_url = end_session_endpoint
else
- final_url = "#{@configuration['end_session_endpoint']}?#{URI.encode_www_form({ redirect_uri: redirect_uri })}"
+ final_url = "#{end_session_endpoint}?#{URI.encode_www_form({ redirect_uri: redirect_uri })}"
end
_request = -> do
RestClient.post(final_url, payload, header){ |response, request, result|
case response.code
@@ -184,21 +214,22 @@
else
true
end
end
- def self.get_userinfo(access_token = '')
+ def self.get_userinfo(access_token = '', userinfo_endpoint = '')
verify_setup
access_token = self.token["access_token"] if access_token.empty?
+ userinfo_endpoint = @configuration['userinfo_endpoint'] if userinfo_endpoint.blank?
payload = { 'access_token' => access_token }
header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
_request = -> do
- RestClient.post(@configuration['userinfo_endpoint'], payload, header){ |response, request, result|
+ RestClient.post(userinfo_endpoint, payload, header){ |response, request, result|
case response.code
when 200
response.body
else
response.return!
@@ -213,16 +244,20 @@
verify_setup
"#{@auth_server_url}/realms/#{@realm}/account"
end
- def self.has_role?(user_role, access_token = '')
+ def self.has_role?(user_role, access_token = '', client_id = '', secret = '', token_introspection_endpoint = '')
verify_setup
- if user_signed_in?(access_token)
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+ token_introspection_endpoint = @configuration['token_introspection_endpoint'] if token_introspection_endpoint.blank?
+
+ if user_signed_in?(access_token, client_id, secret, token_introspection_endpoint)
dt = decoded_access_token(access_token)[0]
- dt = dt["resource_access"][@client_id]
+ dt = dt["resource_access"][client_id]
if dt != nil
dt["roles"].each do |role|
return true if role.to_s == user_role.to_s
end
false
@@ -232,15 +267,19 @@
else
false
end
end
- def self.user_signed_in?(access_token = '')
+ def self.user_signed_in?(access_token = '', client_id = '', secret = '', token_introspection_endpoint = '')
verify_setup
+ client_id = @client_id if client_id.blank?
+ secret = @secret if secret.blank?
+ token_introspection_endpoint = @configuration['token_introspection_endpoint'] if token_introspection_endpoint.blank?
+
begin
- JSON(get_token_introspection(access_token))['active'] === true
+ JSON(get_token_introspection(access_token, client_id, secret, token_introspection_endpoint))['active'] === true
rescue => e
if e.class < Keycloak::KeycloakException
raise
else
false
@@ -284,21 +323,21 @@
private
KEYCLOACK_CONTROLLER_DEFAULT = 'session'
def self.get_installation
- if File.exists?(KEYCLOAK_JSON_FILE)
- installation = JSON File.read(KEYCLOAK_JSON_FILE)
+ if File.exists?(Keycloak.installation_file)
+ installation = JSON File.read(Keycloak.installation_file)
@realm = installation["realm"]
@client_id = installation["resource"]
@secret = installation["credentials"]["secret"]
@public_key = installation["realm-public-key"]
@auth_server_url = installation["auth-server-url"]
openid_configuration
else
if Keycloak.realm.blank? || Keycloak.auth_server_url.blank?
- raise "#{KEYCLOAK_JSON_FILE} and relm settings not found."
+ raise "#{Keycloak.installation_file} and relm settings not found."
else
@realm = Keycloak.realm
@auth_server_url = Keycloak.auth_server_url
openid_configuration
end
@@ -326,11 +365,11 @@
end
end
end
def self.openid_configuration
- RestClient.proxy = Keycloak.proxy unless Keycloak.proxy.empty?
+ RestClient.proxy = Keycloak.proxy if Keycloak.proxy.present?
config_url = "#{@auth_server_url}/realms/#{@realm}/.well-known/openid-configuration"
_request = -> do
RestClient.get config_url
end
response = exec_request _request
@@ -396,20 +435,16 @@
def self.delete_user(id, access_token = nil)
generic_delete("users/#{id}", nil, nil, access_token)
end
def self.revoke_consent_user(id, client_id = nil, access_token = nil)
- if client_id.nil?
- client_id = Keycloak::Client.client_id
- end
+ client_id = Keycloak::Client.client_id if client_id.blank?
generic_delete("users/#{id}/consents/#{client_id}", nil, nil, access_token)
end
def self.update_account_email(id, actions, redirect_uri = '', client_id = nil, access_token = nil)
- if client_id.nil?
- client_id = Keycloak::Client.client_id
- end
+ client_id = Keycloak::Client.client_id if client_id.blank?
generic_put("users/#{id}/execute-actions-email", {:redirect_uri => redirect_uri, :client_id => client_id}, actions, access_token)
end
def self.get_role_mappings(id, access_token = nil)
generic_get("users/#{id}/role-mappings", nil, access_token)
@@ -527,56 +562,70 @@
end
def self.full_url(service)
base_url + service
end
-
end
module Internal
include Keycloak::Admin
class << self
end
- def self.get_users(query_parameters = nil)
+ def self.get_users(query_parameters = nil, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
proc = lambda {|token|
Keycloak::Admin.get_users(query_parameters, token["access_token"])
}
- default_call(proc)
+ default_call(proc, client_id, secret)
end
- def self.change_password(user_id, redirect_uri = '')
+ def self.change_password(user_id, redirect_uri = '', client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
proc = lambda {|token|
Keycloak.generic_request(token["access_token"],
Keycloak::Admin.full_url("users/#{user_id}/execute-actions-email"),
- {:redirect_uri => redirect_uri, :client_id => Keycloak::Client.client_id},
+ {:redirect_uri => redirect_uri, :client_id => client_id},
['UPDATE_PASSWORD'],
'PUT')
}
- default_call(proc)
+ default_call(proc, client_id, secret)
end
- def self.forgot_password(user_login, redirect_uri = '')
- user = get_user_info(user_login, true)
- change_password(user['id'], redirect_uri)
+ def self.forgot_password(user_login, redirect_uri = '', client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
+ user = get_user_info(user_login, true, client_id, secret)
+ change_password(user['id'], redirect_uri, client_id, secret)
end
- def self.get_logged_user_info
+ def self.get_logged_user_info(client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
proc = lambda {|token|
userinfo = JSON Keycloak::Client.get_userinfo
Keycloak.generic_request(token["access_token"],
Keycloak::Admin.full_url("users/#{userinfo['sub']}"),
nil, nil, 'GET')
}
- default_call(proc)
+ default_call(proc, client_id, secret)
end
- def self.get_user_info(user_login, whole_word = false)
+ def self.get_user_info(user_login, whole_word = false, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
proc = lambda { |token|
if user_login.index('@').nil?
search = {:username => user_login}
else
search = {:email => user_login}
@@ -608,35 +657,43 @@
raise Keycloak::UserLoginNotFound
end
end
}
- default_call(proc)
+ default_call(proc, client_id, secret)
end
- def self.exists_name_or_email(value, user_id = '')
+ def self.exists_name_or_email(value, user_id = '', client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
begin
- usuario = Keycloak::Internal.get_user_info(value, true)
+ usuario = Keycloak::Internal.get_user_info(value, true, client_id, secret)
if user_id.empty? || user_id != usuario['id']
usuario.present?
else
false
end
rescue StandardError
false
end
end
- def self.logged_federation_user?
- info = get_logged_user_info
+ def self.logged_federation_user?(client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+ info = get_logged_user_info(client_id, secret)
info['federationLink'] != nil
end
- def self.create_simple_user(username, password, email, first_name, last_name, realm_roles_names, client_roles_names, proc = nil)
+ def self.create_simple_user(username, password, email, first_name, last_name, realm_roles_names, client_roles_names, proc = nil, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
begin
username.downcase!
- user = get_user_info(username, true)
+ user = get_user_info(username, true, client_id, secret)
newUser = false
rescue Keycloak::UserLoginNotFound
newUser = true
rescue
raise
@@ -651,11 +708,11 @@
if !newUser || Keycloak.generic_request(token["access_token"],
Keycloak::Admin.full_url("users/"),
nil, user_representation, 'POST')
- user = get_user_info(username, true) if newUser
+ user = get_user_info(username, true, client_id, secret) if newUser
credential_representation = { type: "password",
temporary: false,
value: password }
@@ -663,11 +720,11 @@
Keycloak::Admin.full_url("users/#{user['id']}/reset-password"),
nil, credential_representation, 'PUT')
client = JSON Keycloak.generic_request(token["access_token"],
Keycloak::Admin.full_url("clients/"),
- { clientId: Keycloak::Client.client_id }, nil, 'GET')
+ { clientId: client_id }, nil, 'GET')
if client_roles_names.count > 0
roles = []
client_roles_names.each do |r|
if r.present?
@@ -706,42 +763,53 @@
end
end
end
}
- if default_call(proc_default)
+ if default_call(proc_default, client_id, secret)
proc.call user unless proc.nil?
end
end
- def self.create_starter_user(username, password, email, client_roles_names, proc = nil)
- Keycloak::Internal.create_simple_user(username, password, email, '', '', [], client_roles_names, proc)
+ def self.create_starter_user(username, password, email, client_roles_names, proc = nil, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+ Keycloak::Internal.create_simple_user(username, password, email, '', '', [], client_roles_names, proc, client_id, secret)
end
- def self.get_client_roles
+ def self.get_client_roles(client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
proc = lambda {|token|
- client = JSON Keycloak::Admin.get_clients({ clientId: Keycloak::Client.client_id }, token["access_token"])
+ client = JSON Keycloak::Admin.get_clients({ clientId: client_id }, token["access_token"])
Keycloak.generic_request(token["access_token"],
Keycloak::Admin.full_url("clients/#{client[0]['id']}/roles"),
nil, nil, 'GET')
}
- default_call(proc)
+ default_call(proc, client_id, secret)
end
- def self.get_client_user_roles(user_id)
+ def self.get_client_user_roles(user_id, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
proc = lambda {|token|
- client = JSON Keycloak::Admin.get_clients({ clientId: Keycloak::Client.client_id }, token["access_token"])
+ client = JSON Keycloak::Admin.get_clients({ clientId: client_id }, token["access_token"])
Keycloak::Admin.get_effective_client_level_role_composite_user(user_id, client[0]['id'], token["access_token"])
}
- default_call(proc)
+ default_call(proc, client_id, secret)
end
- def self.has_role?(user_id, user_role)
- roles = JSON get_client_user_roles(user_id)
+ def self.has_role?(user_id, user_role, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
+
+ roles = JSON get_client_user_roles(user_id, client_id, secret)
if !roles.nil?
roles.each do |role|
return true if role['name'].to_s == user_role.to_s
end
false
@@ -750,19 +818,21 @@
end
end
protected
- def self.default_call(proc)
+ def self.default_call(proc, client_id = '', secret = '')
+ client_id = Keycloak::Client.client_id if client_id.blank?
+ secret = Keycloak::Client.secret if secret.blank?
begin
tk = nil
resp = nil
Keycloak::Client.get_installation
- payload = { 'client_id' => Keycloak::Client.client_id,
- 'client_secret' => Keycloak::Client.secret,
+ payload = { 'client_id' => client_id,
+ 'client_secret' => secret,
'grant_type' => 'client_credentials' }
header = {'Content-Type' => 'application/x-www-form-urlencoded'}
_request = -> do
@@ -778,11 +848,11 @@
end
Keycloak::Client.exec_request _request
ensure
if tk
- payload = { 'client_id' => Keycloak::Client.client_id,
- 'client_secret' => Keycloak::Client.secret,
+ payload = { 'client_id' => client_id,
+ 'client_secret' => secret,
'refresh_token' => tk["refresh_token"] }
header = {'Content-Type' => 'application/x-www-form-urlencoded'}
_request = -> do
RestClient.post(Keycloak::Client.configuration['end_session_endpoint'], payload, header){|response, request, result|
\ No newline at end of file