keycloak 2.2.1 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +175 -6
- data/lib/keycloak.rb +109 -109
- data/lib/keycloak/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4049ff4cd3aa28843c716f1087015fe93b8f293
|
4
|
+
data.tar.gz: dfd32b98b0dde41107f0dbd9b93c0031bf76fc47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b14927bbff9d4213c5b36cb0ebe5d78b887d1106183a71a363c8996b972fc3f32481ec7d3986658f3326b5a7764e9af7619e52d29f4fa188fdbe79f3075e5158
|
7
|
+
data.tar.gz: a21406c6aa9ed8406c86dc8a256a323c671173ef042a2d4229e24fc9679b3692d58c18c1e5cb6c39184f88ac4f1288ee899310be6bdd5424f01dea17a00066a4
|
data/README.md
CHANGED
@@ -3,22 +3,191 @@ A gem Keycloak foi desenvolvida para integrar aplicações e serviços ao sistem
|
|
3
3
|
|
4
4
|
O seu desenvolvimento foi baseado na versão 3.2 do Keycloak, cuja documentação pode ser encontrada [aqui](http://www.keycloak.org/archive/documentation-3.2.html).
|
5
5
|
|
6
|
-
##
|
6
|
+
## Instalação
|
7
7
|
|
8
|
-
|
8
|
+
Adicione esta linha no <b>Gemfile</b> de sua aplicação:
|
9
9
|
|
10
10
|
```ruby
|
11
11
|
gem 'keycloak'
|
12
12
|
```
|
13
13
|
|
14
|
-
|
14
|
+
Então execute:
|
15
15
|
|
16
16
|
$ bundle
|
17
17
|
|
18
|
-
|
18
|
+
Ou instale você mesmo:
|
19
19
|
|
20
20
|
$ gem install keycloak
|
21
21
|
|
22
|
-
##
|
22
|
+
## Utilização
|
23
23
|
|
24
|
-
|
24
|
+
Considerando que você já possua um ambiente do Keycloak configurado e a gem já instalada, o próximo passo é definir como será a autenticação da aplicação. O Keycloak trabalha com os principais protocolos de autenticação, tais como o OpenID Connect, Oauth 2.0 e SAML 2.0, integrando acesso a sistemas via Single-Sign On, podendo inclusive disponibilizar acessos a usuários LDAP ou Active Directory.
|
25
|
+
|
26
|
+
Ao cadastrar um Reino e também um Client no seu ambiente Keycloak, será necessário fazer o download do arquivo de instalação do Client para dentro da pasta raiz da aplicação, para que a gem obtenha as informações necessárias para interagir com o Keycloak. Para fazer esse download, basta acessar o cadastro de seu Client, clicar na aba <b>Installation</b>, selecionar <b>Keycloak OIDC JSON</b> no campo <b>Format option</b> e clicar em <b>Download</b>.
|
27
|
+
|
28
|
+
A gem possui um módulo principal chamado <b>Keycloak</b>. Dentro desse módulo há três outros módulos: <b>Client</b>, <b>Admin</b> e <b>Internal</b>.
|
29
|
+
|
30
|
+
### Module Keycloak
|
31
|
+
|
32
|
+
O módulo Keycloak possui alguns atributos e suas definições são fundamentais para o perfeito funcionamento da gem na aplicação.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Keycloak.proxy
|
36
|
+
```
|
37
|
+
|
38
|
+
Caso o ambiente onde a sua aplicação será utilizada exija a utilização de proxy para o consumo das APIs do Keycloak, então defina-o neste atributo. Ao ser instalada, a gem cria o arquivo `keycloak.rb` em `config/initializers`. Este atributo pode ser encontrado e definido nesse arquivo.
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
Keycloak.generate_request_exception
|
42
|
+
```
|
43
|
+
|
44
|
+
Este atributo serve para definir se as exceções HTTP geradas nos retornos das requisições feitas para o Keycloak serão ou não estouradas na aplicação. Caso definido como `false`, então a exceção não será estourada e a resposta HTTP será retornada para a aplicação fazer o seu próprio tratamento. O valor default deste atributo é `true`. Ao ser instalada, a gem cria o arquivo `keycloak.rb` em `config/initializers`. Este atributo pode ser encontrado e definido nesse arquivo.
|
45
|
+
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
Keycloak.keycloak_controller
|
49
|
+
```
|
50
|
+
|
51
|
+
É recomendado que a sua aplicação possua um controller que centraliza as ações de sessão que o Keycloak irá gerenciar, tais como a ação de login, logout, atualização de sessão, reset de senha, entre outras. Defina neste atributo qual é o nome do controller que desempenhará esse papel. Se o nome do seu controler é `SessionController`, então o valor deste atributo deverá ser apenas `session`. Ao ser instalada, a gem cria o arquivo `keycloak.rb` em `config/initializers`. Este atributo pode ser encontrado e definido nesse arquivo.
|
52
|
+
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
Keycloak.proc_cookie_token
|
56
|
+
```
|
57
|
+
|
58
|
+
Este atributo trata-se de um método anônimo (lâmbida). O mesmo deve ser implementado na aplicação para que a gem tenha acesso ao token de autenticação que, por sua vez, deverá ser armazenado no cookie. Ao realizar a autenticação no keycloak através da gem, o sistema deverá armazenar o token retornado no cookie do browser, como por exemplo:
|
59
|
+
```ruby
|
60
|
+
cookies.permanent[:keycloak_token] = Keycloak::Client.get_token(params[:user_login], params[:user_password])
|
61
|
+
```
|
62
|
+
A aplicação poderá recuperar o token no cookie implementando o método `Keycloak.proc_cookie_token` da seguinte forma:
|
63
|
+
```ruby
|
64
|
+
Keycloak.proc_cookie_token = -> do
|
65
|
+
cookies.permanent[:keycloak_token]
|
66
|
+
end
|
67
|
+
```
|
68
|
+
Desta forma, todas as vezes que a gem precisar utilizar as informações do token para consumir um serviço do Keycloak, ele irá invocar este método lâmbida.
|
69
|
+
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
Keycloak.proc_external_attributes
|
73
|
+
```
|
74
|
+
|
75
|
+
O Keycloak dá a possibilidade de que novos atributos sejam mapeados no cadastro de usuários. Porém, quando esses atributos são específicos da aplicação, recomenda-se que a própria os gerencie. Para isso, a melhor solução é criar esses atributos na aplicação - exemplo: criar uma tabela no banco de dados da própria aplicação contendo as colunas representando cada um dos atributos, inserindo também nessa tabela uma coluna de identificação única (unique key), contendo na mesma o Id do usuário criado no Keycloak, indicando que esse pertencente àquele Id possui aqueles atributos.
|
76
|
+
Para que a gem tenha acesso a esses atributos, definina o atributo`Keycloak.proc_external_attributes` com um método lâmbida obtendo do `model` os atributos do usuário logado. Exemplo:
|
77
|
+
```ruby
|
78
|
+
Keycloak.proc_external_attributes = -> do
|
79
|
+
atributos = UsuariosAtributo.find_or_create_by(user_keycloak_id: Keycloak::Client.get_attribute('sub'))
|
80
|
+
if atributos.status.nil?
|
81
|
+
atributos.status = false
|
82
|
+
atributos.save
|
83
|
+
end
|
84
|
+
atributos
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
<b>Observação:</b> Os atributos `Keycloak.proc_cookie_token` e `Keycloak.proc_external_attributes` podem ser definidos no `initialize` do controler `ApplicationController`.
|
89
|
+
|
90
|
+
|
91
|
+
### Client
|
92
|
+
|
93
|
+
Esse módulo possui os métodos que representam as APIs de <b>endpoints</b>. Esses serviços são fundamentais para a criação e atualização de tokens, efetuação de login e logout, e, também para a obtenção de informações sintéticas de um usuário logado. O que habilita a gem a fazer uso de todos esses serviços é o arquivo de instalação do client citado anteriormente.
|
94
|
+
|
95
|
+
Vamos ao detalhamento de cada um desses métodos:
|
96
|
+
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
Keycloak::Client.get_token(user, password)
|
100
|
+
```
|
101
|
+
|
102
|
+
Caso você opte por efetuar a autenticação dos usuários utilizando a tela da sua própria aplicação, então utilize esse método. Basta invocá-lo no método de login no `controller`definido com o controlador de sessão de sua aplicação, passando como parâmetro o <b>usuário</b> e a <b>senha</b> informados pelo usuário. Caso a autenticação seja válida, então será retornado um JSON contendo entre as informações principais o `access_token` e o `refresh_token`.
|
103
|
+
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
Keycloak::Client.url_login_redirect(redirect_uri, response_type = 'code')
|
107
|
+
```
|
108
|
+
|
109
|
+
Para efetuar a autenticação dos usuários de sua aplicação utilizando um template configurado no Keycloak, redirecione a requisição para a url retornada nesse método. Passe como parâmetro a url que o usuário terá acesso no caso de êxito na autenticação(`redirect_uri`) e também o tipo de resposta (`response_type`), que caso não informado, a gem assumirá o valor `code`. Caso a autenticação seja bem sucedida, então será retornado um `code` que te habilitará a requisitar um token ao Keycloak.
|
110
|
+
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
Keycloak::Client.get_token_by_code(code, redirect_uri)
|
114
|
+
```
|
115
|
+
|
116
|
+
Ao utilizar o método `Keycloak::Client.url_login_redirect` para obter um `code`, passe-o como parâmetro neste método para que o Keycloak retorne um token, efetuando assim o login do usuário na aplicação. O segundo parâmetro (`redirect_uri`) deve ser passado para que, ao disponibilizar um token, o Keycloak redirecione para a url informada.
|
117
|
+
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
Keycloak::Client.get_token_by_refresh_token(refresh_token = '')
|
121
|
+
```
|
122
|
+
|
123
|
+
Quando o usuário já estiver logado e a sua aplicação acompanhar internamente o tempo de expiração do token fornecido pelo Keycloak, então esse método poderá ser utilizado para a renovação desse token, caso o mesmo ainda seja válido. Para isso, basta passar como parãmetro o `refresh_token`. Caso não seja informado o `refresh_token`, a gem utilizará o `refresh_token` armazenado no cookie.
|
124
|
+
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
Keycloak::Client.get_token_introspection(token = '')
|
128
|
+
```
|
129
|
+
|
130
|
+
Esse método retorna a as informações da sessão do `token` passado como parâmetro. Entre as informações retornadas, a mais importante é o campo `active`, pois ele informa se a sessão do token passado no parâmetro é ativo ou não. Isso auxiliará a sua aplicação a controlar se a sessão do usuário logado expirou ou não. Caso nenhum token seja passado como parâmetro, a gem utilizará o último `access_token` armazenado no cookie da aplicação.
|
131
|
+
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
Keycloak::Client.get_token_by_client_credentials(client_id = '', secret = '')
|
135
|
+
```
|
136
|
+
|
137
|
+
Há alguns serviços do Keycloak como <b>reset de senha</b>, <b>cadastro de usuário</b> na tela inicial da aplicação ou até mesmo autenticação seguindo o padrão <b>OAuth 2.0</b>, que a autenticação de um usuário torna-se desnecessária. Sendo assim, podemos obter um token utilizando as credenciais da sua própria aplicação (Client) cadastrada no Keycloak. Para obter esse token, deve-se passar como parâmetro desse método o `client_id` - informado pela pessoa que cadastrou sua aplicação no Keycloak - e a `secret` de sua aplicação gerado pelo Keycloak - para gerar uma `secret`, o <b>Access Type</b> do seu Client (Aplicação) deverá estar configurado como `confidential`. Caso você não passe nenhum desses parãmetros, a gem utilizará as credenciais contidas no arquivo de instalação citado anteriormente.
|
138
|
+
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
Keycloak::Client.logout(redirect_uri = '', refresh_token = '')
|
142
|
+
```
|
143
|
+
|
144
|
+
Quando utilizado antes da expiração da sessão do usuário logado, esse método encerra a sessão. Se o prâmetro `redirect_uri` for alimentado, então o Keycloak redirecionará a sua aplicação para a url informada após a efetuação do logout. O segundo parâmetro é o `refresh_token` obtido no momento da autenticação ou da atualização da sessão. Caso este último não seja informado, então a gem utilizará o `refresh_token` do cookie.
|
145
|
+
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
Keycloak::Client.get_userinfo(access_token = '')
|
149
|
+
```
|
150
|
+
|
151
|
+
Esse método retorna informações sintéticas do usuário representado pelo `access_token` passado como parâmetro, tais como `sub` - que é o Id do usuário autenticado -, `preferred_username` - que é o nome do usuário autenticado - e `email` - que é o e-mail do usuário. Cado o parâmetro `access_token` não seja informado, então a gem obterá essa informação no cookie.
|
152
|
+
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
Keycloak::Client.url_user_account
|
156
|
+
```
|
157
|
+
|
158
|
+
Retorna a <b>url</b> para acesso ao cadastro de usuários do Reino do arquivo de instalação (`keycloak.json`). Para ter acesso a tela, o Keycloak exigirá a autenticação do usuário. Após logado, e caso tenha permissão, o usuário terá acesso a suas informações cadastrais podendo inclusive alterá-las.
|
159
|
+
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
Keycloak::Client.has_role?(user_role, access_token = '')
|
163
|
+
```
|
164
|
+
|
165
|
+
O método `has_role?` decodifica o JWT `access_token` e verifica se o usuário dono do token possui o <b>role</b> informado no parâmetro `user_role`. Caso o `access_token` não seja informado, então a gem utilizará o `access_token` do cookie.
|
166
|
+
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
Keycloak::Client.user_signed_in?(access_token = '')
|
170
|
+
```
|
171
|
+
|
172
|
+
Esse método verifica se o `access_token` passado no parâmetro ainda está ativo. Para verificar se o usuário está ativo ou não, internamente a gem invoca o método `get_token_introspection`. Caso o `access_token` não seja informado, então a gem utilizará o `access_token` do cookie.
|
173
|
+
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
Keycloak::Client.get_attribute(attribute_name, access_token = '')
|
177
|
+
```
|
178
|
+
|
179
|
+
Esse método decodifica o JWT `access_token` e retorna o valor do atributo de nome passado no parâmetro `attribute_name`. Esse atributo pode ser um <b>mapper</b> - cadastrado na seção <b>Mappers</b> do cadastro do <b>Client</b> do Reino. Caso o `access_token` não seja informado, então a gem utilizará o `access_token` do cookie.
|
180
|
+
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
Keycloak::Client.token
|
184
|
+
```
|
185
|
+
|
186
|
+
Retorna o último token autenticado armazenado no cookie. Quando na aplicação é implementado o método `Keycloak.proc_cookie_token` e um usuário faz a autenticação da aplicação, esse método retornará o token desse usuário.
|
187
|
+
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
Keycloak::Client.external_attributes
|
191
|
+
```
|
192
|
+
|
193
|
+
Quando implementado o método `Keycloak.proc_external_attributes`, o método `external_attributes` o retornará. A finalidade desse método é retornar os atributos específicos da aplicação não mapeados no Keycloak.
|
data/lib/keycloak.rb
CHANGED
@@ -51,14 +51,14 @@ module Keycloak
|
|
51
51
|
mount_request_token(payload)
|
52
52
|
end
|
53
53
|
|
54
|
-
def self.get_token_by_refresh_token(
|
54
|
+
def self.get_token_by_refresh_token(refresh_token = '')
|
55
55
|
verify_setup
|
56
56
|
|
57
|
-
|
57
|
+
refresh_token = self.token['refresh_token'] if refresh_token.empty?
|
58
58
|
|
59
59
|
payload = { 'client_id' => @client_id,
|
60
60
|
'client_secret' => @secret,
|
61
|
-
'refresh_token' =>
|
61
|
+
'refresh_token' => refresh_token,
|
62
62
|
'grant_type' => 'refresh_token' }
|
63
63
|
|
64
64
|
mount_request_token(payload)
|
@@ -149,12 +149,12 @@ module Keycloak
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
-
def self.get_userinfo(
|
152
|
+
def self.get_userinfo(access_token = '')
|
153
153
|
verify_setup
|
154
154
|
|
155
|
-
|
155
|
+
access_token = self.token["access_token"] if access_token.empty?
|
156
156
|
|
157
|
-
payload = { 'access_token' =>
|
157
|
+
payload = { 'access_token' => access_token }
|
158
158
|
|
159
159
|
header = { 'Content-Type' => 'application/x-www-form-urlencoded' }
|
160
160
|
|
@@ -178,15 +178,15 @@ module Keycloak
|
|
178
178
|
"#{@url}/realms/#{@realm}/account"
|
179
179
|
end
|
180
180
|
|
181
|
-
def self.has_role?(
|
181
|
+
def self.has_role?(user_role, access_token = '')
|
182
182
|
verify_setup
|
183
183
|
|
184
|
-
if user_signed_in?(
|
185
|
-
dt = decoded_access_token(
|
184
|
+
if user_signed_in?(access_token)
|
185
|
+
dt = decoded_access_token(access_token)[0]
|
186
186
|
dt = dt["resource_access"][@client_id]
|
187
187
|
if dt != nil
|
188
188
|
dt["roles"].each do |role|
|
189
|
-
return true if role.to_s ==
|
189
|
+
return true if role.to_s == user_role.to_s
|
190
190
|
end
|
191
191
|
false
|
192
192
|
else
|
@@ -197,11 +197,11 @@ module Keycloak
|
|
197
197
|
end
|
198
198
|
end
|
199
199
|
|
200
|
-
def self.user_signed_in?(
|
200
|
+
def self.user_signed_in?(access_token = '')
|
201
201
|
verify_setup
|
202
202
|
|
203
203
|
begin
|
204
|
-
JSON(get_token_introspection(
|
204
|
+
JSON(get_token_introspection(access_token))['active'] === true
|
205
205
|
rescue => e
|
206
206
|
if e.class < Keycloak::KeycloakException
|
207
207
|
raise
|
@@ -211,10 +211,10 @@ module Keycloak
|
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
214
|
-
def self.get_attribute(attributeName,
|
214
|
+
def self.get_attribute(attributeName, access_token = '')
|
215
215
|
verify_setup
|
216
216
|
|
217
|
-
attr = decoded_access_token(
|
217
|
+
attr = decoded_access_token(access_token)[0]
|
218
218
|
attr[attributeName]
|
219
219
|
end
|
220
220
|
|
@@ -306,14 +306,14 @@ module Keycloak
|
|
306
306
|
exec_request _request
|
307
307
|
end
|
308
308
|
|
309
|
-
def self.decoded_access_token(
|
310
|
-
|
311
|
-
JWT.decode
|
309
|
+
def self.decoded_access_token(access_token = '')
|
310
|
+
access_token = self.token["access_token"] if access_token.empty?
|
311
|
+
JWT.decode access_token, @public_key, false, { :algorithm => 'RS256' }
|
312
312
|
end
|
313
313
|
|
314
|
-
def self.decoded_refresh_token(
|
315
|
-
|
316
|
-
JWT.decode
|
314
|
+
def self.decoded_refresh_token(refresh_token = '')
|
315
|
+
refresh_token = self.token["access_token"] if refresh_token.empty?
|
316
|
+
JWT.decode refresh_token, @public_key, false, { :algorithm => 'RS256' }
|
317
317
|
end
|
318
318
|
|
319
319
|
def self.decoded_id_token(idToken = '')
|
@@ -331,97 +331,97 @@ module Keycloak
|
|
331
331
|
class << self
|
332
332
|
end
|
333
333
|
|
334
|
-
def self.get_users(
|
335
|
-
generic_get("users/",
|
334
|
+
def self.get_users(query_parameters = nil, access_token = nil)
|
335
|
+
generic_get("users/", query_parameters, access_token)
|
336
336
|
end
|
337
337
|
|
338
|
-
def self.create_user(
|
339
|
-
generic_post("users/", nil,
|
338
|
+
def self.create_user(user_representation, access_token = nil)
|
339
|
+
generic_post("users/", nil, user_representation, access_token)
|
340
340
|
end
|
341
341
|
|
342
|
-
def self.count_users(
|
343
|
-
generic_get("users/count/", nil,
|
342
|
+
def self.count_users(access_token = nil)
|
343
|
+
generic_get("users/count/", nil, access_token)
|
344
344
|
end
|
345
345
|
|
346
|
-
def self.get_user(id,
|
347
|
-
generic_get("users/#{id}", nil,
|
346
|
+
def self.get_user(id, access_token = nil)
|
347
|
+
generic_get("users/#{id}", nil, access_token)
|
348
348
|
end
|
349
349
|
|
350
|
-
def self.update_user(id,
|
351
|
-
generic_put("users/#{id}", nil,
|
350
|
+
def self.update_user(id, user_representation, access_token = nil)
|
351
|
+
generic_put("users/#{id}", nil, user_representation, access_token)
|
352
352
|
end
|
353
353
|
|
354
|
-
def self.delete_user(id,
|
355
|
-
generic_delete("users/#{id}", nil, nil,
|
354
|
+
def self.delete_user(id, access_token = nil)
|
355
|
+
generic_delete("users/#{id}", nil, nil, access_token)
|
356
356
|
end
|
357
357
|
|
358
|
-
def self.revoke_consent_user(id,
|
359
|
-
if
|
360
|
-
|
358
|
+
def self.revoke_consent_user(id, client_id = nil, access_token = nil)
|
359
|
+
if client_id.nil?
|
360
|
+
client_id = Keycloak::Client.client_id
|
361
361
|
end
|
362
|
-
generic_delete("users/#{id}/consents/#{
|
362
|
+
generic_delete("users/#{id}/consents/#{client_id}", nil, nil, access_token)
|
363
363
|
end
|
364
364
|
|
365
|
-
def self.update_account_email(id, actions,
|
366
|
-
if
|
367
|
-
|
365
|
+
def self.update_account_email(id, actions, redirect_uri = '', client_id = nil, access_token = nil)
|
366
|
+
if client_id.nil?
|
367
|
+
client_id = Keycloak::Client.client_id
|
368
368
|
end
|
369
|
-
generic_put("users/#{id}/execute-actions-email", {:redirect_uri =>
|
369
|
+
generic_put("users/#{id}/execute-actions-email", {:redirect_uri => redirect_uri, :client_id => client_id}, actions, access_token)
|
370
370
|
end
|
371
371
|
|
372
|
-
def self.get_role_mappings(id,
|
373
|
-
generic_get("users/#{id}/role-mappings", nil,
|
372
|
+
def self.get_role_mappings(id, access_token = nil)
|
373
|
+
generic_get("users/#{id}/role-mappings", nil, access_token)
|
374
374
|
end
|
375
375
|
|
376
|
-
def self.get_clients(
|
377
|
-
generic_get("clients/",
|
376
|
+
def self.get_clients(query_parameters = nil, access_token = nil)
|
377
|
+
generic_get("clients/", query_parameters, access_token)
|
378
378
|
end
|
379
379
|
|
380
|
-
def self.get_all_roles_client(id,
|
381
|
-
generic_get("clients/#{id}/roles", nil,
|
380
|
+
def self.get_all_roles_client(id, access_token = nil)
|
381
|
+
generic_get("clients/#{id}/roles", nil, access_token)
|
382
382
|
end
|
383
383
|
|
384
|
-
def self.get_roles_client_by_name(id,
|
385
|
-
generic_get("clients/#{id}/roles/#{
|
384
|
+
def self.get_roles_client_by_name(id, role_name, access_token = nil)
|
385
|
+
generic_get("clients/#{id}/roles/#{role_name}", nil, access_token)
|
386
386
|
end
|
387
387
|
|
388
|
-
def self.add_client_level_roles_to_user(id, client,
|
389
|
-
generic_post("users/#{id}/role-mappings/clients/#{client}", nil,
|
388
|
+
def self.add_client_level_roles_to_user(id, client, role_representation, access_token = nil)
|
389
|
+
generic_post("users/#{id}/role-mappings/clients/#{client}", nil, role_representation, access_token)
|
390
390
|
end
|
391
391
|
|
392
|
-
def self.delete_client_level_roles_from_user(id, client,
|
393
|
-
generic_delete("users/#{id}/role-mappings/clients/#{client}", nil,
|
392
|
+
def self.delete_client_level_roles_from_user(id, client, role_representation, access_token = nil)
|
393
|
+
generic_delete("users/#{id}/role-mappings/clients/#{client}", nil, role_representation, access_token)
|
394
394
|
end
|
395
395
|
|
396
|
-
def self.get_client_level_role_for_user_and_app(id, client,
|
397
|
-
generic_get("users/#{id}/role-mappings/clients/#{client}", nil,
|
396
|
+
def self.get_client_level_role_for_user_and_app(id, client, access_token = nil)
|
397
|
+
generic_get("users/#{id}/role-mappings/clients/#{client}", nil, access_token)
|
398
398
|
end
|
399
399
|
|
400
|
-
def self.update_effective_user_roles(id,
|
401
|
-
client = JSON get_clients({ clientId:
|
400
|
+
def self.update_effective_user_roles(id, client_id, rolesNames, access_token = nil)
|
401
|
+
client = JSON get_clients({ clientId: client_id })
|
402
402
|
|
403
|
-
|
403
|
+
user_roles = JSON get_client_level_role_for_user_and_app(id, client[0]['id'], access_token)
|
404
404
|
|
405
405
|
roles = Array.new
|
406
406
|
# Include new role
|
407
407
|
rolesNames.each do |r|
|
408
408
|
if r && !r.empty?
|
409
409
|
found = false
|
410
|
-
|
410
|
+
user_roles.each do |ur|
|
411
411
|
found = ur['name'] == r
|
412
412
|
break if found
|
413
413
|
found = false
|
414
414
|
end
|
415
415
|
if !found
|
416
|
-
role = JSON get_roles_client_by_name(client[0]['id'], r,
|
416
|
+
role = JSON get_roles_client_by_name(client[0]['id'], r, access_token)
|
417
417
|
roles.push(role)
|
418
418
|
end
|
419
419
|
end
|
420
420
|
end
|
421
421
|
|
422
|
-
|
422
|
+
garbage_roles = Array.new
|
423
423
|
# Exclude old role
|
424
|
-
|
424
|
+
user_roles.each do |ur|
|
425
425
|
found = false
|
426
426
|
rolesNames.each do |r|
|
427
427
|
if r && !r.empty?
|
@@ -431,43 +431,43 @@ module Keycloak
|
|
431
431
|
end
|
432
432
|
end
|
433
433
|
if !found
|
434
|
-
|
434
|
+
garbage_roles.push(ur)
|
435
435
|
end
|
436
436
|
end
|
437
437
|
|
438
|
-
if
|
439
|
-
delete_client_level_roles_from_user(id, client[0]['id'],
|
438
|
+
if garbage_roles.count > 0
|
439
|
+
delete_client_level_roles_from_user(id, client[0]['id'], garbage_roles, access_token)
|
440
440
|
end
|
441
441
|
|
442
442
|
if roles.count > 0
|
443
|
-
add_client_level_roles_to_user(id, client[0]['id'], roles,
|
443
|
+
add_client_level_roles_to_user(id, client[0]['id'], roles, access_token)
|
444
444
|
end
|
445
445
|
end
|
446
446
|
|
447
|
-
def self.reset_password(id, credentialRepresentation,
|
448
|
-
generic_put("users/#{id}/reset-password", nil, credentialRepresentation,
|
447
|
+
def self.reset_password(id, credentialRepresentation, access_token = nil)
|
448
|
+
generic_put("users/#{id}/reset-password", nil, credentialRepresentation, access_token)
|
449
449
|
end
|
450
450
|
|
451
|
-
def self.get_effective_client_level_role_composite_user(id, client,
|
452
|
-
generic_get("users/#{id}/role-mappings/clients/#{client}/composite", nil,
|
451
|
+
def self.get_effective_client_level_role_composite_user(id, client, access_token = nil)
|
452
|
+
generic_get("users/#{id}/role-mappings/clients/#{client}/composite", nil, access_token)
|
453
453
|
end
|
454
454
|
|
455
455
|
# Generics methods
|
456
456
|
|
457
|
-
def self.generic_get(service,
|
458
|
-
Keycloak.generic_request(effective_access_token(
|
457
|
+
def self.generic_get(service, query_parameters = nil, access_token = nil)
|
458
|
+
Keycloak.generic_request(effective_access_token(access_token), full_url(service), query_parameters, nil, 'GET')
|
459
459
|
end
|
460
460
|
|
461
|
-
def self.generic_post(service,
|
462
|
-
Keycloak.generic_request(effective_access_token(
|
461
|
+
def self.generic_post(service, query_parameters, body_parameter, access_token = nil)
|
462
|
+
Keycloak.generic_request(effective_access_token(access_token), full_url(service), query_parameters, body_parameter, 'POST')
|
463
463
|
end
|
464
464
|
|
465
|
-
def self.generic_put(service,
|
466
|
-
Keycloak.generic_request(effective_access_token(
|
465
|
+
def self.generic_put(service, query_parameters, body_parameter, access_token = nil)
|
466
|
+
Keycloak.generic_request(effective_access_token(access_token), full_url(service), query_parameters, body_parameter, 'PUT')
|
467
467
|
end
|
468
468
|
|
469
|
-
def self.generic_delete(service,
|
470
|
-
Keycloak.generic_request(effective_access_token(
|
469
|
+
def self.generic_delete(service, query_parameters = nil, body_parameter = nil, access_token = nil)
|
470
|
+
Keycloak.generic_request(effective_access_token(access_token), full_url(service), query_parameters, body_parameter, 'DELETE')
|
471
471
|
end
|
472
472
|
|
473
473
|
private
|
@@ -496,19 +496,19 @@ module Keycloak
|
|
496
496
|
class << self
|
497
497
|
end
|
498
498
|
|
499
|
-
def self.get_users(
|
499
|
+
def self.get_users(query_parameters = nil)
|
500
500
|
proc = lambda {|token|
|
501
|
-
Keycloak::Admin.get_users(
|
501
|
+
Keycloak::Admin.get_users(query_parameters, token["access_token"])
|
502
502
|
}
|
503
503
|
|
504
504
|
default_call(proc)
|
505
505
|
end
|
506
506
|
|
507
|
-
def self.change_password(
|
507
|
+
def self.change_password(user_id, redirect_uri = '')
|
508
508
|
proc = lambda {|token|
|
509
509
|
Keycloak.generic_request(token["access_token"],
|
510
|
-
Keycloak::Admin.full_url("users/#{
|
511
|
-
{:redirect_uri =>
|
510
|
+
Keycloak::Admin.full_url("users/#{user_id}/execute-actions-email"),
|
511
|
+
{:redirect_uri => redirect_uri, :client_id => Keycloak::Client.client_id},
|
512
512
|
['UPDATE_PASSWORD'],
|
513
513
|
'PUT')
|
514
514
|
}
|
@@ -516,9 +516,9 @@ module Keycloak
|
|
516
516
|
default_call(proc)
|
517
517
|
end
|
518
518
|
|
519
|
-
def self.forgot_password(
|
520
|
-
user = get_user_info(
|
521
|
-
change_password(user['id'],
|
519
|
+
def self.forgot_password(user_login, redirect_uri = '')
|
520
|
+
user = get_user_info(user_login, true)
|
521
|
+
change_password(user['id'], redirect_uri)
|
522
522
|
end
|
523
523
|
|
524
524
|
def self.get_logged_user_info
|
@@ -532,12 +532,12 @@ module Keycloak
|
|
532
532
|
default_call(proc)
|
533
533
|
end
|
534
534
|
|
535
|
-
def self.get_user_info(
|
535
|
+
def self.get_user_info(user_login, whole_word = false)
|
536
536
|
proc = lambda { |token|
|
537
|
-
if
|
538
|
-
search = {:username =>
|
537
|
+
if user_login.index('@').nil?
|
538
|
+
search = {:username => user_login}
|
539
539
|
else
|
540
|
-
search = {:email =>
|
540
|
+
search = {:email => user_login}
|
541
541
|
end
|
542
542
|
users = JSON Keycloak.generic_request(token["access_token"],
|
543
543
|
Keycloak::Admin.full_url("users/"),
|
@@ -548,8 +548,8 @@ module Keycloak
|
|
548
548
|
else
|
549
549
|
efective_index = -1
|
550
550
|
users.each_with_index do |user, i|
|
551
|
-
if
|
552
|
-
efective_index = i if
|
551
|
+
if whole_word
|
552
|
+
efective_index = i if user_login == user['username'] || user_login == user['email']
|
553
553
|
else
|
554
554
|
efective_index = 0
|
555
555
|
end
|
@@ -557,7 +557,7 @@ module Keycloak
|
|
557
557
|
end
|
558
558
|
|
559
559
|
if efective_index >= 0
|
560
|
-
if
|
560
|
+
if whole_word
|
561
561
|
users[efective_index]
|
562
562
|
else
|
563
563
|
users
|
@@ -576,9 +576,9 @@ module Keycloak
|
|
576
576
|
info['federationLink'] != nil
|
577
577
|
end
|
578
578
|
|
579
|
-
def self.create_starter_user(
|
579
|
+
def self.create_starter_user(username, password, email, client_roles_names, proc = nil)
|
580
580
|
begin
|
581
|
-
user = get_user_info(
|
581
|
+
user = get_user_info(username, true)
|
582
582
|
newUser = false
|
583
583
|
rescue Keycloak::UserLoginNotFound
|
584
584
|
newUser = true
|
@@ -587,7 +587,7 @@ module Keycloak
|
|
587
587
|
end
|
588
588
|
|
589
589
|
proc_default = lambda { |token|
|
590
|
-
user_representation = { username:
|
590
|
+
user_representation = { username: username,
|
591
591
|
email: email,
|
592
592
|
enabled: true }
|
593
593
|
|
@@ -595,7 +595,7 @@ module Keycloak
|
|
595
595
|
Keycloak::Admin.full_url("users/"),
|
596
596
|
nil, user_representation, 'POST')
|
597
597
|
|
598
|
-
user = get_user_info(
|
598
|
+
user = get_user_info(username, true) if newUser
|
599
599
|
|
600
600
|
credential_representation = { type: "password",
|
601
601
|
temporary: false,
|
@@ -610,7 +610,7 @@ module Keycloak
|
|
610
610
|
{ clientId: Keycloak::Client.client_id }, nil, 'GET')
|
611
611
|
|
612
612
|
roles = []
|
613
|
-
|
613
|
+
client_roles_names.each do |r|
|
614
614
|
if r.present?
|
615
615
|
role = JSON Keycloak.generic_request(token["access_token"],
|
616
616
|
Keycloak::Admin.full_url("clients/#{client[0]['id']}/roles/#{r}"),
|
@@ -646,20 +646,20 @@ module Keycloak
|
|
646
646
|
default_call(proc)
|
647
647
|
end
|
648
648
|
|
649
|
-
def self.get_client_user_roles(
|
649
|
+
def self.get_client_user_roles(user_id)
|
650
650
|
proc = lambda {|token|
|
651
651
|
client = JSON Keycloak::Admin.get_clients({ clientId: Keycloak::Client.client_id }, token["access_token"])
|
652
|
-
Keycloak::Admin.get_effective_client_level_role_composite_user(
|
652
|
+
Keycloak::Admin.get_effective_client_level_role_composite_user(user_id, client[0]['id'], token["access_token"])
|
653
653
|
}
|
654
654
|
|
655
655
|
default_call(proc)
|
656
656
|
end
|
657
657
|
|
658
|
-
def self.has_role?(
|
659
|
-
roles = JSON get_client_user_roles(
|
658
|
+
def self.has_role?(user_id, user_role)
|
659
|
+
roles = JSON get_client_user_roles(user_id)
|
660
660
|
if !roles.nil?
|
661
661
|
roles.each do |role|
|
662
|
-
return true if role['name'].to_s ==
|
662
|
+
return true if role['name'].to_s == user_role.to_s
|
663
663
|
end
|
664
664
|
false
|
665
665
|
else
|
@@ -721,15 +721,15 @@ module Keycloak
|
|
721
721
|
|
722
722
|
private
|
723
723
|
|
724
|
-
def self.generic_request(
|
724
|
+
def self.generic_request(access_token, uri, query_parameters, body_parameter, method)
|
725
725
|
Keycloak::Client.verify_setup
|
726
726
|
final_url = uri
|
727
727
|
|
728
728
|
header = {'Content-Type' => 'application/x-www-form-urlencoded',
|
729
|
-
'Authorization' => "Bearer #{
|
729
|
+
'Authorization' => "Bearer #{access_token}"}
|
730
730
|
|
731
|
-
if
|
732
|
-
parameters = URI.encode_www_form(
|
731
|
+
if query_parameters
|
732
|
+
parameters = URI.encode_www_form(query_parameters)
|
733
733
|
final_url = final_url << '?' << parameters
|
734
734
|
end
|
735
735
|
|
@@ -742,7 +742,7 @@ module Keycloak
|
|
742
742
|
end
|
743
743
|
when 'POST', 'PUT'
|
744
744
|
header["Content-Type"] = 'application/json'
|
745
|
-
parameters = JSON.generate
|
745
|
+
parameters = JSON.generate body_parameter
|
746
746
|
_request = -> do
|
747
747
|
case method.upcase
|
748
748
|
when 'POST'
|
@@ -757,9 +757,9 @@ module Keycloak
|
|
757
757
|
end
|
758
758
|
when 'DELETE'
|
759
759
|
_request = -> do
|
760
|
-
if
|
760
|
+
if body_parameter
|
761
761
|
header["Content-Type"] = 'application/json'
|
762
|
-
parameters = JSON.generate
|
762
|
+
parameters = JSON.generate body_parameter
|
763
763
|
RestClient::Request.execute(method: :delete, url: final_url,
|
764
764
|
payload: parameters, headers: header) { |response, request, result|
|
765
765
|
rescue_response(response)
|
data/lib/keycloak/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keycloak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guilherme Portugues
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|