keycloak-admin 0.7.7 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8be78b3854a7d3ac95ddb700599f49f8b108f2eda85de66df200aa5e362b7f5e
4
- data.tar.gz: 81103f2021f10e78c92327d7beace0ea30bc23175e3605c408e70f01a172203b
3
+ metadata.gz: 832e114e10e83ff18cfb5eaad1c157248da889b5041137ebf28fd30e610ee07d
4
+ data.tar.gz: e1151d727d5d6d8320db86024e7f10ad81f35a23dc13312aac065757e8664be5
5
5
  SHA512:
6
- metadata.gz: 83bda7a2b12cd6384710234618392aebfe0b29aa61378bf8350c8c8b3c70ad9725293f150c0074137351b21825cd3798d6ca180180a4b5d9c84909bef67a32b3
7
- data.tar.gz: c052198198d30a8978229dfc71d2d5cb0d26db94e22291e6286dea7d8133b2060d5d658f26fc5e7e5f4b9b35fc11f3dce0eff13c1451aa48e85ee2678e90fde6
6
+ metadata.gz: eae1ed6f49db46eec2b4463acbd7cf164948aeba4e672f30703f8724bb70d9d441ff469dfd0fa81645821d5d0bfb19ed0bd7376407026fa1467b66c20069c006
7
+ data.tar.gz: 26818a04afbc95c05e878881d1b7c38e336f5e18a926995390b5e629786c395807276e6ef18c466e61f1600e65cbdd6b4ea6f80ff6e3af5a3ea070c77f18c655
data/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+
9
+ ## [1.0.1] - 2021-10-14
10
+
11
+ * List all `Identity Providers`
12
+ * Add Group on Users (thanks to @tomuench)
13
+ * Remove Group from Users (thanks to @tomuench)
14
+
15
+ ## [1.0.0] - 2021-08-03
16
+
17
+ * Add `totp` on Users
18
+ * Add `required_actions` on Users
19
+
20
+ ## [0.7.9] - 2020-10-22
21
+
22
+ * Extend `search` function to use complex queries (thanks to @hobbypunk90)
23
+
24
+ ## [0.7.8] - 2020-10-15
25
+
26
+ * Bug: `rest_client_options` default value does not match the documentation (was `nil` by default, should be `{}`)
27
+ * Update documentation about client setup (based on Keycloak 11)
28
+
8
29
  ## [0.7.7] - 2020-07-10
9
30
 
10
31
  * Fix: `Replace request method shorthand with .execute for proper RestClient option support` (thanks to @RomanHargrave)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keycloak-admin (0.7.7)
4
+ keycloak-admin (1.0.1)
5
5
  http-cookie (~> 1.0, >= 1.0.3)
6
6
  rest-client (~> 2.0)
7
7
 
@@ -13,11 +13,11 @@ GEM
13
13
  domain_name (0.5.20190701)
14
14
  unf (>= 0.0.5, < 1.0.0)
15
15
  http-accept (1.7.0)
16
- http-cookie (1.0.3)
16
+ http-cookie (1.0.4)
17
17
  domain_name (~> 0.5)
18
18
  mime-types (3.3.1)
19
19
  mime-types-data (~> 3.2015)
20
- mime-types-data (3.2020.0512)
20
+ mime-types-data (3.2021.0704)
21
21
  netrc (0.11.0)
22
22
  rest-client (2.1.0)
23
23
  http-accept (>= 1.7.0, < 2.0)
data/README.md CHANGED
@@ -12,37 +12,59 @@ This gem *does not* require Rails.
12
12
  For example, using `bundle`, add this line to your Gemfile.
13
13
 
14
14
  ```ruby
15
- gem "keycloak-admin", "0.7.7"
15
+ gem "keycloak-admin", "1.0.1"
16
16
  ```
17
17
 
18
18
  ## Login
19
19
 
20
- You can choose your login process between two different login methods: `username/password` and `Account Service`.
21
-
22
- ### Login with username/password
23
-
24
- Using this login method requires to create a user (and her credentials).
25
- * In Keycloak
26
- * Make your client `confidential` or `public`
27
- * Do not check `Service Accounts Enabled`
28
- * In this gem's configuration
29
- * Set `use_service_account` to `false`
30
- * Setup `username` and `password`
31
- * Setup `client_secret` if your client is `confidential`
32
-
33
- ### Login with an Account Service
34
-
35
- Using a service account to use the REST Admin API does not require to create a dedicated user (http://www.keycloak.org/docs/2.5/server_admin/topics/clients/oidc/service-accounts.html).
36
-
37
- * In Keycloak
38
- * Make your client `confidential`
39
- * Check its toggle `Service Accounts Enabled`
40
- * Disable both `Standard Flow Enabled` and `Implicit Flow Enabled `
41
- * Enable `Direct Access Grants Enabled`
42
- * After saving this client, open the `Service Account Roles` and add relevant `realm-management.` client's roles. For instance: `view-users` if you want to search for users using this gem.
43
- * In this gem's configuration
20
+ To login on Keycloak's Admin API, you first need to setup a client.
21
+
22
+ Go to your realm administration page and open `Clients`. Then, click on the `Create` button.
23
+ On the first screen, enter:
24
+ * `Client ID`: _e.g. my-app-admin-client_
25
+ * `Client Protocol`: select `openid-connect`
26
+ * `Root URL`: let it blank
27
+
28
+ The next screen must be configured depending on how you want to authenticate:
29
+ * `username/password` with a user of the realm
30
+ * `Direct Access Grants` with a service account
31
+
32
+ ### Login with username/password (realm user)
33
+
34
+ * In Keycloak, during the client setup:
35
+ * `Access Type`: `public` or `confidential`
36
+ * `Service Accounts Enabled` (when `confidential`): `false`
37
+ * After saving your client, if you have chosen a `confidential` client, go to `Credentials` tab and copy the `Client Secret`
38
+
39
+ * In Keycloak, create a dedicated user (and her credentials):
40
+ * Go to `Users`
41
+ * Click on the `Add user` button
42
+ * Setup her mandatory information, depending on your realm's configuration
43
+ * On the `Credentials` tab, create her a password (toggle off `Temporary`)
44
+
45
+ * In this gem's configuration (see Section `Configuration`):
46
+ * Setup `username` and `password` according to your user's configuration
47
+ * Setup `client_id` with your `Client ID` (_e.g. my-app-admin-client_)
48
+ * If your client is `confidential`, copy its Client Secret to `client_secret`
49
+
50
+ ### Login with `Direct Access Grants` (Service account)
51
+
52
+ Using a service account to use the REST Admin API does not require to create a dedicated user (https://www.keycloak.org/docs/latest/server_admin/#_service_accounts).
53
+
54
+ * In Keycloak, during the client setup:
55
+ * `Access Type`: `confidential`
56
+ * `Service Accounts Enabled` (when `confidential`): `true`
57
+ * `Standard Flow Enabled`: `false`
58
+ * `Implicit Flow Enabled`: `false`
59
+ * `Direct Access Grants Enabled`: `true`
60
+ * After saving this client
61
+ * open the `Service Account Roles` and add relevant `realm-management.` client's roles. For instance: `view-users` if you want to search for users using this gem.
62
+ * open the `Credentials` tab and copy the `Client Secret`
63
+
64
+ * In this gem's configuration (see Section `Configuration`):
44
65
  * Set `use_service_account` to `true`
45
- * Setup `client_secret`
66
+ * Setup `client_id` with your `Client ID` (_e.g. my-app-admin-client_)
67
+ * Copy its Client Secret to `client_secret`
46
68
 
47
69
  ## Configuration
48
70
 
@@ -69,7 +91,8 @@ All options have a default value. However, all of them can be changed in your in
69
91
 
70
92
  | Option | Default Value | Type | Required? | Description | Example |
71
93
  | ---- | ----- | ------ | ----- | ------ | ----- |
72
- | `server_url` | `nil`| String | Required | The base url where your Keycloak server is located. This value can be retrieved in your Keycloak client configuration. | `server_domain` | `nil`| String | Required | Public domain that identify your authentication cookies. | `auth.service.io` |
94
+ | `server_url` | `nil` | String | Required | The base url where your Keycloak server is located (a URL that starts with `http` and that ends with `/auth`). This value can be retrieved in your Keycloak client configuration. | `http://auth:8080/auth`
95
+ | `server_domain` | `nil`| String | Required | Public domain that identify your authentication cookies. | `auth.service.io` |
73
96
  | `client_realm_name` | `""`| String | Required | Name of the realm that contains the admin client. | `master` |
74
97
  | `client_id` | `admin-cli`| String | Required | Client that should be used to access admin capabilities. | `api-cli` |
75
98
  | `client_secret` | `nil`| String | Optional | If your client is `confidential`, this parameter must be specified. | `4e3c481c-f823-4a6a-b8a7-bf8c86e3eac3` |
@@ -97,6 +120,9 @@ All options have a default value. However, all of them can be changed in your in
97
120
  * Get list of client role mappings for a user/group
98
121
  * Save client role mappings for a user/group
99
122
  * Save realm-level role mappings for a user/group
123
+ * Add a Group on a User
124
+ * Remove a Group from a User
125
+ * Get list of Identity Providers
100
126
  * Link/Unlink users to federated identity provider brokers
101
127
  * Execute actions emails
102
128
  * Send forgot passsword mail
@@ -122,10 +148,18 @@ KeycloakAdmin.realm("a_realm").users.get(user_id)
122
148
 
123
149
  Returns an array of `KeycloakAdmin::UserRepresentation`.
124
150
 
151
+ According to [the documentation](https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_users_resource):
152
+ * When providing a `String` parameter, this produces an arbitrary search string
153
+ * When providing a `Hash`, you can search for specific field (_e.g_ an email)
154
+
125
155
  ```ruby
126
156
  KeycloakAdmin.realm("a_realm").users.search("a_username_or_an_email")
127
157
  ```
128
158
 
159
+ ```ruby
160
+ KeycloakAdmin.realm("a_realm").users.search({ email: "john@doe.com" })
161
+ ```
162
+
129
163
  ### List all users in a realm
130
164
 
131
165
  Returns an array of `KeycloakAdmin::UserRepresentation`.
@@ -336,6 +370,16 @@ group_id = "3a63b5c0-ef8a-47fd-86ed-b5fead18d9b8"
336
370
  KeycloakAdmin.realm("a_realm").group(group_id).role_mapper.save_realm_level(role_list)
337
371
  ```
338
372
 
373
+ ### Get list of identity providers
374
+
375
+ Note: This client requires the `realm-management.view-identity-providers` role.
376
+
377
+ Returns an array of `KeycloakAdmin::IdentityProviderRepresentation`.
378
+
379
+ ```ruby
380
+ KeycloakAdmin.realm("a_realm").identity_providers.list
381
+ ```
382
+
339
383
  ## How to execute library tests
340
384
 
341
385
  From the `keycloak-admin-api` directory:
@@ -343,4 +387,5 @@ From the `keycloak-admin-api` directory:
343
387
  ```
344
388
  $ docker build . -t keycloak-admin:test
345
389
  $ docker run -v `pwd`:/usr/src/app/ keycloak-admin:test bundle exec rspec spec
346
- ```
390
+ ```
391
+
@@ -0,0 +1,31 @@
1
+ module KeycloakAdmin
2
+ class IdentityProviderClient < Client
3
+ def initialize(configuration, realm_client)
4
+ super(configuration)
5
+ raise ArgumentError.new("realm must be defined") unless realm_client.name_defined?
6
+ @realm_client = realm_client
7
+ end
8
+
9
+ def list
10
+ response = execute_http do
11
+ RestClient::Resource.new(identity_providers_url, @configuration.rest_client_options).get(headers)
12
+ end
13
+ JSON.parse(response).map { |provider_as_hash| IdentityProviderRepresentation.from_hash(provider_as_hash) }
14
+ end
15
+
16
+ def get(internal_id_or_alias=nil)
17
+ response = execute_http do
18
+ RestClient::Resource.new(identity_providers_url, @configuration.rest_client_options).get(headers)
19
+ end
20
+ IdentityProviderRepresentation.from_hash(JSON.parse(response))
21
+ end
22
+
23
+ def identity_providers_url(internal_id_or_alias=nil)
24
+ if internal_id_or_alias
25
+ "#{@realm_client.realm_admin_url}/identity-provider/instances/#{internal_id_or_alias}"
26
+ else
27
+ "#{@realm_client.realm_admin_url}/identity-provider/instances"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -83,6 +83,10 @@ module KeycloakAdmin
83
83
  UserClient.new(@configuration, self)
84
84
  end
85
85
 
86
+ def identity_providers
87
+ IdentityProviderClient.new(@configuration, self)
88
+ end
89
+
86
90
  def user(user_id)
87
91
  UserResource.new(@configuration, self, user_id)
88
92
  end
@@ -31,6 +31,27 @@ module KeycloakAdmin
31
31
  )
32
32
  end
33
33
 
34
+ def add_group(user_id, group_id)
35
+ RestClient::Request.execute(
36
+ @configuration.rest_client_options.merge(
37
+ method: :put,
38
+ url: "#{users_url(user_id)}/groups/#{group_id}",
39
+ payload: {},
40
+ headers: headers
41
+ )
42
+ )
43
+ end
44
+
45
+ def remove_group(user_id, group_id)
46
+ RestClient::Request.execute(
47
+ @configuration.rest_client_options.merge(
48
+ method: :delete,
49
+ url: "#{users_url(user_id)}/groups/#{group_id}",
50
+ headers: headers
51
+ )
52
+ )
53
+ end
54
+
34
55
  def get(user_id)
35
56
  response = execute_http do
36
57
  RestClient::Resource.new(users_url(user_id), @configuration.rest_client_options).get(headers)
@@ -38,8 +59,22 @@ module KeycloakAdmin
38
59
  UserRepresentation.from_hash(JSON.parse(response))
39
60
  end
40
61
 
62
+ ##
63
+ # Query can be a string or a hash.
64
+ # * String: It's used as search query
65
+ # * Hash: Used for complex search queries.
66
+ # For its documentation see: https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_users_resource
67
+ ##
41
68
  def search(query)
42
- derived_headers = query ? headers.merge({params: { search: query }}) : headers
69
+ derived_headers = case query
70
+ when String
71
+ headers.merge({params: { search: query }})
72
+ when Hash
73
+ headers.merge({params: query })
74
+ else
75
+ headers
76
+ end
77
+
43
78
  response = execute_http do
44
79
  RestClient::Resource.new(users_url, @configuration.rest_client_options).get(derived_headers)
45
80
  end
@@ -0,0 +1,67 @@
1
+ module KeycloakAdmin
2
+ class IdentityProviderRepresentation < Representation
3
+ attr_accessor :alias,
4
+ :display_name,
5
+ :internal_id,
6
+ :provider_id,
7
+ :enabled,
8
+ :update_profile_first_login_mode,
9
+ :trust_email,
10
+ :store_token,
11
+ :add_read_token_role_on_create,
12
+ :authenticate_by_default,
13
+ :link_only,
14
+ :first_broker_login_flow_alias,
15
+ :configuration
16
+
17
+ def self.from_hash(hash)
18
+ if hash.nil?
19
+ nil
20
+ else
21
+ new(
22
+ hash["alias"],
23
+ hash["displayName"],
24
+ hash["internalId"],
25
+ hash["providerId"],
26
+ hash["enabled"],
27
+ hash["updateProfileFirstLoginMode"],
28
+ hash["trustEmail"],
29
+ hash["storeToken"],
30
+ hash["addReadTokenRoleOnCreate"],
31
+ hash["authenticateByDefault"],
32
+ hash["linkOnly"],
33
+ hash["firstBrokerLoginFlowAlias"],
34
+ hash["config"]
35
+ )
36
+ end
37
+ end
38
+
39
+ def initialize(alias_name,
40
+ display_name,
41
+ internal_id,
42
+ provider_id,
43
+ enabled,
44
+ update_profile_first_login_mode,
45
+ trust_email,
46
+ store_token,
47
+ add_read_token_role_on_create,
48
+ authenticate_by_default,
49
+ link_only,
50
+ first_broker_login_flow_alias,
51
+ configuration)
52
+ @alias = alias_name
53
+ @display_name = display_name
54
+ @internal_id = internal_id
55
+ @provider_id = provider_id
56
+ @enabled = enabled
57
+ @update_profile_first_login_mode = update_profile_first_login_mode
58
+ @trust_email = trust_email
59
+ @store_token = store_token
60
+ @add_read_token_role_on_create = add_read_token_role_on_create
61
+ @authenticate_by_default = authenticate_by_default
62
+ @link_only = link_only
63
+ @first_broker_login_flow_alias = first_broker_login_flow_alias
64
+ @configuration = configuration
65
+ end
66
+ end
67
+ end
@@ -10,8 +10,10 @@ module KeycloakAdmin
10
10
  :email_verified,
11
11
  :first_name,
12
12
  :last_name,
13
+ :totp,
13
14
  :credentials,
14
- :federated_identities
15
+ :federated_identities,
16
+ :required_actions
15
17
 
16
18
  def self.from_hash(hash)
17
19
  user = new
@@ -25,6 +27,8 @@ module KeycloakAdmin
25
27
  user.first_name = hash["firstName"]
26
28
  user.last_name = hash["lastName"]
27
29
  user.attributes = hash["attributes"]
30
+ user.required_actions = hash["requiredActions"] || []
31
+ user.totp = hash["totp"] || false
28
32
  user.credentials = hash["credentials"]&.map{ |hash| CredentialRepresentation.from_hash(hash) } || []
29
33
  user.federated_identities = hash["federatedIdentities"]&.map { |hash| FederatedIdentityRepresentation.from_hash(hash) } || []
30
34
  user
@@ -1,3 +1,3 @@
1
1
  module KeycloakAdmin
2
- VERSION = "0.7.7"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -10,6 +10,7 @@ require_relative "keycloak-admin/client/role_client"
10
10
  require_relative "keycloak-admin/client/role_mapper_client"
11
11
  require_relative "keycloak-admin/client/token_client"
12
12
  require_relative "keycloak-admin/client/user_client"
13
+ require_relative "keycloak-admin/client/identity_provider_client"
13
14
  require_relative "keycloak-admin/client/configurable_token_client"
14
15
  require_relative "keycloak-admin/representation/camel_json"
15
16
  require_relative "keycloak-admin/representation/representation"
@@ -23,6 +24,7 @@ require_relative "keycloak-admin/representation/realm_representation"
23
24
  require_relative "keycloak-admin/representation/role_representation"
24
25
  require_relative "keycloak-admin/representation/federated_identity_representation"
25
26
  require_relative "keycloak-admin/representation/user_representation"
27
+ require_relative "keycloak-admin/representation/identity_provider_representation"
26
28
  require_relative "keycloak-admin/resource/base_role_containing_resource"
27
29
  require_relative "keycloak-admin/resource/group_resource"
28
30
  require_relative "keycloak-admin/resource/user_resource"
@@ -55,7 +57,7 @@ module KeycloakAdmin
55
57
  config.use_service_account = true
56
58
  config.username = nil
57
59
  config.password = nil
58
- config.rest_client_options = nil
60
+ config.rest_client_options = {}
59
61
  end
60
62
  end
61
63
 
@@ -0,0 +1,92 @@
1
+ RSpec.describe KeycloakAdmin::IdentityProviderClient do
2
+ describe "#identity_providers_url" do
3
+ let(:realm_name) { "valid-realm" }
4
+ let(:provider_id) { nil }
5
+
6
+ before(:each) do
7
+ @built_url = KeycloakAdmin.realm(realm_name).identity_providers.identity_providers_url(provider_id)
8
+ end
9
+
10
+ context "when provider_id is not defined" do
11
+ let(:provider_id) { nil }
12
+ it "returns a proper url without provider id" do
13
+ expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/identity-provider/instances"
14
+ end
15
+ end
16
+
17
+ context "when provider_id is defined" do
18
+ let(:provider_id) { "95985b21-d884-4bbd-b852-cb8cd365afc2" }
19
+ it "returns a proper url with the provider id" do
20
+ expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/identity-provider/instances/95985b21-d884-4bbd-b852-cb8cd365afc2"
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#list" do
26
+ let(:realm_name) { "valid-realm" }
27
+ let(:json_response) do
28
+ <<-JSON
29
+ [
30
+ {
31
+ "alias": "acme",
32
+ "displayName": "ACME",
33
+ "internalId": "20fea77e-ae3d-411e-9467-2b3a20cd3e6d",
34
+ "providerId": "saml",
35
+ "enabled": true,
36
+ "updateProfileFirstLoginMode": "on",
37
+ "trustEmail": true,
38
+ "storeToken": false,
39
+ "addReadTokenRoleOnCreate": false,
40
+ "authenticateByDefault": false,
41
+ "linkOnly": false,
42
+ "firstBrokerLoginFlowAlias": "first broker login",
43
+ "config": {
44
+ "hideOnLoginPage": "",
45
+ "validateSignature": "true",
46
+ "samlXmlKeyNameTranformer": "KEY_ID",
47
+ "signingCertificate": "",
48
+ "postBindingLogout": "false",
49
+ "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
50
+ "postBindingResponse": "true",
51
+ "backchannelSupported": "",
52
+ "signatureAlgorithm": "RSA_SHA256",
53
+ "wantAssertionsEncrypted": "false",
54
+ "xmlSigKeyInfoKeyNameTransformer": "CERT_SUBJECT",
55
+ "useJwksUrl": "true",
56
+ "wantAssertionsSigned": "true",
57
+ "postBindingAuthnRequest": "true",
58
+ "forceAuthn": "",
59
+ "wantAuthnRequestsSigned": "true",
60
+ "singleSignOnServiceUrl": "https://login.microsoftonline.com/test/saml2",
61
+ "addExtensionsElementWithKeyInfo": "false"
62
+ }
63
+ }
64
+ ]
65
+ JSON
66
+ end
67
+ before(:each) do
68
+ @identity_provider_client = KeycloakAdmin.realm(realm_name).identity_providers
69
+
70
+ stub_token_client
71
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return json_response
72
+ end
73
+
74
+ it "lists identity providers" do
75
+ identity_providers = @identity_provider_client.list
76
+ expect(identity_providers.length).to eq 1
77
+ expect(identity_providers[0].alias).to eq "acme"
78
+ end
79
+
80
+ it "passes rest client options" do
81
+ rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
82
+ allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
83
+
84
+ expect(RestClient::Resource).to receive(:new).with(
85
+ "http://auth.service.io/auth/admin/realms/valid-realm/identity-provider/instances", rest_client_options).and_call_original
86
+
87
+ identity_providers = @identity_provider_client.list
88
+ expect(identity_providers.length).to eq 1
89
+ expect(identity_providers[0].alias).to eq "acme"
90
+ end
91
+ end
92
+ end
@@ -158,7 +158,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
158
158
  @user_client = KeycloakAdmin.realm(realm_name).users
159
159
 
160
160
  stub_token_client
161
- allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '{"username":"test_username","createdTimestamp":1559347200}'
161
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '{"username":"test_username","createdTimestamp":1559347200, "requiredActions":["CONFIGURE_TOTP"], "totp": true}'
162
162
  end
163
163
 
164
164
  it "parses the response" do
@@ -175,6 +175,8 @@ RSpec.describe KeycloakAdmin::TokenClient do
175
175
 
176
176
  user = @user_client.get('test_user_id')
177
177
  expect(user.username).to eq 'test_username'
178
+ expect(user.totp).to be true
179
+ expect(user.required_actions).to eq ["CONFIGURE_TOTP"]
178
180
  end
179
181
  end
180
182
 
@@ -192,12 +194,24 @@ RSpec.describe KeycloakAdmin::TokenClient do
192
194
  allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '[{"username":"test_username","createdTimestamp":1559347200}]'
193
195
  end
194
196
 
195
- it "finds a user" do
197
+ it "finds a user using a string" do
196
198
  users = @user_client.search("test_username")
197
199
  expect(users.length).to eq 1
198
200
  expect(users[0].username).to eq "test_username"
199
201
  end
200
202
 
203
+ it "finds a user using nil does not fail" do
204
+ users = @user_client.search(nil)
205
+ expect(users.length).to eq 1
206
+ expect(users[0].username).to eq "test_username"
207
+ end
208
+
209
+ it "finds a user using a hash" do
210
+ users = @user_client.search({ search: "test_username"})
211
+ expect(users.length).to eq 1
212
+ expect(users[0].username).to eq "test_username"
213
+ end
214
+
201
215
  it "passes rest client options" do
202
216
  rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
203
217
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
@@ -0,0 +1,113 @@
1
+ RSpec.describe KeycloakAdmin::IdentityProviderRepresentation do
2
+ describe "#from_hash" do
3
+ before(:each) do
4
+ json = <<-JSON
5
+ {
6
+ "alias": "acme",
7
+ "displayName": "ACME",
8
+ "internalId": "20fea77e-ae3d-411e-9467-2b3a20cd3e6d",
9
+ "providerId": "saml",
10
+ "enabled": true,
11
+ "updateProfileFirstLoginMode": "on",
12
+ "trustEmail": true,
13
+ "storeToken": false,
14
+ "addReadTokenRoleOnCreate": false,
15
+ "authenticateByDefault": false,
16
+ "linkOnly": false,
17
+ "firstBrokerLoginFlowAlias": "first broker login",
18
+ "config": {
19
+ "hideOnLoginPage": "",
20
+ "validateSignature": "true",
21
+ "samlXmlKeyNameTranformer": "KEY_ID",
22
+ "signingCertificate": "",
23
+ "postBindingLogout": "false",
24
+ "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
25
+ "postBindingResponse": "true",
26
+ "backchannelSupported": "",
27
+ "signatureAlgorithm": "RSA_SHA256",
28
+ "wantAssertionsEncrypted": "false",
29
+ "xmlSigKeyInfoKeyNameTransformer": "CERT_SUBJECT",
30
+ "useJwksUrl": "true",
31
+ "wantAssertionsSigned": "true",
32
+ "postBindingAuthnRequest": "true",
33
+ "forceAuthn": "",
34
+ "wantAuthnRequestsSigned": "true",
35
+ "singleSignOnServiceUrl": "https://login.microsoftonline.com/test/saml2",
36
+ "addExtensionsElementWithKeyInfo": "false"
37
+ }
38
+ }
39
+ JSON
40
+ payload = JSON.parse(json)
41
+ @identity_provider = KeycloakAdmin::IdentityProviderRepresentation.from_hash(payload)
42
+ end
43
+
44
+ it "parses the alias" do
45
+ expect(@identity_provider.alias).to eq "acme"
46
+ end
47
+
48
+ it "parses the display name" do
49
+ expect(@identity_provider.display_name).to eq "ACME"
50
+ end
51
+
52
+ it "parses the internalId" do
53
+ expect(@identity_provider.internal_id).to eq "20fea77e-ae3d-411e-9467-2b3a20cd3e6d"
54
+ end
55
+
56
+ it "parses the provider id" do
57
+ expect(@identity_provider.provider_id).to eq "saml"
58
+ end
59
+
60
+ it "parses the enabled" do
61
+ expect(@identity_provider.enabled).to eq true
62
+ end
63
+
64
+ it "parses the update_profile_first_login_mode" do
65
+ expect(@identity_provider.update_profile_first_login_mode).to eq "on"
66
+ end
67
+
68
+ it "parses the trust_email" do
69
+ expect(@identity_provider.trust_email).to eq true
70
+ end
71
+
72
+ it "parses the store_token" do
73
+ expect(@identity_provider.store_token).to eq false
74
+ end
75
+
76
+ it "parses the add_read_token_role_on_create" do
77
+ expect(@identity_provider.add_read_token_role_on_create).to eq false
78
+ end
79
+
80
+ it "parses the authenticate_by_default" do
81
+ expect(@identity_provider.authenticate_by_default).to eq false
82
+ end
83
+
84
+ it "parses the link_only" do
85
+ expect(@identity_provider.link_only).to eq false
86
+ end
87
+
88
+ it "parses the first_broker_login_flow_alias" do
89
+ expect(@identity_provider.first_broker_login_flow_alias).to eq "first broker login"
90
+ end
91
+
92
+ it "parses the configuration as a hash with camel properties" do
93
+ expect(@identity_provider.configuration["hideOnLoginPage"]).to eq ""
94
+ expect(@identity_provider.configuration["validateSignature"]).to eq "true"
95
+ expect(@identity_provider.configuration["samlXmlKeyNameTranformer"]).to eq "KEY_ID"
96
+ expect(@identity_provider.configuration["signingCertificate"]).to eq ""
97
+ expect(@identity_provider.configuration["postBindingLogout"]).to eq "false"
98
+ expect(@identity_provider.configuration["nameIDPolicyFormat"]).to eq "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
99
+ expect(@identity_provider.configuration["postBindingResponse"]).to eq "true"
100
+ expect(@identity_provider.configuration["backchannelSupported"]).to eq ""
101
+ expect(@identity_provider.configuration["signatureAlgorithm"]).to eq "RSA_SHA256"
102
+ expect(@identity_provider.configuration["wantAssertionsEncrypted"]).to eq "false"
103
+ expect(@identity_provider.configuration["xmlSigKeyInfoKeyNameTransformer"]).to eq "CERT_SUBJECT"
104
+ expect(@identity_provider.configuration["useJwksUrl"]).to eq "true"
105
+ expect(@identity_provider.configuration["wantAssertionsSigned"]).to eq "true"
106
+ expect(@identity_provider.configuration["postBindingAuthnRequest"]).to eq "true"
107
+ expect(@identity_provider.configuration["forceAuthn"]).to eq ""
108
+ expect(@identity_provider.configuration["wantAuthnRequestsSigned"]).to eq "true"
109
+ expect(@identity_provider.configuration["singleSignOnServiceUrl"]).to eq "https://login.microsoftonline.com/test/saml2"
110
+ expect(@identity_provider.configuration["addExtensionsElementWithKeyInfo"]).to eq "false"
111
+ end
112
+ end
113
+ end
@@ -9,7 +9,7 @@ RSpec.describe KeycloakAdmin::UserRepresentation do
9
9
  end
10
10
 
11
11
  it "can convert to json" do
12
- expect(@user.to_json).to eq '{"id":null,"createdTimestamp":1559836000,"origin":null,"username":"test_username","email":null,"enabled":true,"emailVerified":null,"firstName":null,"lastName":null,"attributes":null,"credentials":[],"federatedIdentities":[]}'
12
+ expect(@user.to_json).to eq '{"id":null,"createdTimestamp":1559836000,"origin":null,"username":"test_username","email":null,"enabled":true,"emailVerified":null,"firstName":null,"lastName":null,"attributes":null,"requiredActions":[],"totp":false,"credentials":[],"federatedIdentities":[]}'
13
13
  end
14
14
  end
15
15
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keycloak-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.7
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorent Lempereur
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-10 00:00:00.000000000 Z
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-cookie
@@ -94,6 +94,7 @@ files:
94
94
  - lib/keycloak-admin/client/client_role_mappings_client.rb
95
95
  - lib/keycloak-admin/client/configurable_token_client.rb
96
96
  - lib/keycloak-admin/client/group_client.rb
97
+ - lib/keycloak-admin/client/identity_provider_client.rb
97
98
  - lib/keycloak-admin/client/realm_client.rb
98
99
  - lib/keycloak-admin/client/role_client.rb
99
100
  - lib/keycloak-admin/client/role_mapper_client.rb
@@ -105,6 +106,7 @@ files:
105
106
  - lib/keycloak-admin/representation/credential_representation.rb
106
107
  - lib/keycloak-admin/representation/federated_identity_representation.rb
107
108
  - lib/keycloak-admin/representation/group_representation.rb
109
+ - lib/keycloak-admin/representation/identity_provider_representation.rb
108
110
  - lib/keycloak-admin/representation/impersonation_redirection_representation.rb
109
111
  - lib/keycloak-admin/representation/impersonation_representation.rb
110
112
  - lib/keycloak-admin/representation/realm_representation.rb
@@ -121,12 +123,14 @@ files:
121
123
  - spec/client/client_spec.rb
122
124
  - spec/client/configurable_token_client_spec.rb
123
125
  - spec/client/group_client_spec.rb
126
+ - spec/client/identity_provider_client_spec.rb
124
127
  - spec/client/realm_client_spec.rb
125
128
  - spec/client/role_client_spec.rb
126
129
  - spec/client/role_mapper_client_spec.rb
127
130
  - spec/client/token_client_spec.rb
128
131
  - spec/client/user_client_spec.rb
129
132
  - spec/configuration_spec.rb
133
+ - spec/representation/identity_provider_representation_spec.rb
130
134
  - spec/representation/impersonation_representation_spec.rb
131
135
  - spec/representation/user_representation_spec.rb
132
136
  - spec/resource/group_resource_spec.rb
@@ -136,7 +140,7 @@ homepage: https://github.com/looorent/keycloak-admin-ruby
136
140
  licenses:
137
141
  - MIT
138
142
  metadata: {}
139
- post_install_message:
143
+ post_install_message:
140
144
  rdoc_options: []
141
145
  require_paths:
142
146
  - lib
@@ -151,8 +155,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
155
  - !ruby/object:Gem::Version
152
156
  version: '0'
153
157
  requirements: []
154
- rubygems_version: 3.0.3
155
- signing_key:
158
+ rubygems_version: 3.2.3
159
+ signing_key:
156
160
  specification_version: 4
157
161
  summary: Keycloak Admin REST API client written in Ruby
158
162
  test_files: []