keycloak-api-manager 4.0.0 → 5.0.0
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/Handlers/attackDetectionHandler.js +64 -0
- package/Handlers/clientPoliciesHandler.js +120 -0
- package/Handlers/groupsHandler.js +32 -0
- package/Handlers/organizationsHandler.js +243 -0
- package/Handlers/serverInfoHandler.js +36 -0
- package/Handlers/userProfileHandler.js +121 -0
- package/README.md +83 -7157
- package/docs/architecture.md +47 -0
- package/docs/deployment.md +32 -0
- package/docs/keycloak-setup.md +47 -0
- package/docs/test-configuration.md +43 -0
- package/docs/testing.md +60 -0
- package/index.js +156 -240
- package/package.json +28 -15
- package/test/.mocharc.json +2 -2
- package/test/config/secrets.json +12 -0
- package/test/docker-keycloak/certs/keycloak.crt +58 -0
- package/test/docker-keycloak/certs/keycloak.key +28 -0
- package/test/docker-keycloak/docker-compose-https.yml +2 -0
- package/test/docker-keycloak/docker-compose.yml +4 -4
- package/test/helpers/matrix.js +16 -0
- package/test/matrix/auth.json +27 -0
- package/test/matrix/clients.json +45 -0
- package/test/matrix/realms-components-idp.json +37 -0
- package/test/matrix/users-roles-groups.json +26 -0
- package/test/package-lock.json +3032 -0
- package/test/specs/attackDetection.test.js +102 -0
- package/test/specs/clientCredentials.test.js +79 -0
- package/test/specs/clientPolicies.test.js +162 -0
- package/test/specs/{debugClientLibrary.test.js → diagnostics/debugClientLibrary.test.js} +2 -2
- package/test/specs/groupPermissions.test.js +87 -0
- package/test/specs/matrix/matrix-auth.test.js +112 -0
- package/test/specs/matrix/matrix-clients.test.js +59 -0
- package/test/specs/matrix/matrix-realms-components-idp.test.js +111 -0
- package/test/specs/matrix/matrix-users-roles-groups.test.js +68 -0
- package/test/specs/organizations.test.js +183 -0
- package/test/specs/serverInfo.test.js +140 -0
- package/test/specs/userProfile.test.js +135 -0
- package/test/{enableServerFeatures.js → support/enableServerFeatures.js} +43 -26
- package/test/{setup.js → support/setup.js} +3 -3
- package/test/support/testConfig.js +69 -0
- package/test/testConfig.js +1 -69
- package/test-output.log +72 -0
- package/test/TESTING.md +0 -327
- package/test/config/CONFIGURATION.md +0 -170
- package/test/diagnostic-protocol-mappers.js +0 -189
- package/test/docker-keycloak/DEPLOYMENT_GUIDE.md +0 -262
- package/test/helpers/setup.js +0 -186
package/test/TESTING.md
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
# Keycloak API Manager - Test Suite
|
|
2
|
-
|
|
3
|
-
Comprehensive test suite for `keycloak-api-manager` library.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
This test workspace validates all administrative functions provided by the library against a real Keycloak instance. Tests cover:
|
|
8
|
-
|
|
9
|
-
- **Authentication Management** - Required actions, authentication flows, executions
|
|
10
|
-
- **Clients** - CRUD operations, roles, secrets, scopes, sessions, authorization services
|
|
11
|
-
- **Client Scopes** - Management, protocol mappers, scope mappings
|
|
12
|
-
- **Components** - Provider listing, CRUD operations, sub-components
|
|
13
|
-
- **Groups** - CRUD, members, role mappings, admin permissions
|
|
14
|
-
- **Identity Providers** - Factory listing, CRUD, mappers
|
|
15
|
-
- **Realms** - Full lifecycle, configuration, events, keys, localization
|
|
16
|
-
- **Roles** - CRUD, composite roles, user assignments
|
|
17
|
-
- **Users** - CRUD, credentials, groups, role mappings, sessions, impersonation
|
|
18
|
-
|
|
19
|
-
## Architecture
|
|
20
|
-
|
|
21
|
-
### Shared Test Realm Strategy
|
|
22
|
-
|
|
23
|
-
Unlike traditional test approaches where each suite creates/destroys its own realm, this implementation uses a **shared test realm** created once before all tests:
|
|
24
|
-
|
|
25
|
-
**Benefits**:
|
|
26
|
-
- ⚡ **5-10x faster** - Eliminates repeated realm creation overhead (~2-5s per test)
|
|
27
|
-
- 🔄 **Consistent environment** - All tests run against identical infrastructure
|
|
28
|
-
- 🛡️ **Idempotent setup** - Running tests multiple times doesn't recreate existing resources
|
|
29
|
-
- 🎯 **Isolated resources** - Tests create unique resources (e.g., `user-${timestamp}`) to avoid conflicts
|
|
30
|
-
|
|
31
|
-
**Trade-offs**:
|
|
32
|
-
- Requires cleanup of test-specific resources (most tests handle this)
|
|
33
|
-
- Shared realm means tests can't modify realm-level settings without affecting others
|
|
34
|
-
|
|
35
|
-
### File Structure
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
test/
|
|
39
|
-
├── config/ # Configuration files (propertiesmanager)
|
|
40
|
-
│ ├── default.json # Base configuration (committed)
|
|
41
|
-
│ ├── secrets.json # Passwords (gitignored, required)
|
|
42
|
-
│ ├── local.json # Developer overrides (gitignored, optional)
|
|
43
|
-
│ ├── local.json.example # Template for local.json
|
|
44
|
-
│ └── CONFIGURATION.md # Configuration documentation
|
|
45
|
-
├── specs/ # Test suites
|
|
46
|
-
│ ├── authenticationManagement.test.js
|
|
47
|
-
│ ├── clients.test.js
|
|
48
|
-
│ ├── clientScopes.test.js
|
|
49
|
-
│ ├── components.test.js
|
|
50
|
-
│ ├── groups.test.js
|
|
51
|
-
│ ├── identityProviders.test.js
|
|
52
|
-
│ ├── realms.test.js
|
|
53
|
-
│ ├── roles.test.js
|
|
54
|
-
│ └── users.test.js
|
|
55
|
-
├── .mocharc.json # Mocha configuration
|
|
56
|
-
├── enableServerFeatures.js # Creates shared test infrastructure
|
|
57
|
-
├── package.json # Test dependencies
|
|
58
|
-
├── setup.js # Global Mocha hooks
|
|
59
|
-
└── testConfig.js # Configuration loader and exports
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Key Components
|
|
63
|
-
|
|
64
|
-
#### `testConfig.js`
|
|
65
|
-
Centralized configuration module that:
|
|
66
|
-
- Sets up propertiesmanager environment
|
|
67
|
-
- Loads and merges config files (default → secrets → local)
|
|
68
|
-
- Exports standardized constants for tests:
|
|
69
|
-
- `KEYCLOAK_CONFIG` - Admin connection settings
|
|
70
|
-
- `TEST_REALM` - Shared realm name
|
|
71
|
-
- `TEST_CLIENT_*` - Client configuration
|
|
72
|
-
- `TEST_USER_*` - User details and credentials
|
|
73
|
-
- `TEST_ROLES` - Array of test roles
|
|
74
|
-
- `TEST_GROUP_NAME` - Test group name
|
|
75
|
-
- `TEST_CLIENT_SCOPE` - Client scope name
|
|
76
|
-
- `generateUniqueName()` - Helper for unique resource names
|
|
77
|
-
|
|
78
|
-
#### `setup.js`
|
|
79
|
-
Global Mocha hooks loaded via `.mocharc.json`:
|
|
80
|
-
- Runs `enableServerFeatures()` once in `before()` hook
|
|
81
|
-
- Sets 30s timeout for realm creation
|
|
82
|
-
- Logs setup progress to console
|
|
83
|
-
|
|
84
|
-
#### `enableServerFeatures.js`
|
|
85
|
-
Infrastructure setup script that creates (if not exists):
|
|
86
|
-
1. **Test Realm** - Isolated environment for all tests
|
|
87
|
-
2. **Test Client** - Service account client for auth tests
|
|
88
|
-
3. **Test User** - Standard user with credentials
|
|
89
|
-
4. **Test Roles** - Multiple roles for RBAC testing
|
|
90
|
-
5. **Test Group** - Group for membership tests
|
|
91
|
-
6. **Fine-grained Permissions** - Admin permissions (if server supports)
|
|
92
|
-
7. **Client Scope** - For scope mapping tests
|
|
93
|
-
|
|
94
|
-
Runs idempotently - safe to execute multiple times.
|
|
95
|
-
|
|
96
|
-
#### `.mocharc.json`
|
|
97
|
-
Mocha configuration:
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"file": ["setup.js"], // Load global hooks before tests
|
|
101
|
-
"spec": ["specs/*.test.js"] // Run all test suites
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Running Tests
|
|
106
|
-
|
|
107
|
-
### Prerequisites
|
|
108
|
-
|
|
109
|
-
1. **Keycloak Instance**: Running and accessible
|
|
110
|
-
2. **Configuration**: Create `test/config/secrets.json` with admin password
|
|
111
|
-
3. **SSH Tunnel** (if remote): Ensure tunnel is active before running tests
|
|
112
|
-
|
|
113
|
-
### Commands
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
# Install dependencies and run all tests
|
|
117
|
-
npm test
|
|
118
|
-
|
|
119
|
-
# Or step-by-step:
|
|
120
|
-
npm --prefix test install # Install test dependencies
|
|
121
|
-
npm --prefix test test # Run all tests
|
|
122
|
-
|
|
123
|
-
# Run specific test suite
|
|
124
|
-
npm --prefix test test -- --grep "Users Handler"
|
|
125
|
-
|
|
126
|
-
# Run specific test
|
|
127
|
-
npm --prefix test test -- --grep "should create, find, update, and delete clients"
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Diagnostics
|
|
131
|
-
|
|
132
|
-
### Protocol Mapper Diagnostic Script
|
|
133
|
-
|
|
134
|
-
The file [test/diagnostic-protocol-mappers.js](test/diagnostic-protocol-mappers.js) is a manual troubleshooting script.
|
|
135
|
-
It is not part of the automated Mocha test suite. It is used to validate protocol mapper creation via:
|
|
136
|
-
|
|
137
|
-
- Direct Admin REST API calls
|
|
138
|
-
- The library client (`keycloak-api-manager`)
|
|
139
|
-
|
|
140
|
-
Run it manually when you need to debug protocol mapper behavior:
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
node test/diagnostic-protocol-mappers.js
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
It uses the same `test/config` configuration and the shared test realm.
|
|
147
|
-
|
|
148
|
-
### Expected Output
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
propertiesmanager Configuration loaded successfully for environment: test
|
|
152
|
-
|
|
153
|
-
=== Running global test setup ===
|
|
154
|
-
|
|
155
|
-
Configuring Keycloak Admin Client...
|
|
156
|
-
|
|
157
|
-
1. Setting up test realm: keycloak-api-manager-test-realm
|
|
158
|
-
✓ Test realm already exists: keycloak-api-manager-test-realm
|
|
159
|
-
|
|
160
|
-
2. Setting up test client...
|
|
161
|
-
✓ Test client updated: test-client
|
|
162
|
-
|
|
163
|
-
[... additional setup output ...]
|
|
164
|
-
|
|
165
|
-
✓ Keycloak server configuration complete!
|
|
166
|
-
|
|
167
|
-
=== Global setup complete ===
|
|
168
|
-
|
|
169
|
-
Users Handler
|
|
170
|
-
✔ should find, findOne, count and update users
|
|
171
|
-
✔ should manage password and credentials
|
|
172
|
-
[... more tests ...]
|
|
173
|
-
|
|
174
|
-
59 passing (9s)
|
|
175
|
-
7 pending
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Configuration
|
|
179
|
-
|
|
180
|
-
Configuration uses [propertiesmanager](https://www.npmjs.com/package/propertiesmanager) for hierarchical config management.
|
|
181
|
-
|
|
182
|
-
**Quick Setup**:
|
|
183
|
-
|
|
184
|
-
1. Copy secrets template:
|
|
185
|
-
```bash
|
|
186
|
-
cp test/config/local.json.example test/config/secrets.json
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
2. Edit `test/config/secrets.json`:
|
|
190
|
-
```json
|
|
191
|
-
{
|
|
192
|
-
"test": {
|
|
193
|
-
"keycloak": {
|
|
194
|
-
"password": "your-admin-password"
|
|
195
|
-
},
|
|
196
|
-
"realm": {
|
|
197
|
-
"user": {
|
|
198
|
-
"password": "test-user-password"
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
3. (Optional) Override baseUrl in `test/config/local.json`:
|
|
206
|
-
```json
|
|
207
|
-
{
|
|
208
|
-
"test": {
|
|
209
|
-
"keycloak": {
|
|
210
|
-
"baseUrl": "http://localhost:8080"
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
See [config/CONFIGURATION.md](config/CONFIGURATION.md) for detailed configuration documentation.
|
|
217
|
-
|
|
218
|
-
## Test Writing Guidelines
|
|
219
|
-
|
|
220
|
-
### Use Shared Configuration
|
|
221
|
-
|
|
222
|
-
```javascript
|
|
223
|
-
const {
|
|
224
|
-
TEST_REALM,
|
|
225
|
-
TEST_CLIENT_ID,
|
|
226
|
-
TEST_USER_USERNAME,
|
|
227
|
-
generateUniqueName
|
|
228
|
-
} = require('../testConfig');
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Create Unique Resources
|
|
232
|
-
|
|
233
|
-
Avoid conflicts by using timestamps or UUIDs:
|
|
234
|
-
|
|
235
|
-
```javascript
|
|
236
|
-
const userName = generateUniqueName('test-user');
|
|
237
|
-
const roleName = `role-${Date.now()}`;
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Respect Shared Realm
|
|
241
|
-
|
|
242
|
-
Don't:
|
|
243
|
-
- Modify realm-level settings (will affect other tests)
|
|
244
|
-
- Delete the shared realm
|
|
245
|
-
- Assume exclusive access to shared resources (client, user, roles)
|
|
246
|
-
|
|
247
|
-
Do:
|
|
248
|
-
- Create test-specific resources with unique names
|
|
249
|
-
- Clean up resources created during test (in `after()` hooks)
|
|
250
|
-
- Use the shared infrastructure for read operations
|
|
251
|
-
|
|
252
|
-
### Handle Feature Availability
|
|
253
|
-
|
|
254
|
-
Some Keycloak features may not be available on all server versions:
|
|
255
|
-
|
|
256
|
-
```javascript
|
|
257
|
-
try {
|
|
258
|
-
await keycloakManager.users.listConsents({ realm: TEST_REALM, id: userId });
|
|
259
|
-
} catch (err) {
|
|
260
|
-
if (err.response?.status === 404) {
|
|
261
|
-
this.skip(); // Skip test if feature not available
|
|
262
|
-
}
|
|
263
|
-
throw err;
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
## Troubleshooting
|
|
268
|
-
|
|
269
|
-
### Tests hang indefinitely
|
|
270
|
-
- Check Keycloak instance is running and accessible
|
|
271
|
-
- Verify SSH tunnel is active (if using remote Keycloak)
|
|
272
|
-
- Check `baseUrl` in configuration matches your setup
|
|
273
|
-
|
|
274
|
-
### "Configuration loading failed"
|
|
275
|
-
- Ensure `test/config/secrets.json` exists
|
|
276
|
-
- Verify JSON syntax (no trailing commas)
|
|
277
|
-
- Check environment wrapper present: `{ "test": { ... } }`
|
|
278
|
-
|
|
279
|
-
### "Access denied" or 403 errors
|
|
280
|
-
- Verify admin credentials in `secrets.json`
|
|
281
|
-
- Ensure admin user has realm-management permissions
|
|
282
|
-
- Check `realmName` is correct (usually "master" for admin user)
|
|
283
|
-
|
|
284
|
-
### "Realm not found" errors
|
|
285
|
-
- Check global setup ran successfully (see console output)
|
|
286
|
-
- Verify shared realm created: look for "✓ Test realm created/exists"
|
|
287
|
-
- Ensure realm name matches configuration
|
|
288
|
-
|
|
289
|
-
### Slow test execution
|
|
290
|
-
- First run is slower (~10-20s) due to realm setup
|
|
291
|
-
- Subsequent runs should be faster (~5-10s)
|
|
292
|
-
- If still slow, check network latency to Keycloak instance
|
|
293
|
-
- Consider using local Keycloak instance instead of remote tunnel
|
|
294
|
-
|
|
295
|
-
### Tests fail inconsistently
|
|
296
|
-
- May indicate race conditions or shared resource conflicts
|
|
297
|
-
- Ensure test resources use unique names
|
|
298
|
-
- Check cleanup logic in `after()` hooks
|
|
299
|
-
- Run single test in isolation to verify: `--grep "test name"`
|
|
300
|
-
|
|
301
|
-
## Performance Metrics
|
|
302
|
-
|
|
303
|
-
Typical performance on 2020 MacBook Pro with local Keycloak:
|
|
304
|
-
|
|
305
|
-
- **Global Setup**: ~10-15 seconds (runs once)
|
|
306
|
-
- **Full Suite**: ~9 seconds (59 tests)
|
|
307
|
-
- **Individual Test**: ~50-200ms average
|
|
308
|
-
|
|
309
|
-
Performance with remote Keycloak over SSH tunnel:
|
|
310
|
-
- **Global Setup**: ~15-25 seconds
|
|
311
|
-
- **Full Suite**: ~15-30 seconds
|
|
312
|
-
|
|
313
|
-
## Contributing
|
|
314
|
-
|
|
315
|
-
When adding new tests:
|
|
316
|
-
|
|
317
|
-
1. Follow existing patterns in `specs/` directory
|
|
318
|
-
2. Import shared config from `testConfig.js`
|
|
319
|
-
3. Use `generateUniqueName()` for test resources
|
|
320
|
-
4. Add cleanup in `after()` hooks
|
|
321
|
-
5. Handle optional features gracefully (use `this.skip()`)
|
|
322
|
-
6. Document any new configuration requirements
|
|
323
|
-
7. Update this README if adding new test categories
|
|
324
|
-
|
|
325
|
-
## License
|
|
326
|
-
|
|
327
|
-
Same as parent project.
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# Test Configuration
|
|
2
|
-
|
|
3
|
-
This directory contains hierarchical configuration files managed by [propertiesmanager](https://www.npmjs.com/package/propertiesmanager).
|
|
4
|
-
|
|
5
|
-
## Configuration Files
|
|
6
|
-
|
|
7
|
-
### `default.json` (required, committed to git)
|
|
8
|
-
Base configuration with non-sensitive defaults. Contains the "test" environment section with:
|
|
9
|
-
|
|
10
|
-
- **keycloak**: Admin connection settings (baseUrl, realmName, clientId, username, grantType)
|
|
11
|
-
- **realm**: Test realm infrastructure specifications (realm name, client, user, roles, groups, scopes)
|
|
12
|
-
|
|
13
|
-
**When to edit**: Update non-sensitive defaults that all developers should use.
|
|
14
|
-
|
|
15
|
-
### `secrets.json` (required, gitignored)
|
|
16
|
-
Sensitive credentials overlaid on default.json. Contains passwords and secrets.
|
|
17
|
-
|
|
18
|
-
**Structure**:
|
|
19
|
-
```json
|
|
20
|
-
{
|
|
21
|
-
"test": {
|
|
22
|
-
"keycloak": {
|
|
23
|
-
"password": "admin"
|
|
24
|
-
},
|
|
25
|
-
"realm": {
|
|
26
|
-
"user": {
|
|
27
|
-
"password": "test-password"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**When to create**: Before running tests for the first time. Copy structure above and fill in your Keycloak admin password.
|
|
35
|
-
|
|
36
|
-
### `local.json` (optional, gitignored)
|
|
37
|
-
Developer-specific overrides for local environments. Useful for:
|
|
38
|
-
- Custom baseUrl (localhost instead of tunnel)
|
|
39
|
-
- Different realm names
|
|
40
|
-
- Custom ports
|
|
41
|
-
|
|
42
|
-
**Example**:
|
|
43
|
-
```json
|
|
44
|
-
{
|
|
45
|
-
"test": {
|
|
46
|
-
"keycloak": {
|
|
47
|
-
"baseUrl": "http://localhost:8080"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**When to create**: Only if you need to override defaults for your local environment.
|
|
54
|
-
|
|
55
|
-
### `local.json.example` (committed to git)
|
|
56
|
-
Template showing example local overrides. Copy to `local.json` and customize.
|
|
57
|
-
|
|
58
|
-
## Configuration Loading
|
|
59
|
-
|
|
60
|
-
Files are merged in this order:
|
|
61
|
-
1. **default.json** - Base configuration
|
|
62
|
-
2. **secrets.json** - Overlays sensitive credentials
|
|
63
|
-
3. **local.json** - Overlays developer-specific settings (if exists)
|
|
64
|
-
|
|
65
|
-
The environment section is determined by `NODE_ENV` (default: "test").
|
|
66
|
-
|
|
67
|
-
## Important Notes
|
|
68
|
-
|
|
69
|
-
### Environment Wrapper Required
|
|
70
|
-
All configuration must be wrapped in an environment key:
|
|
71
|
-
|
|
72
|
-
✅ **Correct**:
|
|
73
|
-
```json
|
|
74
|
-
{
|
|
75
|
-
"test": {
|
|
76
|
-
"keycloak": { "baseUrl": "..." }
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
❌ **Incorrect**:
|
|
82
|
-
```json
|
|
83
|
-
{
|
|
84
|
-
"keycloak": { "baseUrl": "..." }
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Git Ignored Files
|
|
89
|
-
These files are excluded from git (see `.gitignore`):
|
|
90
|
-
- `secrets.json` - Contains passwords
|
|
91
|
-
- `local.json` - Developer-specific customizations
|
|
92
|
-
|
|
93
|
-
### Security
|
|
94
|
-
- Never commit `secrets.json` or `local.json`
|
|
95
|
-
- Keep passwords out of `default.json`
|
|
96
|
-
- Use secure passwords in production-like environments
|
|
97
|
-
|
|
98
|
-
## Configuration Schema
|
|
99
|
-
|
|
100
|
-
### keycloak (admin connection)
|
|
101
|
-
```json
|
|
102
|
-
{
|
|
103
|
-
"baseUrl": "http://127.0.0.1:9998", // Keycloak server URL
|
|
104
|
-
"realmName": "master", // Admin realm (usually "master")
|
|
105
|
-
"clientId": "admin-cli", // Admin client ID
|
|
106
|
-
"username": "admin", // Admin username
|
|
107
|
-
"password": "admin", // Admin password (in secrets.json)
|
|
108
|
-
"grantType": "password", // OAuth2 grant type
|
|
109
|
-
"tokenLifeSpan": 60 // Token refresh interval (seconds)
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Diagnostic Script Configuration
|
|
114
|
-
|
|
115
|
-
The manual diagnostic script [test/diagnostic-protocol-mappers.js](../diagnostic-protocol-mappers.js)
|
|
116
|
-
uses the same `test` configuration (including `baseUrl`, credentials, and realm settings).
|
|
117
|
-
It is not part of the automated test suite and must be run manually.
|
|
118
|
-
|
|
119
|
-
Run it with:
|
|
120
|
-
```bash
|
|
121
|
-
node test/diagnostic-protocol-mappers.js
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Make sure `baseUrl` points to a reachable Keycloak instance and `secrets.json` contains valid credentials.
|
|
125
|
-
|
|
126
|
-
### realm (test infrastructure)
|
|
127
|
-
```json
|
|
128
|
-
{
|
|
129
|
-
"name": "keycloak-api-manager-test-realm", // Test realm name
|
|
130
|
-
"client": {
|
|
131
|
-
"clientId": "test-client", // Test client ID
|
|
132
|
-
"clientSecret": "test-client-secret" // Test client secret
|
|
133
|
-
},
|
|
134
|
-
"user": {
|
|
135
|
-
"username": "test-user", // Test user username
|
|
136
|
-
"password": "test-password", // Test user password (in secrets.json)
|
|
137
|
-
"email": "test-user@test.local", // Test user email
|
|
138
|
-
"firstName": "Test", // Test user first name
|
|
139
|
-
"lastName": "User" // Test user last name
|
|
140
|
-
},
|
|
141
|
-
"roles": ["test-role-1", "test-role-2", "test-admin-role"], // Roles to create
|
|
142
|
-
"group": {
|
|
143
|
-
"name": "test-group" // Test group name
|
|
144
|
-
},
|
|
145
|
-
"clientScope": {
|
|
146
|
-
"name": "test-scope" // Test client scope name
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Troubleshooting
|
|
152
|
-
|
|
153
|
-
### "Configuration loading failed"
|
|
154
|
-
- Ensure `secrets.json` exists with valid JSON
|
|
155
|
-
- Check that environment wrapper "test" is present in all files
|
|
156
|
-
- Verify JSON syntax (no trailing commas, proper quotes)
|
|
157
|
-
|
|
158
|
-
### "Access denied" errors during tests
|
|
159
|
-
- Check admin username/password in `secrets.json`
|
|
160
|
-
- Verify `baseUrl` points to accessible Keycloak instance
|
|
161
|
-
- If using SSH tunnel, ensure it's active
|
|
162
|
-
|
|
163
|
-
### "Realm not found" errors
|
|
164
|
-
- Ensure global setup ran successfully (check console output)
|
|
165
|
-
- Verify realm name matches between config and test expectations
|
|
166
|
-
- Check that Keycloak instance is running and accessible
|
|
167
|
-
|
|
168
|
-
## More Information
|
|
169
|
-
|
|
170
|
-
See main project [README.md](../../README.md) for overall test architecture and execution instructions.
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const http = require('http');
|
|
3
|
-
const https = require('https');
|
|
4
|
-
|
|
5
|
-
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
6
|
-
process.env.PROPERTIES_PATH = path.join(__dirname, 'config');
|
|
7
|
-
|
|
8
|
-
const { conf } = require('propertiesmanager');
|
|
9
|
-
const keycloakManager = require('keycloak-api-manager');
|
|
10
|
-
const { TEST_REALM } = require('./testConfig');
|
|
11
|
-
|
|
12
|
-
function requestAdmin(baseUrl, token, apiPath, method = 'GET', body) {
|
|
13
|
-
const url = new URL(apiPath, baseUrl);
|
|
14
|
-
const transport = url.protocol === 'https:' ? https : http;
|
|
15
|
-
const payload = body ? JSON.stringify(body) : null;
|
|
16
|
-
|
|
17
|
-
const options = {
|
|
18
|
-
method,
|
|
19
|
-
headers: {
|
|
20
|
-
Accept: 'application/json',
|
|
21
|
-
Authorization: `Bearer ${token}`,
|
|
22
|
-
...(payload ? { 'Content-Type': 'application/json' } : {}),
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
const req = transport.request(url, options, (res) => {
|
|
28
|
-
let data = '';
|
|
29
|
-
res.on('data', (chunk) => {
|
|
30
|
-
data += chunk;
|
|
31
|
-
});
|
|
32
|
-
res.on('end', () => {
|
|
33
|
-
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
34
|
-
try {
|
|
35
|
-
const result = {
|
|
36
|
-
data: data ? JSON.parse(data) : null,
|
|
37
|
-
statusCode: res.statusCode,
|
|
38
|
-
headers: res.headers,
|
|
39
|
-
};
|
|
40
|
-
resolve(result);
|
|
41
|
-
} catch {
|
|
42
|
-
resolve({
|
|
43
|
-
data: data || null,
|
|
44
|
-
statusCode: res.statusCode,
|
|
45
|
-
headers: res.headers,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
const error = new Error(`HTTP ${res.statusCode}: ${data}`);
|
|
50
|
-
error.statusCode = res.statusCode;
|
|
51
|
-
error.response = data;
|
|
52
|
-
reject(error);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
req.on('error', reject);
|
|
58
|
-
if (payload) {
|
|
59
|
-
req.write(payload);
|
|
60
|
-
}
|
|
61
|
-
req.end();
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function main() {
|
|
66
|
-
try {
|
|
67
|
-
// Configura keycloak manager
|
|
68
|
-
const keycloakConfig = (conf && conf.keycloak) || {};
|
|
69
|
-
console.log('keycloakConfig baseUrl:', keycloakConfig.baseUrl);
|
|
70
|
-
|
|
71
|
-
if (!keycloakConfig.baseUrl) {
|
|
72
|
-
throw new Error('baseUrl not configured in keycloak config');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
await keycloakManager.configure(keycloakConfig);
|
|
76
|
-
|
|
77
|
-
keycloakManager.setConfig({ realmName: TEST_REALM });
|
|
78
|
-
const token = keycloakManager.getToken();
|
|
79
|
-
const baseUrl = keycloakConfig.baseUrl.endsWith('/') ? keycloakConfig.baseUrl : `${keycloakConfig.baseUrl}/`;
|
|
80
|
-
|
|
81
|
-
console.log('\n=== PROTOCOL MAPPER DIRECT API TEST ===');
|
|
82
|
-
console.log('Base URL:', baseUrl);
|
|
83
|
-
console.log();
|
|
84
|
-
|
|
85
|
-
// 1. Trova il test client
|
|
86
|
-
const clients = await keycloakManager.clients.find({ clientId: 'test-client' });
|
|
87
|
-
if (!clients || !clients.length) {
|
|
88
|
-
console.log('❌ Test client not found');
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
91
|
-
const testClient = clients[0];
|
|
92
|
-
console.log(`✅ Found test client: ${testClient.clientId} (ID: ${testClient.id})\n`);
|
|
93
|
-
|
|
94
|
-
// 2. Prova a creare un protocol mapper con API diretta
|
|
95
|
-
const apiPath = `/admin/realms/${TEST_REALM}/clients/${testClient.id}/protocol-mappers/models`;
|
|
96
|
-
|
|
97
|
-
const protocolMapper = {
|
|
98
|
-
name: `direct-api-test-${Date.now()}`,
|
|
99
|
-
protocol: 'openid-connect',
|
|
100
|
-
protocolMapper: 'oidc-usermodel-attribute-mapper',
|
|
101
|
-
consentRequired: false,
|
|
102
|
-
config: {
|
|
103
|
-
'user.attribute': 'email',
|
|
104
|
-
'claim.name': 'email_test',
|
|
105
|
-
'jsonType.label': 'String',
|
|
106
|
-
'id.token.claim': 'true',
|
|
107
|
-
'access.token.claim': 'true',
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
console.log(`📡 Direct API POST: ${apiPath}`);
|
|
112
|
-
console.log(`Payload: ${JSON.stringify(protocolMapper, null, 2)}\n`);
|
|
113
|
-
|
|
114
|
-
const result = await requestAdmin(
|
|
115
|
-
baseUrl,
|
|
116
|
-
token.accessToken,
|
|
117
|
-
apiPath,
|
|
118
|
-
'POST',
|
|
119
|
-
protocolMapper
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
console.log(`✅ SUCCESS - Status: ${result.statusCode}`);
|
|
123
|
-
console.log(`Location: ${result.headers.location || 'N/A'}\n`);
|
|
124
|
-
|
|
125
|
-
// 3. Verifica che sia stato creato
|
|
126
|
-
const listResult = await requestAdmin(
|
|
127
|
-
baseUrl,
|
|
128
|
-
token.accessToken,
|
|
129
|
-
apiPath,
|
|
130
|
-
'GET'
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const createdMapper = listResult.data?.find(m => m.name === protocolMapper.name);
|
|
134
|
-
if (createdMapper) {
|
|
135
|
-
console.log(`✅ Mapper verified in list:`);
|
|
136
|
-
console.log(` ID: ${createdMapper.id}`);
|
|
137
|
-
console.log(` Name: ${createdMapper.name}`);
|
|
138
|
-
console.log(` Protocol Mapper: ${createdMapper.protocolMapper}\n`);
|
|
139
|
-
|
|
140
|
-
// Cleanup
|
|
141
|
-
await requestAdmin(
|
|
142
|
-
baseUrl,
|
|
143
|
-
token.accessToken,
|
|
144
|
-
`${apiPath}/${createdMapper.id}`,
|
|
145
|
-
'DELETE'
|
|
146
|
-
);
|
|
147
|
-
console.log('🧹 Cleanup: Mapper deleted\n');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// 4. Prova con il client manager della libreria
|
|
151
|
-
console.log('=== TESTING THROUGH KEYCLOAK MANAGER ===\n');
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
await keycloakManager.clients.addProtocolMapper(
|
|
155
|
-
{ id: testClient.id },
|
|
156
|
-
{
|
|
157
|
-
name: `library-test-${Date.now()}`,
|
|
158
|
-
protocol: 'openid-connect',
|
|
159
|
-
protocolMapper: 'oidc-usermodel-attribute-mapper',
|
|
160
|
-
consentRequired: false,
|
|
161
|
-
config: {
|
|
162
|
-
'user.attribute': 'username',
|
|
163
|
-
'claim.name': 'user_name',
|
|
164
|
-
'jsonType.label': 'String',
|
|
165
|
-
'id.token.claim': 'true',
|
|
166
|
-
'access.token.claim': 'true',
|
|
167
|
-
},
|
|
168
|
-
}
|
|
169
|
-
);
|
|
170
|
-
console.log('✅ SUCCESS through keycloak-api-manager');
|
|
171
|
-
} catch (err) {
|
|
172
|
-
console.log('❌ FAILED through keycloak-api-manager');
|
|
173
|
-
console.log(`Error: ${err.message}\n`);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
console.log('\n=== SUMMARY ===');
|
|
177
|
-
console.log('Direct API: ✅ Works');
|
|
178
|
-
console.log('Library: Check output above');
|
|
179
|
-
|
|
180
|
-
} catch (err) {
|
|
181
|
-
console.error('❌ ERROR:', err.message);
|
|
182
|
-
if (err.response) {
|
|
183
|
-
console.error('Response:', err.response);
|
|
184
|
-
}
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
main();
|