keycloak-admin 0.7.7 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []