keycloak-api-manager 3.2.0 → 3.2.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.
package/.mocharc.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "require": ["test/mocha.env.js"],
3
+ "timeout": 15000,
4
+ "spec": "test/**/*.test.js",
5
+ "reporter": "spec",
6
+ "parallel": false
7
+ }
@@ -218,7 +218,7 @@ exports.updateRequiredAction=function(filter,actionRepresentation){
218
218
  * @parameters:
219
219
  * - filter: parameter provided as a JSON object that accepts the following filter:
220
220
  * - alias: [required] The alias (providerId) of the required action to update.
221
- * - actionRepresentation: The configuration object to update.
221
+ * - actionConfigRepresentation: The configuration object to update.
222
222
  */
223
223
  exports.updateRequiredActionConfig=function(filter, actionConfigRepresentation){
224
224
  return (kcAdminClientHandler.authenticationManagement.updateRequiredActionConfig(filter,actionConfigRepresentation));
@@ -20,8 +20,8 @@ exports.setKcAdminClient=function(kcAdminClient){
20
20
  * A client scope defines a set of protocol mappers and roles that can be applied to clients,
21
21
  * such as during login or token generation.
22
22
  */
23
- exports.create=function(scopeRappresentation){
24
- return (kcAdminClientHandler.clientScopes.create(scopeRappresentation ));
23
+ exports.create=function(scopeRepresentation){
24
+ return (kcAdminClientHandler.clientScopes.create(scopeRepresentation ));
25
25
  }
26
26
 
27
27
 
@@ -35,13 +35,13 @@ exports.create=function(scopeRappresentation){
35
35
  * - filter: parameter provided as a JSON object that accepts the following filter:
36
36
  * - id: [required] The unique ID of the client scope to update.
37
37
  * - realm: [optional] The realm where the client scope exists.
38
- * - scopeRappresentation: The updated client scope object.
38
+ * - scopeRepresentation: The updated client scope object.
39
39
  * - name: [optional] The name of the scope
40
40
  * - description: [optional] The scope description
41
41
  * - {other scope fields}
42
42
  */
43
- exports.update=function(filter,scopeRappresentation){
44
- return (kcAdminClientHandler.clientScopes.update(filter,scopeRappresentation ));
43
+ exports.update=function(filter,scopeRepresentation){
44
+ return (kcAdminClientHandler.clientScopes.update(filter,scopeRepresentation ));
45
45
  }
46
46
 
47
47
 
@@ -195,7 +195,7 @@ exports.getClientSecret=function(filter){
195
195
  * - id: [required] The internal ID of the client (not clientId)
196
196
  */
197
197
  exports.generateNewClientSecret=function(filter){
198
- return (kcAdminClientHandler.clients.creatgenerateNewClientSecrete(filter));
198
+ return (kcAdminClientHandler.clients.generateNewClientSecret(filter));
199
199
  }
200
200
 
201
201
 
@@ -60,8 +60,8 @@ exports.create=function(componentRepresentation){
60
60
  * - bindCredential: ["secret"],
61
61
  * - usersDn: ["ou=users,dc=example,dc=com"]
62
62
  */
63
- exports.update=function(filters, componentRepresentation){
64
- return (kcAdminClientHandler.components.update(filters, componentRepresentation));
63
+ exports.update=function(filter, componentRepresentation){
64
+ return (kcAdminClientHandler.components.update(filter, componentRepresentation));
65
65
  }
66
66
 
67
67
 
@@ -25,8 +25,8 @@ exports.setKcAdminClient=function(kcAdminClient){
25
25
  * - description: [optional] the new group Description
26
26
  * - {other [optional] group description fields}
27
27
  */
28
- exports.create=function(groupRappresentation){
29
- return (kcAdminClientHandler.groups.create(groupRappresentation));
28
+ exports.create=function(groupRepresentation){
29
+ return (kcAdminClientHandler.groups.create(groupRepresentation));
30
30
  }
31
31
 
32
32
 
@@ -18,7 +18,7 @@ exports.setKcAdminClient=function(kcAdminClient){
18
18
  * or another SAML/OIDC provider.
19
19
  * This method requires specifying an alias, the provider type, and configuration settings such as client ID, client secret, and any other provider-specific options.
20
20
  * @parameters:
21
- * - identityProvidersRappresentation: parameter provided as a JSON object containing the configuration of the Identity Provider
21
+ * - identityProvidersRepresentation: parameter provided as a JSON object containing the configuration of the Identity Provider
22
22
  * - alias: [required] Unique name for the IdP within the realm.
23
23
  * - providerId: [required] Type of provider (google, facebook, oidc, saml, etc.).
24
24
  * - enabled: [optional] Whether the IdP is enabled. Default is true.
@@ -29,8 +29,8 @@ exports.setKcAdminClient=function(kcAdminClient){
29
29
  * - firstBrokerLoginFlowAlias: [optional] Flow to use on first login.
30
30
  * - config : [optional] Provider-specific configuration, e.g., client ID, client secret, endpoints, etc.
31
31
  */
32
- exports.create=function(identityProvidersRappresentation){
33
- return (kcAdminClientHandler.identityProviders.create(identityProvidersRappresentation));
32
+ exports.create=function(identityProvidersRepresentation){
33
+ return (kcAdminClientHandler.identityProviders.create(identityProvidersRepresentation));
34
34
  }
35
35
 
36
36
  /**
package/README.md CHANGED
@@ -95,7 +95,7 @@ const express = require('express');
95
95
  // Initialize the manager with Keycloak credentials
96
96
  await KeycloakManager.configure({
97
97
  baseUrl: 'http://localhost:8080', // Keycloak base URL
98
- realm: 'master', // Realm where the admin user belongs
98
+ realmName: 'master', // Realm where the admin user belongs (alias: realm)
99
99
  clientId: 'admin-cli', // Keycloak admin client
100
100
  username: 'admin', // Admin username
101
101
  password: 'admin', // Admin password
@@ -165,7 +165,7 @@ const KeycloakManager = require('keycloak-api-manager');
165
165
  // Initialize the manager with Keycloak credentials
166
166
  await KeycloakManager.configure({
167
167
  baseUrl: 'http://localhost:8080', // Keycloak base URL
168
- realm: 'master', // Realm where the admin user belongs
168
+ realmName: 'master', // Realm where the admin user belongs (alias: realm)
169
169
  clientId: 'admin-cli', // Keycloak admin client
170
170
  username: 'admin', // Admin username
171
171
  password: 'admin', // Admin password
@@ -186,7 +186,8 @@ Parameters:
186
186
  exposed by this adapter, so any attempt to call KeycloakManager.{function} will result in a runtime error due to access on an undefined object
187
187
  Main supported options:
188
188
  - baseUrl: [required] Keycloak base Url
189
- - realmName: [required] A String that specifies the realm to authenticate against, if different from the "keyCloakConfig.realm" parameter. If you intend to use Keycloak administrator credentials, this should be set to 'master'.
189
+ - realmName: [required] A String that specifies the realm to authenticate against, if different from the "keyCloakConfig.realm" parameter. If you intend to use Keycloak administrator credentials, this should be set to 'master'.
190
+ - realm: [optional] Alias of realmName for backward compatibility.
190
191
  - grantType: [required] The OAuth2 grant type used for authentication. example "password". Possible values: 'password', 'client_credentials', 'refresh_token', etc.
191
192
  - clientId: [required] string containing the client ID configured in Keycloak. Required for all grant types.
192
193
  - tokenLifeSpan: [required] Numeric Lifetime of an access token expressed in seconds. It indicates how often the access token should be renewed. If set incorrectly and the Keycloak token expires before the renewal interval defined by this parameter, errors and exceptions may occur
@@ -412,7 +413,7 @@ It’s useful for incremental updates or merging configuration pieces.
412
413
  **` -- @parameters -- `**
413
414
  - configuration: is a JSON object that accepts filter parameters
414
415
  - realm:[required] The name of the realm where the data should be imported.
415
- - representation:[required] A JSON object representing part of the realm configuration to be imported(can include users, roles, groups, clients, etc.).
416
+ - rep:[required] A JSON object representing part of the realm configuration to be imported(can include users, roles, groups, clients, etc.).
416
417
  - ifResourceExists:[required] Defines the behavior when an imported resource already exists in the target realm.
417
418
  Options are:
418
419
  - 'FAIL' – the operation fails if a resource already exists.
@@ -1950,7 +1951,10 @@ Creates a new client with the provided configuration
1950
1951
  ```js
1951
1952
  const KeycloakManager = require('keycloak-api-manager');
1952
1953
  // create a client called my-client
1953
- const client= await KeycloakManager.clients.create({name: "my-client", id:"client-id"});
1954
+ const client= await KeycloakManager.clients.create({
1955
+ name: "my-client",
1956
+ clientId:"client-id"
1957
+ });
1954
1958
  console.log("New Client Created:", client);
1955
1959
  ```
1956
1960
 
@@ -2333,7 +2337,7 @@ Default client scopes are automatically assigned to a client during token reques
2333
2337
 
2334
2338
  **` -- @parameters -- `**
2335
2339
  - filter: JSON structure that defines the filter parameters:
2336
- - id: [required] The client ID of the client whose default client scopes you want to list.
2340
+ - id: [required] The internal ID of the client whose default client scopes you want to list.
2337
2341
 
2338
2342
  ```js
2339
2343
  const KeycloakManager = require('keycloak-api-manager');
@@ -2353,7 +2357,7 @@ Optional scopes are those that a client can request explicitly but are not autom
2353
2357
 
2354
2358
  **` -- @parameters -- `**
2355
2359
  - filter: JSON structure that defines the filter parameters:
2356
- - id: [required] The client ID of the client whose optional client scopes you want to list.
2360
+ - id: [required] The internal ID of the client whose optional client scopes you want to list.
2357
2361
 
2358
2362
  ```js
2359
2363
  const KeycloakManager = require('keycloak-api-manager');
@@ -4038,7 +4042,7 @@ Client scopes are reusable sets of protocol mappers and role scope mappings whic
4038
4042
  can be assigned to clients to define what information about the user is included in tokens and what roles are available.
4039
4043
 
4040
4044
  #### `entity clientScopes functions`
4041
- ##### `function create(scopeRappresentation)`
4045
+ ##### `function create(scopeRepresentation)`
4042
4046
  method is used to create a new client scope in a Keycloak realm.
4043
4047
  A client scope defines a set of protocol mappers and roles that can be applied to clients,
4044
4048
  such as during login or token generation.
@@ -4053,7 +4057,7 @@ const KeycloakManager = require('keycloak-api-manager');
4053
4057
  ```
4054
4058
 
4055
4059
 
4056
- ##### `function update(filter,scopeRappresentation)`
4060
+ ##### `function update(filter,scopeRepresentation)`
4057
4061
  The method updates the configuration of an existing client scope in a realm.
4058
4062
  You can modify properties such as the scope’s name, description, attributes, or protocol mappers.
4059
4063
 
@@ -4061,7 +4065,7 @@ You can modify properties such as the scope’s name, description, attributes, o
4061
4065
  - filter: parameter provided as a JSON object that accepts the following filter:
4062
4066
  - id: [required] The unique ID of the client scope to update.
4063
4067
  - realm: [optional] The realm where the client scope exists.
4064
- - scopeRappresentation: The updated client scope object. for example:
4068
+ - scopeRepresentation: The updated client scope object. for example:
4065
4069
  - name: [optional] The name of the scope
4066
4070
  - description: [optional] The scope description
4067
4071
  - other scope fields....
@@ -4890,14 +4894,14 @@ These are providers like Google, Facebook, GitHub, SAML, OIDC, etc.
4890
4894
 
4891
4895
  #### `entity identityProviders functions`
4892
4896
 
4893
- ##### `function identityProviders.create(identityProvidersRappresentation)`
4897
+ ##### `function identityProviders.create(identityProvidersRepresentation)`
4894
4898
  The method is used to create a new Identity Provider (IdP) in a Keycloak realm.
4895
4899
  An IdP allows users to authenticate via external providers such as Google, Facebook, GitHub,
4896
4900
  or another SAML/OIDC provider.
4897
4901
  This method requires specifying an alias, the provider type, and configuration settings such as client ID, client secret, and any other provider-specific options.
4898
4902
 
4899
4903
  **` -- @parameters -- `**
4900
- - identityProvidersRappresentation: parameter provided as a JSON object containing the configuration of the Identity Provider
4904
+ - identityProvidersRepresentation: parameter provided as a JSON object containing the configuration of the Identity Provider
4901
4905
  - alias: [required] Unique name for the IdP within the realm.
4902
4906
  - providerId: [required] Type of provider (google, facebook, oidc, saml, etc.).
4903
4907
  - enabled: [optional] Whether the IdP is enabled. Default is true.
@@ -5280,7 +5284,7 @@ Groups are collections of users and can have roles and attributes assigned to th
5280
5284
  Groups help organize users and assign permissions in a scalable way
5281
5285
 
5282
5286
  #### `entity groups functions`
5283
- ##### `function create(groupRappresentation)`
5287
+ ##### `function create(groupRepresentation)`
5284
5288
  Create a new group in the current realme
5285
5289
 
5286
5290
  **` -- @parameters -- `**
@@ -5732,7 +5736,7 @@ Get a role by its Id
5732
5736
 
5733
5737
  **` -- @parameters -- `**
5734
5738
  - filters: parameter provided as a JSON object that accepts the following parameters:
5735
- - Id (string, required) — The Id of the role to retrieve.
5739
+ - id (string, required) — The id of the role to retrieve.
5736
5740
  - realm (string, optional if set globally) — The realm where the role is defined.
5737
5741
  ```js
5738
5742
  const KeycloakManager = require('keycloak-api-manager');
@@ -5759,7 +5763,7 @@ Update a role by its Id
5759
5763
 
5760
5764
  **` -- @parameters -- `**
5761
5765
  - filters: parameter provided as a JSON object that accepts the following parameters:
5762
- - name (string, required) — The exact name of the role to retrieve.
5766
+ - id (string, required) — The id of the role to retrieve.
5763
5767
  - realm (string, optional if set globally) — The realm where the role is defined.
5764
5768
  - role_dictionary: A JSON object representing a role dictionary as defined in Keycloak
5765
5769
  ```js
@@ -6289,7 +6293,7 @@ This allows you to modify settings such as OTP policies, password requirements,
6289
6293
  **` -- @parameters -- `**
6290
6294
  - filter: parameter provided as a JSON object that accepts the following filter:
6291
6295
  - alias: [required] The alias (providerId) of the required action to update.
6292
- - actionRepresentation: The configuration object to update.
6296
+ - actionConfigRepresentation: The configuration object to update.
6293
6297
 
6294
6298
 
6295
6299
  ```js
@@ -0,0 +1,27 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ keycloak:
5
+ image: keycloak/keycloak:latest
6
+ container_name: keycloak-test
7
+ ports:
8
+ - "8080:8080"
9
+ environment:
10
+ KEYCLOAK_ADMIN: admin
11
+ KEYCLOAK_ADMIN_PASSWORD: admin
12
+ KC_DB: dev-mem
13
+ KC_METRICS_ENABLED: 'false'
14
+ KC_HEALTH_ENABLED: 'true'
15
+ command:
16
+ - start-dev
17
+ healthcheck:
18
+ test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"]
19
+ interval: 5s
20
+ timeout: 5s
21
+ retries: 12
22
+ networks:
23
+ - keycloak-network
24
+
25
+ networks:
26
+ keycloak-network:
27
+ driver: bridge
package/index.mjs ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ESM wrapper for keycloak-api-manager
3
+ * This file provides ES Module support while the core is still CommonJS
4
+ */
5
+
6
+ import { createRequire } from 'module';
7
+ import { fileURLToPath } from 'url';
8
+ import path from 'path';
9
+
10
+ const require = createRequire(import.meta.url);
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ const keycloakApiManager = require('./index.js');
15
+
16
+ export const configure = keycloakApiManager.configure;
17
+ export const setConfig = keycloakApiManager.setConfig;
18
+ export const getToken = keycloakApiManager.getToken;
19
+ export const auth = keycloakApiManager.auth;
20
+
21
+ export default keycloakApiManager;
package/package.json CHANGED
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "keycloak-api-manager",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "Keycloak-api-manager is a lightweight Node.js wrapper for the Keycloak Admin REST API. It provides an easy-to-use functional methods and functions to manage realms, users, roles, clients, groups, and permissions directly from your application code — just like you would from the Keycloak admin console.",
5
5
  "main": "index.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./index.mjs",
9
+ "require": "./index.js"
10
+ }
11
+ },
6
12
  "scripts": {
7
- "test": "mocha"
13
+ "test": "mocha",
14
+ "test:watch": "mocha --watch --watch-extensions js"
8
15
  },
9
16
  "dependencies": {
10
17
  "@keycloak/keycloak-admin-client": "^26.3.2",
@@ -23,6 +30,11 @@
23
30
  "serve-favicon": "^2.5.0",
24
31
  "underscore": "^1.13.7"
25
32
  },
33
+ "devDependencies": {
34
+ "chai": "^4.3.10",
35
+ "mocha": "^10.2.0",
36
+ "dockerode": "^4.0.2"
37
+ },
26
38
  "keywords": [
27
39
  "keycloak",
28
40
  "user",
@@ -0,0 +1,329 @@
1
+ const { expect } = require('chai');
2
+ const { getAdminClient } = require('./config');
3
+
4
+ describe('Authentication Management Handler', function () {
5
+ this.timeout(20000);
6
+ let client;
7
+ let testFlowId;
8
+ let testFlowAlias;
9
+ let testExecutionId;
10
+ let testRequiredActionAlias;
11
+
12
+ before(function () {
13
+ client = getAdminClient();
14
+ testFlowAlias = `test-flow-${Date.now()}`;
15
+ });
16
+
17
+ // ==================== AUTHENTICATION FLOWS ====================
18
+ describe('Authentication Flows', function () {
19
+ describe('getFlows', function () {
20
+ it('should list all authentication flows', async function () {
21
+ const flows = await client.authenticationManagement.getFlows({
22
+ realm: 'test-realm',
23
+ });
24
+
25
+ expect(flows).to.be.an('array');
26
+ expect(flows.length).to.be.greaterThan(0);
27
+ });
28
+ });
29
+
30
+ describe('createFlow', function () {
31
+ it('should create an authentication flow', async function () {
32
+ const flowRep = {
33
+ alias: testFlowAlias,
34
+ description: 'Test Flow Description',
35
+ flowType: 'basic-flow',
36
+ builtIn: false,
37
+ };
38
+
39
+ const result = await client.authenticationManagement.createFlow(
40
+ { realm: 'test-realm' },
41
+ flowRep
42
+ );
43
+
44
+ expect(result).to.have.property('id');
45
+ testFlowId = result.id;
46
+ });
47
+ });
48
+
49
+ describe('getFlow', function () {
50
+ it('should retrieve a specific flow', async function () {
51
+ if (testFlowId) {
52
+ const flow = await client.authenticationManagement.getFlow({
53
+ realm: 'test-realm',
54
+ id: testFlowId,
55
+ });
56
+
57
+ expect(flow).to.exist;
58
+ expect(flow.id).to.equal(testFlowId);
59
+ }
60
+ });
61
+ });
62
+
63
+ describe('updateFlow', function () {
64
+ it('should update flow configuration', async function () {
65
+ if (testFlowId) {
66
+ const updateRep = {
67
+ description: 'Updated Description',
68
+ };
69
+
70
+ await client.authenticationManagement.updateFlow(
71
+ { realm: 'test-realm', id: testFlowId },
72
+ updateRep
73
+ );
74
+
75
+ const updated = await client.authenticationManagement.getFlow({
76
+ realm: 'test-realm',
77
+ id: testFlowId,
78
+ });
79
+
80
+ expect(updated.description).to.equal('Updated Description');
81
+ }
82
+ });
83
+ });
84
+
85
+ describe('copyFlow', function () {
86
+ it('should copy an authentication flow', async function () {
87
+ if (testFlowId) {
88
+ try {
89
+ const flowCopy = await client.authenticationManagement.copyFlow(
90
+ { realm: 'test-realm', id: testFlowId },
91
+ { newName: `copied-${testFlowAlias}` }
92
+ );
93
+
94
+ expect(flowCopy).to.exist;
95
+ } catch (err) {
96
+ // Copy might not be supported in all versions
97
+ }
98
+ }
99
+ });
100
+ });
101
+ });
102
+
103
+ // ==================== FLOW EXECUTIONS ====================
104
+ describe('Flow Executions', function () {
105
+ describe('getExecutions', function () {
106
+ it('should retrieve flow executions', async function () {
107
+ if (testFlowId) {
108
+ const executions = await client.authenticationManagement.getExecutions({
109
+ realm: 'test-realm',
110
+ flowAlias: testFlowAlias,
111
+ });
112
+
113
+ expect(executions).to.be.an('array');
114
+ }
115
+ });
116
+ });
117
+
118
+ describe('addExecutionToFlow', function () {
119
+ it('should add an execution to a flow', async function () {
120
+ if (testFlowId) {
121
+ try {
122
+ const execution = await client.authenticationManagement.addExecutionToFlow(
123
+ { realm: 'test-realm', flowAlias: testFlowAlias },
124
+ { provider: 'auth-cookie' }
125
+ );
126
+
127
+ expect(execution).to.exist;
128
+ testExecutionId = execution.id;
129
+ } catch (err) {
130
+ // Execution might not be allowed
131
+ }
132
+ }
133
+ });
134
+ });
135
+
136
+ describe('updateExecution', function () {
137
+ it('should update an execution', async function () {
138
+ if (testExecutionId && testFlowAlias) {
139
+ try {
140
+ const updateRep = {
141
+ requirement: 'CONDITIONAL',
142
+ };
143
+
144
+ await client.authenticationManagement.updateExecution(
145
+ { realm: 'test-realm', flowAlias: testFlowAlias },
146
+ updateRep
147
+ );
148
+
149
+ // Verify no error thrown
150
+ } catch (err) {
151
+ // Update might fail for some providers
152
+ }
153
+ }
154
+ });
155
+ });
156
+
157
+ describe('raisePriorityExecution', function () {
158
+ it('should raise execution priority', async function () {
159
+ if (testExecutionId && testFlowAlias) {
160
+ try {
161
+ await client.authenticationManagement.raisePriorityExecution({
162
+ realm: 'test-realm',
163
+ flowAlias: testFlowAlias,
164
+ executionId: testExecutionId,
165
+ });
166
+
167
+ // Verify no error thrown
168
+ } catch (err) {
169
+ // Priority adjust might not be supported
170
+ }
171
+ }
172
+ });
173
+ });
174
+
175
+ describe('lowerPriorityExecution', function () {
176
+ it('should lower execution priority', async function () {
177
+ if (testExecutionId && testFlowAlias) {
178
+ try {
179
+ await client.authenticationManagement.lowerPriorityExecution({
180
+ realm: 'test-realm',
181
+ flowAlias: testFlowAlias,
182
+ executionId: testExecutionId,
183
+ });
184
+
185
+ // Verify no error thrown
186
+ } catch (err) {
187
+ // Priority adjust might not be supported
188
+ }
189
+ }
190
+ });
191
+ });
192
+ });
193
+
194
+ // ==================== REQUIRED ACTIONS ====================
195
+ describe('Required Actions', function () {
196
+ describe('getRequiredActions', function () {
197
+ it('should list all required actions', async function () {
198
+ const actions = await client.authenticationManagement.getRequiredActions();
199
+
200
+ expect(actions).to.be.an('array');
201
+ expect(actions.length).to.be.greaterThan(0);
202
+ });
203
+ });
204
+
205
+ describe('getUnregisteredRequiredActions', function () {
206
+ it('should list unregistered required actions', async function () {
207
+ const unregistered = await client.authenticationManagement.getUnregisteredRequiredActions();
208
+
209
+ expect(unregistered).to.be.an('array');
210
+ });
211
+ });
212
+
213
+ describe('getRequiredActionForAlias', function () {
214
+ it('should retrieve a required action by alias', async function () {
215
+ const actions = await client.authenticationManagement.getRequiredActions();
216
+ if (actions.length > 0) {
217
+ const action = await client.authenticationManagement.getRequiredActionForAlias({
218
+ alias: actions[0].alias,
219
+ });
220
+
221
+ expect(action).to.exist;
222
+ testRequiredActionAlias = action.alias;
223
+ }
224
+ });
225
+ });
226
+
227
+ describe('updateRequiredAction', function () {
228
+ it('should update a required action', async function () {
229
+ if (testRequiredActionAlias) {
230
+ try {
231
+ const updateRep = {
232
+ enabled: true,
233
+ };
234
+
235
+ await client.authenticationManagement.updateRequiredAction(
236
+ { alias: testRequiredActionAlias },
237
+ updateRep
238
+ );
239
+
240
+ // Verify no error thrown
241
+ } catch (err) {
242
+ // Update might not be allowed
243
+ }
244
+ }
245
+ });
246
+ });
247
+
248
+ describe('raiseRequiredActionPriority', function () {
249
+ it('should raise required action priority', async function () {
250
+ if (testRequiredActionAlias) {
251
+ try {
252
+ await client.authenticationManagement.raiseRequiredActionPriority({
253
+ alias: testRequiredActionAlias,
254
+ });
255
+
256
+ // Verify no error thrown
257
+ } catch (err) {
258
+ // Priority adjust might not be supported
259
+ }
260
+ }
261
+ });
262
+ });
263
+
264
+ describe('lowerRequiredActionPriority', function () {
265
+ it('should lower required action priority', async function () {
266
+ if (testRequiredActionAlias) {
267
+ try {
268
+ await client.authenticationManagement.lowerRequiredActionPriority({
269
+ alias: testRequiredActionAlias,
270
+ });
271
+
272
+ // Verify no error thrown
273
+ } catch (err) {
274
+ // Priority adjust might not be supported
275
+ }
276
+ }
277
+ });
278
+ });
279
+ });
280
+
281
+ // ==================== PROVIDER INFORMATION ====================
282
+ describe('Authenticator Providers', function () {
283
+ describe('getAuthenticatorProviders', function () {
284
+ it('should retrieve authenticator providers', async function () {
285
+ const providers = await client.authenticationManagement.getAuthenticatorProviders();
286
+
287
+ expect(providers).to.be.an('array');
288
+ });
289
+ });
290
+
291
+ describe('getClientAuthenticatorProviders', function () {
292
+ it('should retrieve client authenticator providers', async function () {
293
+ const providers = await client.authenticationManagement.getClientAuthenticatorProviders();
294
+
295
+ expect(providers).to.be.an('array');
296
+ });
297
+ });
298
+
299
+ describe('getFormProviders', function () {
300
+ it('should retrieve form providers', async function () {
301
+ const providers = await client.authenticationManagement.getFormProviders();
302
+
303
+ expect(providers).to.be.an('array');
304
+ });
305
+ });
306
+
307
+ describe('getFormActionProviders', function () {
308
+ it('should retrieve form action providers', async function () {
309
+ const providers = await client.authenticationManagement.getFormActionProviders();
310
+
311
+ expect(providers).to.be.an('array');
312
+ });
313
+ });
314
+ });
315
+
316
+ // ==================== CLEANUP ====================
317
+ after(async function () {
318
+ try {
319
+ if (testFlowId) {
320
+ await client.authenticationManagement.deleteFlow({
321
+ realm: 'test-realm',
322
+ id: testFlowId,
323
+ });
324
+ }
325
+ } catch (err) {
326
+ console.error('Cleanup error:', err.message);
327
+ }
328
+ });
329
+ });