lib/keycloak.rb in keycloak-2.1.0 vs lib/keycloak.rb in keycloak-2.2.0
- old
+ new
@@ -4,762 +4,799 @@
require 'jwt'
require 'base64'
require 'uri'
module Keycloak
+ class << self
+ attr_accessor :proxy, :generate_request_exception, :keycloak_controller,
+ :proc_cookie_token, :proc_external_attributes
+ end
- class << self
- attr_accessor :proxy, :generate_request_exception, :keycloak_controller,
- :proc_cookie_token, :proc_external_attributes
- end
+ def self.explode_exception
+ if Keycloak.generate_request_exception == nil
+ Keycloak.generate_request_exception = true
+ end
+ Keycloak.generate_request_exception
+ end
- def self.explode_exception
- if Keycloak.generate_request_exception == nil
- Keycloak.generate_request_exception = true
- end
- Keycloak.generate_request_exception
- end
+ module Client
+ class << self
+ attr_reader :realm, :url, :client_id, :auth_server_url,
+ :secret, :configuration, :public_key
+ end
- module Client
+ KEYCLOAK_JSON_FILE = 'keycloak.json'
- class << self
- attr_reader :realm, :url, :client_id, :auth_server_url,
- :secret, :configuration, :public_key
+ def self.get_token(user, password)
+ setup_module
- end
+ payload = { 'client_id' => @client_id,
+ 'client_secret' => @secret,
+ 'username' => user,
+ 'password' => password,
+ 'grant_type' => 'password' }
- KEYCLOAK_JSON_FILE = 'keycloak.json'
+ mount_request_token(payload)
+ end
- def self.get_token(user, password)
- setup_module
+ def self.get_token_by_code(code, redirect_uri)
+ verify_setup
- payload = {'client_id' => @client_id,
- 'client_secret' => @secret,
- 'username' => user,
- 'password' => password,
- 'grant_type' => 'password'
- }
+ payload = { 'client_id' => @client_id,
+ 'client_secret' => @secret,
+ 'code' => code,
+ 'grant_type' => 'authorization_code',
+ 'redirect_uri' => redirect_uri }
- mount_request_token(payload)
- end
+ mount_request_token(payload)
+ end
- def self.get_token_by_code(code, redirect_uri)
- verify_setup
+ def self.get_token_by_refresh_token(refreshToken = '')
+ verify_setup
- payload = {'client_id' => @client_id,
- 'client_secret' => @secret,
- 'code' => code,
- 'grant_type' => 'authorization_code',
- 'redirect_uri' => redirect_uri
- }
+ refreshToken = self.token['refresh_token'] if refreshToken.empty?
- mount_request_token(payload)
- end
+ payload = { 'client_id' => @client_id,
+ 'client_secret' => @secret,
+ 'refresh_token' => refreshToken,
+ 'grant_type' => 'refresh_token' }
- def self.get_token_by_refresh_token(refreshToken = '')
- verify_setup
+ mount_request_token(payload)
+ end
- refreshToken = self.token['refresh_token'] if refreshToken.empty?
+ def self.get_token_by_client_credentials
+ setup_module
- payload = {'client_id' => @client_id,
- 'client_secret' => @secret,
- 'refresh_token' => refreshToken,
- 'grant_type' => 'refresh_token'
- }
+ payload = { 'client_id' => @client_id,
+ 'client_secret' => @secret,
+ 'grant_type' => 'client_credentials' }
- mount_request_token(payload)
- end
+ mount_request_token(payload)
+ end
- def self.get_token_by_client_credentials
- setup_module
+ def self.get_token_introspection(token = '')
+ verify_setup
- payload = {'client_id' => @client_id,
- 'client_secret' => @secret,
- 'grant_type' => 'client_credentials'
- }
+ token = self.token["access_token"] if token.empty?
- mount_request_token(payload)
- end
+ payload = { 'token' => token }
- def self.get_token_introspection(token = '')
- verify_setup
+ authorization = Base64.strict_encode64("#{@client_id}:#{@secret}")
+ authorization = "Basic #{authorization}"
- token = self.token["access_token"] if token.empty?
+ header = {'Content-Type' => 'application/x-www-form-urlencoded',
+ 'authorization' => authorization}
- payload = {'token' => token}
+ _request = -> do
+ RestClient.post(@configuration['token_introspection_endpoint'], payload, header){|response, request, result|
+ case response.code
+ when 200..399
+ response.body
- authorization = Base64.strict_encode64("#{@client_id}:#{@secret}")
- authorization = "Basic #{authorization}"
+ else
+ response.return!
+ end
+ }
+ end
- header = {'Content-Type' => 'application/x-www-form-urlencoded',
- 'authorization' => authorization}
+ exec_request _request
+ end
- _request = -> do
- RestClient.post(@configuration['token_introspection_endpoint'], payload, header){|response, request, result|
- case response.code
- when 200..399
- response.body
+ def self.url_login_redirect(redirect_uri, response_type = 'code')
+ verify_setup
- else
- response.return!
- end
- }
- end
+ p = URI.encode_www_form({ response_type: response_type, client_id: @client_id, redirect_uri: redirect_uri })
+ "#{@configuration['authorization_endpoint']}?#{p}"
+ end
- exec_request _request
- end
+ def self.logout(redirect_uri = '', refresh_token = '')
+ verify_setup
- def self.url_login_redirect(redirect_uri, response_type = 'code')
- verify_setup
+ if self.token || !refresh_token.empty?
- p = URI.encode_www_form({:response_type => response_type, :client_id => @client_id, :redirect_uri => redirect_uri})
- "#{@configuration['authorization_endpoint']}?#{p}"
- end
+ refresh_token = self.token['refresh_token'] if refresh_token.empty?
- def self.logout(redirect_uri = '', refresh_token = '')
- verify_setup
+ payload = { 'client_id' => @client_id,
+ 'client_secret' => @secret,
+ 'refresh_token' => refresh_token
+ }
- if self.token || !refresh_token.empty?
+ header = {'Content-Type' => 'application/x-www-form-urlencoded'}
- refresh_token = self.token['refresh_token'] if refresh_token.empty?
+ if redirect_uri.empty?
+ final_url = @configuration['end_session_endpoint']
+ else
+ final_url = "#{@configuration['end_session_endpoint']}?#{URI.encode_www_form({ redirect_uri: redirect_uri })}"
+ end
- payload = {'client_id' => @client_id,
- 'client_secret' => @secret,
- 'refresh_token' => refresh_token
- }
+ _request = -> do
+ RestClient.post(final_url, payload, header){ |response, request, result|
+ case response.code
+ when 200..399
+ true
+ else
+ response.return!
+ end
+ }
+ end
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
+ exec_request _request
+ else
+ true
+ end
+ end
- if redirect_uri.empty?
- final_url = @configuration['end_session_endpoint']
- else
- final_url = "#{@configuration['end_session_endpoint']}?#{URI.encode_www_form({:redirect_uri => redirect_uri})}"
- end
+ def self.get_userinfo(accessToken = '')
+ verify_setup
- _request = -> do
- RestClient.post(final_url, payload, header){|response, request, result|
- case response.code
- when 200..399
- true
- else
- response.return!
- end
- }
- end
+ accessToken = self.token["access_token"] if accessToken.empty?
- exec_request _request
- else
- true
- end
- end
+ payload = { 'access_token' => accessToken }
- def self.get_userinfo(accessToken = '')
- verify_setup
+ header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
- accessToken = self.token["access_token"] if accessToken.empty?
+ _request = -> do
+ RestClient.post(@configuration['userinfo_endpoint'], payload, header){ |response, request, result|
+ case response.code
+ when 200
+ response.body
+ else
+ response.return!
+ end
+ }
+ end
- payload = {'access_token' => accessToken}
+ exec_request _request
+ end
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
+ def self.url_user_account
+ verify_setup
- _request = -> do
- RestClient.post(@configuration['userinfo_endpoint'], payload, header){|response, request, result|
- case response.code
- when 200
- response.body
- else
- response.return!
- end
- }
- end
+ "#{@url}/realms/#{@realm}/account"
+ end
- exec_request _request
- end
+ def self.has_role?(userRole, accessToken = '')
+ verify_setup
- def self.url_user_account
- verify_setup
+ if user_signed_in?(accessToken)
+ dt = decoded_access_token(accessToken)[0]
+ dt = dt["resource_access"][@client_id]
+ if dt != nil
+ dt["roles"].each do |role|
+ return true if role.to_s == userRole.to_s
+ end
+ false
+ else
+ false
+ end
+ else
+ false
+ end
+ end
- "#{@url}/realms/#{@realm}/account"
- end
+ def self.user_signed_in?(accessToken = '')
+ verify_setup
- def self.has_role?(userRole, accessToken = '')
- verify_setup
+ begin
+ JSON(get_token_introspection(accessToken))['active'] === true
+ rescue => e
+ if e.class < Keycloak::KeycloakException
+ raise
+ else
+ false
+ end
+ end
+ end
- if user_signed_in?(accessToken)
- dt = decoded_access_token(accessToken)[0]
- dt = dt["resource_access"][@client_id]
- if dt != nil
- dt["roles"].each do |role|
- return true if role.to_s == userRole.to_s
- end
- false
- else
- false
- end
- else
- false
- end
- end
+ def self.get_attribute(attributeName, accessToken = '')
+ verify_setup
- def self.user_signed_in?(accessToken = '')
- verify_setup
+ attr = decoded_access_token(accessToken)[0]
+ attr[attributeName]
+ end
- begin
- JSON(get_token_introspection(accessToken))['active'] === true
- rescue => e
- if e.class < Keycloak::KeycloakException
- raise
- else
- false
- end
- end
- end
+ def self.token
+ if !Keycloak.proc_cookie_token.nil?
+ JSON Keycloak.proc_cookie_token.call
+ else
+ raise Keycloak::ProcCookieTokenNotDefined
+ end
+ end
- def self.get_attribute(attributeName, accessToken = '')
- verify_setup
+ def self.external_attributes
+ if !Keycloak.proc_external_attributes.nil?
+ Keycloak.proc_external_attributes.call
+ else
+ raise Keycloak::ProcExternalAttributesNotDefined
+ end
+ end
- attr = decoded_access_token(accessToken)[0]
- attr[attributeName]
- end
+ private
- def self.token
- unless Keycloak.proc_cookie_token.nil?
- JSON Keycloak.proc_cookie_token.call
- else
- raise Keycloak::ProcCookieTokenNotDefined
- end
- end
+ KEYCLOACK_CONTROLLER_DEFAULT = 'session'
- def self.external_attributes
- unless Keycloak.proc_external_attributes.nil?
- Keycloak.proc_external_attributes.call
- else
- raise Keycloak::ProcExternalAttributesNotDefined
- end
- end
+ def self.get_installation
+ if File.exists?(KEYCLOAK_JSON_FILE)
+ installation = JSON File.read(KEYCLOAK_JSON_FILE)
+ @realm = installation["realm"]
+ @url = installation["auth-server-url"]
+ @client_id = installation["resource"]
+ @secret = installation["credentials"]["secret"]
+ @public_key = installation["realm-public-key"]
+ @auth_server_url = installation["auth-server-url"]
+ openid_configuration
+ else
+ raise "#{KEYCLOAK_JSON_FILE} not found."
+ end
+ end
- private
+ def self.verify_setup
+ get_installation if @configuration.nil?
+ end
- KEYCLOACK_CONTROLLER_DEFAULT = 'session'
+ def self.setup_module
+ Keycloak.proxy ||= ''
+ Keycloak.keycloak_controller ||= KEYCLOACK_CONTROLLER_DEFAULT
+ get_installation
+ end
- def self.get_installation
- if File.exists?(KEYCLOAK_JSON_FILE)
- installation = JSON File.read(KEYCLOAK_JSON_FILE)
- @realm = installation["realm"]
- @url = installation["auth-server-url"]
- @client_id = installation["resource"]
- @secret = installation["credentials"]["secret"]
- @public_key = installation["realm-public-key"]
- @auth_server_url = installation["auth-server-url"]
- openid_configuration
- else
- raise "#{KEYCLOAK_JSON_FILE} not found."
- end
- end
+ def self.exec_request(proc_request)
+ if Keycloak.explode_exception
+ proc_request.call
+ else
+ begin
+ proc_request.call
+ rescue RestClient::ExceptionWithResponse => err
+ err.response
+ end
+ end
+ end
- def self.verify_setup
- get_installation if @configuration.nil?
- end
+ def self.openid_configuration
+ RestClient.proxy = Keycloak.proxy unless Keycloak.proxy.empty?
+ config_url = "#{@url}/realms/#{@realm}/.well-known/openid-configuration"
+ _request = -> do
+ RestClient.get config_url
+ end
+ response = exec_request _request
+ if response.code == 200
+ @configuration = JSON response.body
+ else
+ response.return!
+ end
+ end
- def self.setup_module
- Keycloak.proxy ||= ''
- Keycloak.keycloak_controller ||= KEYCLOACK_CONTROLLER_DEFAULT
- get_installation
- end
+ def self.mount_request_token(payload)
+ header = {'Content-Type' => 'application/x-www-form-urlencoded'}
- def self.exec_request(proc_request)
- if Keycloak.explode_exception
- proc_request.call
- else
- begin
- proc_request.call
- rescue RestClient::ExceptionWithResponse => err
- err.response
- end
- end
- end
+ _request = -> do
+ RestClient.post(@configuration['token_endpoint'], payload, header){|response, request, result|
+ case response.code
+ when 200
+ response.body
+ else
+ response.return!
+ end
+ }
+ end
- def self.openid_configuration
- RestClient.proxy = Keycloak.proxy unless Keycloak.proxy.empty?
- configUrl = "#{@url}/realms/#{@realm}/.well-known/openid-configuration"
- _request = -> do
- RestClient.get configUrl
- end
- response = exec_request _request
- if response.code == 200
- @configuration = JSON response.body
- else
- response.return!
- end
- end
+ exec_request _request
+ end
- def self.mount_request_token(payload)
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
+ def self.decoded_access_token(accessToken = '')
+ accessToken = self.token["access_token"] if accessToken.empty?
+ JWT.decode accessToken, @public_key, false, { :algorithm => 'RS256' }
+ end
- _request = -> do
- RestClient.post(@configuration['token_endpoint'], payload, header){|response, request, result|
- case response.code
- when 200
- response.body
- else
- response.return!
- end
- }
- end
+ def self.decoded_refresh_token(refreshToken = '')
+ refreshToken = self.token["access_token"] if refreshToken.empty?
+ JWT.decode refreshToken, @public_key, false, { :algorithm => 'RS256' }
+ end
- exec_request _request
- end
+ def self.decoded_id_token(idToken = '')
+ tk = self.token
+ idToken = tk["id_token"] if idToken.empty?
+ if idToken
+ @decoded_id_token = JWT.decode idToken, @public_key, false, { :algorithm => 'RS256' }
+ end
+ end
- def self.decoded_access_token(accessToken = '')
- accessToken = self.token["access_token"] if accessToken.empty?
- JWT.decode accessToken, @public_key, false, { :algorithm => 'RS256' }
- end
+ end
- def self.decoded_refresh_token(refreshToken = '')
- refreshToken = self.token["access_token"] if refreshToken.empty?
- JWT.decode refreshToken, @public_key, false, { :algorithm => 'RS256' }
- end
+ # Os recursos desse module (admin) serão utilizadas apenas por usuários que possuem as roles do client realm-management
+ module Admin
+ class << self
+ end
- def self.decoded_id_token(idToken = '')
- tk = self.token
- idToken = tk["id_token"] if idToken.empty?
- if idToken
- @decoded_id_token = JWT.decode idToken, @public_key, false, { :algorithm => 'RS256' }
- end
- end
+ def self.get_users(queryParameters = nil, accessToken = nil)
+ generic_get("users/", queryParameters, accessToken)
+ end
- end
+ def self.create_user(userRepresentation, accessToken = nil)
+ generic_post("users/", nil, userRepresentation, accessToken)
+ end
- # Os recursos desse module (admin) serão utilizadas apenas por usuários que possuem as roles do client realm-management
- module Admin
+ def self.count_users(accessToken = nil)
+ generic_get("users/count/", nil, accessToken)
+ end
- class << self
+ def self.get_user(id, accessToken = nil)
+ generic_get("users/#{id}", nil, accessToken)
+ end
- end
+ def self.update_user(id, userRepresentation, accessToken = nil)
+ generic_put("users/#{id}", nil, userRepresentation, accessToken)
+ end
- def self.get_users( queryParameters = nil)
- generic_get("users/", queryParameters)
- end
+ def self.delete_user(id, accessToken = nil)
+ generic_delete("users/#{id}", nil, nil, accessToken)
+ end
- def self.create_user(userRepresentation)
- generic_post("users/", nil, userRepresentation)
- end
+ def self.revoke_consent_user(id, clientID = nil, accessToken = nil)
+ if clientID.nil?
+ clientID = Keycloak::Client.client_id
+ end
+ generic_delete("users/#{id}/consents/#{clientID}", nil, nil, accessToken)
+ end
- def self.count_users
- generic_get("users/count/")
- end
+ def self.update_account_email(id, actions, redirectUri = '', clientID = nil, accessToken = nil)
+ if clientID.nil?
+ clientID = Keycloak::Client.client_id
+ end
+ generic_put("users/#{id}/execute-actions-email", {:redirect_uri => redirectUri, :client_id => clientID}, actions, accessToken)
+ end
- def self.get_user(id)
- generic_get("users/#{id}")
- end
+ def self.get_role_mappings(id, accessToken = nil)
+ generic_get("users/#{id}/role-mappings", nil, accessToken)
+ end
- def self.update_user(id, userRepresentation)
- generic_put("users/#{id}", nil, userRepresentation)
- end
+ def self.get_clients(queryParameters = nil, accessToken = nil)
+ generic_get("clients/", queryParameters, accessToken)
+ end
- def self.delete_user(id)
- generic_delete("users/#{id}")
- end
+ def self.get_all_roles_client(id, accessToken = nil)
+ generic_get("clients/#{id}/roles", nil, accessToken)
+ end
- def self.revoke_consent_user(id, clientID = nil)
- if clientID.nil?
- clientID = Keycloak::Client.client_id
- end
- generic_delete("users/#{id}/consents/#{clientID}")
- end
+ def self.get_roles_client_by_name(id, roleName, accessToken = nil)
+ generic_get("clients/#{id}/roles/#{roleName}", nil, accessToken)
+ end
- def self.update_account_email(id, actions, redirectUri = '', clientID = nil)
- if clientID.nil?
- clientID = Keycloak::Client.client_id
- end
- generic_put("users/#{id}/execute-actions-email", {:redirect_uri => redirectUri, :client_id => clientID}, actions)
- end
+ def self.add_client_level_roles_to_user(id, client, roleRepresentation, accessToken = nil)
+ generic_post("users/#{id}/role-mappings/clients/#{client}", nil, roleRepresentation, accessToken)
+ end
- def self.get_role_mappings(id)
- generic_get("users/#{id}/role-mappings")
- end
+ def self.delete_client_level_roles_from_user(id, client, roleRepresentation, accessToken = nil)
+ generic_delete("users/#{id}/role-mappings/clients/#{client}", nil, roleRepresentation, accessToken)
+ end
- def self.get_clients(queryParameters = nil)
- generic_get("clients/", queryParameters)
- end
+ def self.get_client_level_role_for_user_and_app(id, client, accessToken = nil)
+ generic_get("users/#{id}/role-mappings/clients/#{client}", nil, accessToken)
+ end
- def self.get_all_roles_client(id)
- generic_get("clients/#{id}/roles")
- end
+ def self.update_effective_user_roles(id, clientID, rolesNames, accessToken = nil)
+ client = JSON get_clients({ clientId: clientID })
- def self.get_roles_client_by_name(id, roleName)
- generic_get("clients/#{id}/roles/#{roleName}")
- end
+ userRoles = JSON get_client_level_role_for_user_and_app(id, client[0]['id'], accessToken)
- def self.add_client_level_roles_to_user(id, client, roleRepresentation)
- generic_post("users/#{id}/role-mappings/clients/#{client}", nil, roleRepresentation)
- end
+ roles = Array.new
+ # Include new role
+ rolesNames.each do |r|
+ if r && !r.empty?
+ found = false
+ userRoles.each do |ur|
+ found = ur['name'] == r
+ break if found
+ found = false
+ end
+ if !found
+ role = JSON get_roles_client_by_name(client[0]['id'], r, accessToken)
+ roles.push(role)
+ end
+ end
+ end
- def self.delete_client_level_roles_fom_user(id, client, roleRepresentation)
- generic_delete("users/#{id}/role-mappings/clients/#{client}", nil, roleRepresentation)
- end
+ garbageRoles = Array.new
+ # Exclude old role
+ userRoles.each do |ur|
+ found = false
+ rolesNames.each do |r|
+ if r && !r.empty?
+ found = ur['name'] == r
+ break if found
+ found = false
+ end
+ end
+ if !found
+ garbageRoles.push(ur)
+ end
+ end
- def self.get_client_level_role_for_user_and_app(id, client)
- generic_get("users/#{id}/role-mappings/clients/#{client}")
- end
+ if garbageRoles.count > 0
+ delete_client_level_roles_from_user(id, client[0]['id'], garbageRoles, accessToken)
+ end
- def self.update_effective_user_roles(id, clientID, rolesNames)
- client = JSON get_clients({:clientId => clientID})
+ if roles.count > 0
+ add_client_level_roles_to_user(id, client[0]['id'], roles, accessToken)
+ end
+ end
- userRoles = JSON get_client_level_role_for_user_and_app(id, client[0]['id'])
+ def self.reset_password(id, credentialRepresentation, accessToken = nil)
+ generic_put("users/#{id}/reset-password", nil, credentialRepresentation, accessToken)
+ end
- roles = Array.new
- # Include new role
- rolesNames.each do |r|
- if r && !r.empty?
- found = false
- userRoles.each do |ur|
- found = ur['name'] == r
- break if found
- found = false
- end
- if !found
- role = JSON get_roles_client_by_name(client[0]['id'], r)
- roles.push(role)
- end
- end
- end
+ def self.get_effective_client_level_role_composite_user(id, client, accessToken = nil)
+ generic_get("users/#{id}/role-mappings/clients/#{client}/composite", nil, accessToken)
+ end
- garbageRoles = Array.new
- # Exclude old role
- userRoles.each do |ur|
- found = false
- rolesNames.each do |r|
- if r && !r.empty?
- found = ur['name'] == r
- break if found
- found = false
- end
- end
- if !found
- garbageRoles.push(ur)
- end
- end
+ # Generics methods
- if garbageRoles.count > 0
- delete_client_level_roles_fom_user(id, client[0]['id'], garbageRoles)
- end
+ def self.generic_get(service, queryParameters = nil, accessToken = nil)
+ Keycloak.generic_request(effective_access_token(accessToken), full_url(service), queryParameters, nil, 'GET')
+ end
- if roles.count > 0
- add_client_level_roles_to_user(id, client[0]['id'], roles)
- end
- end
+ def self.generic_post(service, queryParameters, bodyParameter, accessToken = nil)
+ Keycloak.generic_request(effective_access_token(accessToken), full_url(service), queryParameters, bodyParameter, 'POST')
+ end
- def self.reset_password(id, credentialRepresentation)
- generic_put("users/#{id}/reset-password", nil, credentialRepresentation)
- end
+ def self.generic_put(service, queryParameters, bodyParameter, accessToken = nil)
+ Keycloak.generic_request(effective_access_token(accessToken), full_url(service), queryParameters, bodyParameter, 'PUT')
+ end
- # Generics methods
+ def self.generic_delete(service, queryParameters = nil, bodyParameter = nil, accessToken = nil)
+ Keycloak.generic_request(effective_access_token(accessToken), full_url(service), queryParameters, bodyParameter, 'DELETE')
+ end
- def self.generic_get(service, queryParameters = nil)
- Keycloak.generic_request(Keycloak::Client.token['access_token'], full_url(service), queryParameters, nil, 'GET')
- end
+ private
- def self.generic_post(service, queryParameters, bodyParameter)
- Keycloak.generic_request(Keycloak::Client.token['access_token'], full_url(service), queryParameters, bodyParameter, 'POST')
- end
+ def self.effective_access_token(access_token)
+ if access_token.blank?
+ Keycloak::Client.token['access_token']
+ else
+ access_token
+ end
+ end
- def self.generic_put(service, queryParameters, bodyParameter)
- Keycloak.generic_request(Keycloak::Client.token['access_token'], full_url(service), queryParameters, bodyParameter, 'PUT')
- end
+ def self.base_url
+ Keycloak::Client.auth_server_url + "/admin/realms/#{Keycloak::Client.realm}/"
+ end
- def self.generic_delete(service, queryParameters = nil, bodyParameter = nil)
- Keycloak.generic_request(Keycloak::Client.token['access_token'], full_url(service), queryParameters, bodyParameter, 'DELETE')
- end
+ def self.full_url(service)
+ base_url + service
+ end
- private
+ end
- def self.base_url
- Keycloak::Client.auth_server_url + "/admin/realms/#{Keycloak::Client.realm}/"
- end
+ module Internal
+ include Keycloak::Admin
- def self.full_url(service)
- base_url + service
- end
+ class << self
+ end
- end
+ def self.get_users(queryParameters = nil)
+ proc = lambda {|token|
+ Keycloak::Admin.get_users(queryParameters, token["access_token"])
+ }
- module Internal
- include Keycloak::Admin
+ default_call(proc)
+ end
- class << self
- attr_accessor
- end
+ def self.change_password(userID, redirectURI = '')
+ proc = lambda {|token|
+ Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("users/#{userID}/execute-actions-email"),
+ {:redirect_uri => redirectURI, :client_id => Keycloak::Client.client_id},
+ ['UPDATE_PASSWORD'],
+ 'PUT')
+ }
- def self.change_password(userID, redirectURI = '')
- proc = lambda {|token|
- Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("users/#{userID}/execute-actions-email"),
- {:redirect_uri => redirectURI, :client_id => Keycloak::Client.client_id},
- ['UPDATE_PASSWORD'],
- 'PUT')
- }
+ default_call(proc)
+ end
- default_call(proc)
- end
+ def self.forgot_password(userLogin, redirectURI = '')
+ user = get_user_info(userLogin, true)
+ change_password(user['id'], redirectURI)
+ end
- def self.forgot_password(userLogin, redirectURI = '')
- user = get_user_info(userLogin, true)
- change_password(user['id'], redirectURI)
- end
+ def self.get_logged_user_info
+ 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')
+ }
- def self.get_logged_user_info
- 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)
+ end
- default_call(proc)
- end
+ def self.get_user_info(userLogin, wholeWord = false)
+ proc = lambda { |token|
+ if userLogin.index('@').nil?
+ search = {:username => userLogin}
+ else
+ search = {:email => userLogin}
+ end
+ users = JSON Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("users/"),
+ search, nil, 'GET')
+ users[0]
+ if users.count.zero?
+ raise Keycloak::UserLoginNotFound
+ else
+ efective_index = -1
+ users.each_with_index do |user, i|
+ if wholeWord
+ efective_index = i if userLogin == user['username'] || userLogin == user['email']
+ else
+ efective_index = 0
+ end
+ break if efective_index >= 0
+ end
- def self.get_user_info(userLogin, wholeWord = false)
- proc = lambda {|token|
- if userLogin.index('@').nil?
- search = {:username => userLogin}
- else
- search = {:email => userLogin}
- end
- users = JSON Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("users/"),
- search, nil, 'GET')
- users[0]
- if users.count == 0
- raise Keycloak::UserLoginNotFound
- else
- efectiveIndex = -1
- users.each_with_index do |user, i|
- if wholeWord
- efectiveIndex = i if userLogin == user['username'] || userLogin == user['email']
- else
- efectiveIndex = 0
- end
- break if efectiveIndex >= 0
- end
+ if efective_index >= 0
+ if wholeWord
+ users[efective_index]
+ else
+ users
+ end
+ else
+ raise Keycloak::UserLoginNotFound
+ end
+ end
+ }
- if efectiveIndex >= 0
- if wholeWord
- users[efectiveIndex]
- else
- users
- end
- else
- raise Keycloak::UserLoginNotFound
- end
- end
- }
+ default_call(proc)
+ end
- default_call(proc)
- end
+ def self.logged_federation_user?
+ info = get_logged_user_info
+ info['federationLink'] != nil
+ end
- def self.is_logged_federation_user?
- info = get_logged_user_info
- info['federationLink'] != nil
- end
+ def self.create_starter_user(userName, password, email, clientRolesNames, proc = nil)
+ begin
+ user = get_user_info(userName, true)
+ newUser = false
+ rescue Keycloak::UserLoginNotFound
+ newUser = true
+ rescue
+ raise
+ end
- def self.create_starter_user(userName, password, email, clientRolesNames, proc = nil)
- begin
- user = get_user_info(userName, true)
- newUser = false
- rescue Keycloak::UserLoginNotFound
- newUser = true
- rescue
- raise
- end
+ proc_default = lambda { |token|
+ user_representation = { username: userName,
+ email: email,
+ enabled: true }
- procDefault = lambda {|token|
- userRepresentation = {:username => userName,
- :email => email,
- :enabled => true}
+ if !newUser || Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("users/"),
+ nil, user_representation, 'POST')
- if !newUser || Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("users/"),
- nil, userRepresentation, 'POST')
+ user = get_user_info(userName, true) if newUser
- user = get_user_info(userName, true) if newUser
+ credential_representation = { type: "password",
+ temporary: false,
+ value: password }
- credentialRepresentation = {:type => "password",
- :temporary => false,
- :value => password}
+ if Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("users/#{user['id']}/reset-password"),
+ nil, credential_representation, 'PUT')
- if Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("users/#{user['id']}/reset-password"),
- nil, credentialRepresentation, 'PUT')
+ client = JSON Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("clients/"),
+ { clientId: Keycloak::Client.client_id }, nil, 'GET')
- client = JSON Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("clients/"),
- {:clientId => Keycloak::Client.client_id}, nil, 'GET')
+ roles = []
+ clientRolesNames.each do |r|
+ if r.present?
+ role = JSON Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("clients/#{client[0]['id']}/roles/#{r}"),
+ nil, nil, 'GET')
+ roles.push(role)
+ end
+ end
- roles = Array.new
- clientRolesNames.each do |r|
- if r && !r.empty?
- role = JSON Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("clients/#{client[0]['id']}/roles/#{r}"),
- nil, nil, 'GET')
- roles.push(role)
- end
- end
+ if roles.count > 0
+ Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("users/#{user['id']}/role-mappings/clients/#{client[0]['id']}"),
+ nil, roles, 'POST')
+ end
+ end
- if roles.count > 0
- Keycloak.generic_request(token["access_token"],
- Keycloak::Admin.full_url("users/#{user['id']}/role-mappings/clients/#{client[0]['id']}"),
- nil, roles, 'POST')
- end
- end
+ end
+ }
- end
- }
+ if default_call(proc_default)
+ proc.call user unless proc.nil?
+ end
+ end
- if default_call(procDefault)
- if !proc.nil?
- proc.call user
- end
- end
+ def self.get_client_roles
+ proc = lambda {|token|
+ client = JSON Keycloak::Admin.get_clients({ clientId: Keycloak::Client.client_id }, token["access_token"])
- end
+ Keycloak.generic_request(token["access_token"],
+ Keycloak::Admin.full_url("clients/#{client[0]['id']}/roles"),
+ nil, nil, 'GET')
+ }
- protected
+ default_call(proc)
+ end
- def self.default_call(proc)
- begin
- tk = nil
- resp = nil
+ def self.get_client_user_roles(userID)
+ proc = lambda {|token|
+ client = JSON Keycloak::Admin.get_clients({ clientId: Keycloak::Client.client_id }, token["access_token"])
+ Keycloak::Admin.get_effective_client_level_role_composite_user(userID, client[0]['id'], token["access_token"])
+ }
- Keycloak::Client.get_installation
+ default_call(proc)
+ end
- payload = {'client_id' => Keycloak::Client.client_id,
- 'client_secret' => Keycloak::Client.secret,
- 'grant_type' => 'client_credentials'
- }
+ def self.has_role?(userID, userRole)
+ roles = JSON get_client_user_roles(userID)
+ if !roles.nil?
+ roles.each do |role|
+ return true if role['name'].to_s == userRole.to_s
+ end
+ false
+ else
+ false
+ end
+ end
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
+ protected
- _request = -> do
- RestClient.post(Keycloak::Client.configuration['token_endpoint'], payload, header){|response, request, result|
- case response.code
- when 200..399
- tk = JSON response.body
- resp = proc.call(tk)
- else
- response.return!
- end
- }
- end
+ def self.default_call(proc)
+ begin
+ tk = nil
+ resp = nil
- Keycloak::Client.exec_request _request
- ensure
- if tk
- payload = {'client_id' => Keycloak::Client.client_id,
- 'client_secret' => Keycloak::Client.secret,
- 'refresh_token' => tk["refresh_token"]
- }
+ Keycloak::Client.get_installation
- header = {'Content-Type' => 'application/x-www-form-urlencoded'}
- _request = -> do
- RestClient.post(Keycloak::Client.configuration['end_session_endpoint'], payload, header){|response, request, result|
- case response.code
- when 200..399
- resp if resp.nil?
- else
- response.return!
- end
- }
- end
- Keycloak::Client.exec_request _request
- end
- end
- end
+ payload = { 'client_id' => Keycloak::Client.client_id,
+ 'client_secret' => Keycloak::Client.secret,
+ 'grant_type' => 'client_credentials' }
- end
+ header = {'Content-Type' => 'application/x-www-form-urlencoded'}
- private
+ _request = -> do
+ RestClient.post(Keycloak::Client.configuration['token_endpoint'], payload, header){|response, request, result|
+ case response.code
+ when 200..399
+ tk = JSON response.body
+ resp = proc.call(tk)
+ else
+ response.return!
+ end
+ }
+ end
- def self.generic_request(accessToken, uri, queryParameters, bodyParameter, method)
- Keycloak::Client.verify_setup
- final_url = uri
+ Keycloak::Client.exec_request _request
+ ensure
+ if tk
+ payload = { 'client_id' => Keycloak::Client.client_id,
+ 'client_secret' => Keycloak::Client.secret,
+ 'refresh_token' => tk["refresh_token"] }
- header = {'Content-Type' => 'application/x-www-form-urlencoded',
- 'Authorization' => "Bearer #{accessToken}"}
+ header = {'Content-Type' => 'application/x-www-form-urlencoded'}
+ _request = -> do
+ RestClient.post(Keycloak::Client.configuration['end_session_endpoint'], payload, header){|response, request, result|
+ case response.code
+ when 200..399
+ resp if resp.nil?
+ else
+ response.return!
+ end
+ }
+ end
+ Keycloak::Client.exec_request _request
+ end
+ end
+ end
- if queryParameters
- parameters = URI.encode_www_form(queryParameters)
- final_url = final_url << '?' << parameters
- end
+ end
- case method.upcase
- when 'GET'
- _request = -> do
- RestClient.get(final_url, header){|response, request, result|
- rescue_response(response)
- }
- end
- when 'POST', 'PUT'
- header["Content-Type"] = 'application/json'
- parameters = JSON.generate bodyParameter
- _request = -> do
- case method.upcase
- when 'POST'
- RestClient.post(final_url, parameters, header){|response, request, result|
- rescue_response(response)
- }
- else
- RestClient.put(final_url, parameters, header){|response, request, result|
- rescue_response(response)
- }
- end
- end
- when 'DELETE'
- _request = -> do
- if bodyParameter
- header["Content-Type"] = 'application/json'
- parameters = JSON.generate bodyParameter
- RestClient::Request.execute(method: :delete, url: final_url,
- payload: parameters, headers: header){|response, request, result|
- rescue_response(response)
- }
- else
- RestClient.delete(final_url, header){|response, request, result|
- rescue_response(response)
- }
- end
- end
- else
- raise
- end
+ private
- _request.call
+ def self.generic_request(accessToken, uri, queryParameters, bodyParameter, method)
+ Keycloak::Client.verify_setup
+ final_url = uri
- end
+ header = {'Content-Type' => 'application/x-www-form-urlencoded',
+ 'Authorization' => "Bearer #{accessToken}"}
- def self.rescue_response(response)
- case response.code
- when 200..399
- if response.body.empty?
- true
- else
- response.body
- end
- else
- if Keycloak.explode_exception
- response.return!
- else
- begin
- response.return!
- rescue RestClient::ExceptionWithResponse => err
- err.response
- rescue Exception => e
- e.message
- end
- end
- end
- end
+ if queryParameters
+ parameters = URI.encode_www_form(queryParameters)
+ final_url = final_url << '?' << parameters
+ end
+ case method.upcase
+ when 'GET'
+ _request = -> do
+ RestClient.get(final_url, header){|response, request, result|
+ rescue_response(response)
+ }
+ end
+ when 'POST', 'PUT'
+ header["Content-Type"] = 'application/json'
+ parameters = JSON.generate bodyParameter
+ _request = -> do
+ case method.upcase
+ when 'POST'
+ RestClient.post(final_url, parameters, header){|response, request, result|
+ rescue_response(response)
+ }
+ else
+ RestClient.put(final_url, parameters, header){|response, request, result|
+ rescue_response(response)
+ }
+ end
+ end
+ when 'DELETE'
+ _request = -> do
+ if bodyParameter
+ header["Content-Type"] = 'application/json'
+ parameters = JSON.generate bodyParameter
+ RestClient::Request.execute(method: :delete, url: final_url,
+ payload: parameters, headers: header) { |response, request, result|
+ rescue_response(response)
+ }
+ else
+ RestClient.delete(final_url, header) { |response, request, result|
+ rescue_response(response)
+ }
+ end
+ end
+ else
+ raise
+ end
+
+ _request.call
+
+ end
+
+ def self.rescue_response(response)
+ case response.code
+ when 200..399
+ if response.body.empty?
+ true
+ else
+ response.body
+ end
+ else
+ if Keycloak.explode_exception
+ response.return!
+ else
+ begin
+ response.return!
+ rescue RestClient::ExceptionWithResponse => err
+ err.response
+ rescue StandardError => e
+ e.message
+ end
+ end
+ end
+ end
end
require 'keycloak/exceptions'
\ No newline at end of file