keycloak-api-manager 5.0.1 → 5.0.3
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/README.md +19 -1
- package/docs/api/attack-detection.md +42 -0
- package/docs/api/authentication-management.md +160 -0
- package/docs/api/client-policies.md +66 -0
- package/docs/api/client-scopes.md +194 -0
- package/docs/api/clients.md +450 -0
- package/docs/api/components.md +57 -0
- package/docs/api/configuration.md +466 -0
- package/docs/api/groups.md +129 -0
- package/docs/api/identity-providers.md +98 -0
- package/docs/api/organizations.md +615 -0
- package/docs/api/realms.md +277 -0
- package/docs/api/roles.md +102 -0
- package/docs/api/server-info.md +38 -0
- package/docs/api/user-profile.md +63 -0
- package/docs/api/users.md +1563 -0
- package/docs/api-reference.md +163 -0
- package/docs/architecture.md +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
# Organizations API
|
|
2
|
+
|
|
3
|
+
Manage organizations for multi-tenancy in Keycloak 25+.
|
|
4
|
+
|
|
5
|
+
**Namespace:** `KeycloakManager.organizations`
|
|
6
|
+
**Keycloak Version:** 25.0+
|
|
7
|
+
**Required Feature Flag:** `organization`
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Organizations provide a way to group users, identity providers, and domains together, enabling better isolation and management of different organizational units in multi-tenant scenarios.
|
|
12
|
+
|
|
13
|
+
### Enable Organizations Feature
|
|
14
|
+
|
|
15
|
+
Start Keycloak with the organizations feature enabled:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
--features=organization
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or in `docker-compose.yml`:
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
environment:
|
|
25
|
+
KC_FEATURES: 'organization'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Table of Contents
|
|
29
|
+
|
|
30
|
+
- [create()](#create) - Create an organization
|
|
31
|
+
- [find()](#find) - List organizations
|
|
32
|
+
- [findOne()](#findone) - Get organization by ID
|
|
33
|
+
- [update()](#update) - Update organization
|
|
34
|
+
- [del()](#del) - Delete organization
|
|
35
|
+
- [addMember()](#addmember) - Add user to organization
|
|
36
|
+
- [listMembers()](#listmembers) - List organization members
|
|
37
|
+
- [delMember()](#delmember) - Remove user from organization
|
|
38
|
+
- [addIdentityProvider()](#addidentityprovider) - Link identity provider
|
|
39
|
+
- [listIdentityProviders()](#listidentityproviders) - List linked identity providers
|
|
40
|
+
- [delIdentityProvider()](#delidentityprovider) - Unlink identity provider
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## create()
|
|
45
|
+
|
|
46
|
+
Create a new organization in the current realm.
|
|
47
|
+
|
|
48
|
+
**Syntax:**
|
|
49
|
+
```javascript
|
|
50
|
+
const result = await KeycloakManager.organizations.create(organizationRepresentation)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Parameters
|
|
54
|
+
|
|
55
|
+
#### organizationRepresentation (Object) ⚠️ Required
|
|
56
|
+
|
|
57
|
+
| Property | Type | Required | Description |
|
|
58
|
+
|----------|------|----------|-------------|
|
|
59
|
+
| `name` | string | ⚠️ Yes | Unique organization name |
|
|
60
|
+
| `displayName` | string | 📋 Optional | Human-readable display name |
|
|
61
|
+
| `url` | string | 📋 Optional | Organization website URL |
|
|
62
|
+
| `domains` | array | 📋 Optional | List of domain objects |
|
|
63
|
+
| `attributes` | object | 📋 Optional | Custom key-value attributes |
|
|
64
|
+
|
|
65
|
+
### Returns
|
|
66
|
+
|
|
67
|
+
**Promise\<Object\>** - Created organization representation with `id`
|
|
68
|
+
|
|
69
|
+
### Examples
|
|
70
|
+
|
|
71
|
+
#### Basic Organization
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
const org = await KeycloakManager.organizations.create({
|
|
75
|
+
name: 'acme-corp',
|
|
76
|
+
displayName: 'ACME Corporation',
|
|
77
|
+
url: 'https://www.acme.com'
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
console.log('Created organization:', org.id);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### With Domains and Attributes
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
const org = await KeycloakManager.organizations.create({
|
|
87
|
+
name: 'tech-startup',
|
|
88
|
+
displayName: 'Tech Startup Inc.',
|
|
89
|
+
url: 'https://techstartup.io',
|
|
90
|
+
domains: [
|
|
91
|
+
{ name: 'techstartup.io', verified: true },
|
|
92
|
+
{ name: 'staging.techstartup.io', verified: false }
|
|
93
|
+
],
|
|
94
|
+
attributes: {
|
|
95
|
+
industry: ['Technology'],
|
|
96
|
+
country: ['USA'],
|
|
97
|
+
tier: ['Enterprise']
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
console.log('Organization with domains:', org);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## find()
|
|
107
|
+
|
|
108
|
+
List all organizations in the current realm with optional filtering.
|
|
109
|
+
|
|
110
|
+
**Syntax:**
|
|
111
|
+
```javascript
|
|
112
|
+
const organizations = await KeycloakManager.organizations.find(filter)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Parameters
|
|
116
|
+
|
|
117
|
+
#### filter (Object) 📋 Optional
|
|
118
|
+
|
|
119
|
+
| Property | Type | Required | Description |
|
|
120
|
+
|----------|------|----------|-------------|
|
|
121
|
+
| `search` | string | 📋 Optional | Search organizations by name or display name |
|
|
122
|
+
| `first` | number | 📋 Optional | Index of first result (pagination) |
|
|
123
|
+
| `max` | number | 📋 Optional | Maximum number of results |
|
|
124
|
+
| `realm` | string | 📋 Optional | Override realm context |
|
|
125
|
+
|
|
126
|
+
### Returns
|
|
127
|
+
|
|
128
|
+
**Promise\<Array\>** - Array of organization objects
|
|
129
|
+
|
|
130
|
+
### Examples
|
|
131
|
+
|
|
132
|
+
#### List All Organizations
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
const orgs = await KeycloakManager.organizations.find();
|
|
136
|
+
console.log(`Found ${orgs.length} organizations`);
|
|
137
|
+
|
|
138
|
+
orgs.forEach(org => {
|
|
139
|
+
console.log(`- ${org.name}: ${org.displayName}`);
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Search with Pagination
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
const orgs = await KeycloakManager.organizations.find({
|
|
147
|
+
search: 'acme',
|
|
148
|
+
first: 0,
|
|
149
|
+
max: 10
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
console.log('First 10 organizations matching "acme":', orgs);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## findOne()
|
|
158
|
+
|
|
159
|
+
Get a specific organization by ID.
|
|
160
|
+
|
|
161
|
+
**Syntax:**
|
|
162
|
+
```javascript
|
|
163
|
+
const organization = await KeycloakManager.organizations.findOne(filter)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Parameters
|
|
167
|
+
|
|
168
|
+
#### filter (Object) ⚠️ Required
|
|
169
|
+
|
|
170
|
+
| Property | Type | Required | Description |
|
|
171
|
+
|----------|------|----------|-------------|
|
|
172
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
173
|
+
| `realm` | string | 📋 Optional | Override realm context |
|
|
174
|
+
|
|
175
|
+
### Returns
|
|
176
|
+
|
|
177
|
+
**Promise\<Object\>** - Organization representation
|
|
178
|
+
|
|
179
|
+
### Examples
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
const org = await KeycloakManager.organizations.findOne({
|
|
183
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
console.log('Organization:', org.name);
|
|
187
|
+
console.log('Display Name:', org.displayName);
|
|
188
|
+
console.log('URL:', org.url);
|
|
189
|
+
console.log('Attributes:', org.attributes);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## update()
|
|
195
|
+
|
|
196
|
+
Update an existing organization. This performs a merge of the current organization data with the provided updates.
|
|
197
|
+
|
|
198
|
+
**Syntax:**
|
|
199
|
+
```javascript
|
|
200
|
+
await KeycloakManager.organizations.update(filter, organizationRepresentation)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Parameters
|
|
204
|
+
|
|
205
|
+
#### filter (Object) ⚠️ Required
|
|
206
|
+
|
|
207
|
+
| Property | Type | Required | Description |
|
|
208
|
+
|----------|------|----------|-------------|
|
|
209
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
210
|
+
|
|
211
|
+
#### organizationRepresentation (Object) ⚠️ Required
|
|
212
|
+
|
|
213
|
+
Object containing fields to update (same structure as `create()`).
|
|
214
|
+
|
|
215
|
+
### Returns
|
|
216
|
+
|
|
217
|
+
**Promise\<void\>** - Resolves when update completes
|
|
218
|
+
|
|
219
|
+
### Examples
|
|
220
|
+
|
|
221
|
+
#### Update Display Name and URL
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
await KeycloakManager.organizations.update(
|
|
225
|
+
{ id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479' },
|
|
226
|
+
{
|
|
227
|
+
displayName: 'ACME Corporation (Updated)',
|
|
228
|
+
url: 'https://www.acmecorp.com'
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
console.log('Organization updated');
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### Update Attributes
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
await KeycloakManager.organizations.update(
|
|
239
|
+
{ id: orgId },
|
|
240
|
+
{
|
|
241
|
+
attributes: {
|
|
242
|
+
tier: ['Premium'],
|
|
243
|
+
status: ['Active']
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Notes
|
|
250
|
+
|
|
251
|
+
- The update performs a MERGE operation - existing fields not mentioned are preserved.
|
|
252
|
+
- The `name` field, if provided, will be updated; otherwise the current name is kept.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## del()
|
|
257
|
+
|
|
258
|
+
Delete an organization.
|
|
259
|
+
|
|
260
|
+
**Syntax:**
|
|
261
|
+
```javascript
|
|
262
|
+
await KeycloakManager.organizations.del(filter)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Parameters
|
|
266
|
+
|
|
267
|
+
#### filter (Object) ⚠️ Required
|
|
268
|
+
|
|
269
|
+
| Property | Type | Required | Description |
|
|
270
|
+
|----------|------|----------|-------------|
|
|
271
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
272
|
+
|
|
273
|
+
### Returns
|
|
274
|
+
|
|
275
|
+
**Promise\<void\>** - Resolves when deletion completes
|
|
276
|
+
|
|
277
|
+
### Examples
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
await KeycloakManager.organizations.del({
|
|
281
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
console.log('Organization deleted');
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Warning
|
|
288
|
+
|
|
289
|
+
Deleting an organization removes all associated memberships and identity provider links.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## addMember()
|
|
294
|
+
|
|
295
|
+
Add a user as a member of an organization.
|
|
296
|
+
|
|
297
|
+
**Syntax:**
|
|
298
|
+
```javascript
|
|
299
|
+
await KeycloakManager.organizations.addMember(filter)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Parameters
|
|
303
|
+
|
|
304
|
+
#### filter (Object) ⚠️ Required
|
|
305
|
+
|
|
306
|
+
| Property | Type | Required | Description |
|
|
307
|
+
|----------|------|----------|-------------|
|
|
308
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
309
|
+
| `userId` | string | ⚠️ Yes | User UUID |
|
|
310
|
+
|
|
311
|
+
### Returns
|
|
312
|
+
|
|
313
|
+
**Promise\<void\>** - Resolves when user is added
|
|
314
|
+
|
|
315
|
+
### Examples
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
// First, find or create a user
|
|
319
|
+
const users = await KeycloakManager.users.find({ username: 'john.doe' });
|
|
320
|
+
const userId = users[0].id;
|
|
321
|
+
|
|
322
|
+
// Find organization
|
|
323
|
+
const orgs = await KeycloakManager.organizations.find({ search: 'acme' });
|
|
324
|
+
const orgId = orgs[0].id;
|
|
325
|
+
|
|
326
|
+
// Add user to organization
|
|
327
|
+
await KeycloakManager.organizations.addMember({
|
|
328
|
+
id: orgId,
|
|
329
|
+
userId: userId
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
console.log('User added to organization');
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## listMembers()
|
|
338
|
+
|
|
339
|
+
List all members (users) of an organization.
|
|
340
|
+
|
|
341
|
+
**Syntax:**
|
|
342
|
+
```javascript
|
|
343
|
+
const members = await KeycloakManager.organizations.listMembers(filter)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Parameters
|
|
347
|
+
|
|
348
|
+
#### filter (Object) ⚠️ Required
|
|
349
|
+
|
|
350
|
+
| Property | Type | Required | Description |
|
|
351
|
+
|----------|------|----------|-------------|
|
|
352
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
353
|
+
| `first` | number | 📋 Optional | Index of first result (pagination) |
|
|
354
|
+
| `max` | number | 📋 Optional | Maximum number of results |
|
|
355
|
+
|
|
356
|
+
### Returns
|
|
357
|
+
|
|
358
|
+
**Promise\<Array\>** - Array of user representations
|
|
359
|
+
|
|
360
|
+
### Examples
|
|
361
|
+
|
|
362
|
+
```javascript
|
|
363
|
+
const members = await KeycloakManager.organizations.listMembers({
|
|
364
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
|
|
365
|
+
max: 100
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
console.log(`Organization has ${members.length} members`);
|
|
369
|
+
members.forEach(user => {
|
|
370
|
+
console.log(`- ${user.username} (${user.email})`);
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## delMember()
|
|
377
|
+
|
|
378
|
+
Remove a user from an organization.
|
|
379
|
+
|
|
380
|
+
**Syntax:**
|
|
381
|
+
```javascript
|
|
382
|
+
await KeycloakManager.organizations.delMember(filter)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Parameters
|
|
386
|
+
|
|
387
|
+
#### filter (Object) ⚠️ Required
|
|
388
|
+
|
|
389
|
+
| Property | Type | Required | Description |
|
|
390
|
+
|----------|------|----------|-------------|
|
|
391
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
392
|
+
| `userId` | string | ⚠️ Yes | User UUID |
|
|
393
|
+
|
|
394
|
+
### Returns
|
|
395
|
+
|
|
396
|
+
**Promise\<void\>** - Resolves when user is removed
|
|
397
|
+
|
|
398
|
+
### Examples
|
|
399
|
+
|
|
400
|
+
```javascript
|
|
401
|
+
await KeycloakManager.organizations.delMember({
|
|
402
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
|
|
403
|
+
userId: 'a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d'
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
console.log('User removed from organization');
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## addIdentityProvider()
|
|
412
|
+
|
|
413
|
+
Link an identity provider to an organization for federated login.
|
|
414
|
+
|
|
415
|
+
**Syntax:**
|
|
416
|
+
```javascript
|
|
417
|
+
await KeycloakManager.organizations.addIdentityProvider(filter)
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Parameters
|
|
421
|
+
|
|
422
|
+
#### filter (Object) ⚠️ Required
|
|
423
|
+
|
|
424
|
+
| Property | Type | Required | Description |
|
|
425
|
+
|----------|------|----------|-------------|
|
|
426
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
427
|
+
| `alias` | string | ⚠️ Yes | Identity provider alias |
|
|
428
|
+
|
|
429
|
+
### Returns
|
|
430
|
+
|
|
431
|
+
**Promise\<void\>** - Resolves when IdP is linked
|
|
432
|
+
|
|
433
|
+
### Examples
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
// First, ensure identity provider exists
|
|
437
|
+
const idps = await KeycloakManager.identityProviders.find();
|
|
438
|
+
console.log('Available IdPs:', idps.map(i => i.alias));
|
|
439
|
+
|
|
440
|
+
// Link Google IdP to organization
|
|
441
|
+
await KeycloakManager.organizations.addIdentityProvider({
|
|
442
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
|
|
443
|
+
alias: 'google'
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
console.log('Identity provider linked to organization');
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## listIdentityProviders()
|
|
452
|
+
|
|
453
|
+
List all identity providers linked to an organization.
|
|
454
|
+
|
|
455
|
+
**Syntax:**
|
|
456
|
+
```javascript
|
|
457
|
+
const idps = await KeycloakManager.organizations.listIdentityProviders(filter)
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Parameters
|
|
461
|
+
|
|
462
|
+
#### filter (Object) ⚠️ Required
|
|
463
|
+
|
|
464
|
+
| Property | Type | Required | Description |
|
|
465
|
+
|----------|------|----------|-------------|
|
|
466
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
467
|
+
|
|
468
|
+
### Returns
|
|
469
|
+
|
|
470
|
+
**Promise\<Array\>** - Array of identity provider representations
|
|
471
|
+
|
|
472
|
+
### Examples
|
|
473
|
+
|
|
474
|
+
```javascript
|
|
475
|
+
const idps = await KeycloakManager.organizations.listIdentityProviders({
|
|
476
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
console.log(`Organization has ${idps.length} linked identity providers`);
|
|
480
|
+
idps.forEach(idp => {
|
|
481
|
+
console.log(`- ${idp.alias} (${idp.providerId})`);
|
|
482
|
+
});
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
## delIdentityProvider()
|
|
488
|
+
|
|
489
|
+
Unlink an identity provider from an organization.
|
|
490
|
+
|
|
491
|
+
**Syntax:**
|
|
492
|
+
```javascript
|
|
493
|
+
await KeycloakManager.organizations.delIdentityProvider(filter)
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Parameters
|
|
497
|
+
|
|
498
|
+
#### filter (Object) ⚠️ Required
|
|
499
|
+
|
|
500
|
+
| Property | Type | Required | Description |
|
|
501
|
+
|----------|------|----------|-------------|
|
|
502
|
+
| `id` | string | ⚠️ Yes | Organization UUID |
|
|
503
|
+
| `alias` | string | ⚠️ Yes | Identity provider alias |
|
|
504
|
+
|
|
505
|
+
### Returns
|
|
506
|
+
|
|
507
|
+
**Promise\<void\>** - Resolves when IdP is unlinked
|
|
508
|
+
|
|
509
|
+
### Examples
|
|
510
|
+
|
|
511
|
+
```javascript
|
|
512
|
+
await KeycloakManager.organizations.delIdentityProvider({
|
|
513
|
+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
|
|
514
|
+
alias: 'google'
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
console.log('Identity provider unlinked from organization');
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## Complete Workflow Example
|
|
523
|
+
|
|
524
|
+
```javascript
|
|
525
|
+
const KeycloakManager = require('keycloak-api-manager');
|
|
526
|
+
|
|
527
|
+
async function organizationWorkflow() {
|
|
528
|
+
// Setup
|
|
529
|
+
await KeycloakManager.configure({
|
|
530
|
+
baseUrl: 'https://keycloak.example.com',
|
|
531
|
+
realmName: 'master',
|
|
532
|
+
username: 'admin',
|
|
533
|
+
password: 'admin',
|
|
534
|
+
grantType: 'password',
|
|
535
|
+
clientId: 'admin-cli'
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
KeycloakManager.setConfig({ realmName: 'my-app' });
|
|
539
|
+
|
|
540
|
+
try {
|
|
541
|
+
// 1. Create organization
|
|
542
|
+
const org = await KeycloakManager.organizations.create({
|
|
543
|
+
name: 'tech-corp',
|
|
544
|
+
displayName: 'Technology Corporation',
|
|
545
|
+
url: 'https://techcorp.io',
|
|
546
|
+
attributes: {
|
|
547
|
+
industry: ['Technology'],
|
|
548
|
+
size: ['Large']
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
console.log('✓ Created organization:', org.id);
|
|
552
|
+
|
|
553
|
+
// 2. Find user to add
|
|
554
|
+
const users = await KeycloakManager.users.find({
|
|
555
|
+
username: 'john.doe',
|
|
556
|
+
exact: true
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
if (users.length > 0) {
|
|
560
|
+
// 3. Add user as member
|
|
561
|
+
await KeycloakManager.organizations.addMember({
|
|
562
|
+
id: org.id,
|
|
563
|
+
userId: users[0].id
|
|
564
|
+
});
|
|
565
|
+
console.log('✓ Added user to organization');
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// 4. Link identity provider
|
|
569
|
+
await KeycloakManager.organizations.addIdentityProvider({
|
|
570
|
+
id: org.id,
|
|
571
|
+
alias: 'google'
|
|
572
|
+
});
|
|
573
|
+
console.log('✓ Linked Google IdP');
|
|
574
|
+
|
|
575
|
+
// 5. List members
|
|
576
|
+
const members = await KeycloakManager.organizations.listMembers({
|
|
577
|
+
id: org.id
|
|
578
|
+
});
|
|
579
|
+
console.log(`✓ Organization has ${members.length} members`);
|
|
580
|
+
|
|
581
|
+
// 6. List identity providers
|
|
582
|
+
const idps = await KeycloakManager.organizations.listIdentityProviders({
|
|
583
|
+
id: org.id
|
|
584
|
+
});
|
|
585
|
+
console.log(`✓ Organization has ${idps.length} linked IdPs`);
|
|
586
|
+
|
|
587
|
+
// 7. Update organization
|
|
588
|
+
await KeycloakManager.organizations.update(
|
|
589
|
+
{ id: org.id },
|
|
590
|
+
{ displayName: 'Technology Corporation (Updated)' }
|
|
591
|
+
);
|
|
592
|
+
console.log('✓ Updated organization');
|
|
593
|
+
|
|
594
|
+
// 8. Cleanup (optional)
|
|
595
|
+
// await KeycloakManager.organizations.del({ id: org.id });
|
|
596
|
+
// console.log('✓ Deleted organization');
|
|
597
|
+
|
|
598
|
+
} catch (error) {
|
|
599
|
+
console.error('✗ Error:', error.message);
|
|
600
|
+
} finally {
|
|
601
|
+
KeycloakManager.stop();
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
organizationWorkflow();
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## See Also
|
|
611
|
+
|
|
612
|
+
- [API Reference](../api-reference.md) - Complete API index
|
|
613
|
+
- [Users API](users.md) - User management for adding members
|
|
614
|
+
- [Identity Providers API](identity-providers.md) - IdP configuration
|
|
615
|
+
- [Configuration](configuration.md) - Authentication setup
|