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
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
|
|
4
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
5
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', 'config');
|
|
6
|
+
|
|
7
|
+
const { conf } = require('propertiesmanager');
|
|
8
|
+
const KeycloakManager = require('../../index');
|
|
9
|
+
const { TEST_REALM, generateUniqueName } = require('../testConfig');
|
|
10
|
+
|
|
11
|
+
const config = {
|
|
12
|
+
baseUrl: conf.keycloak.baseUrl,
|
|
13
|
+
realmName: conf.keycloak.realmName,
|
|
14
|
+
clientId: conf.keycloak.clientId,
|
|
15
|
+
clientSecret: conf.keycloak.clientSecret,
|
|
16
|
+
grantType: conf.keycloak.grantType,
|
|
17
|
+
username: conf.keycloak.username,
|
|
18
|
+
password: conf.keycloak.password,
|
|
19
|
+
tokenLifeSpan: conf.keycloak.tokenLifeSpan
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Integration tests for Attack Detection Handler
|
|
24
|
+
* Tests brute force detection, login failure management
|
|
25
|
+
*/
|
|
26
|
+
describe('Attack Detection Handler Tests', function () {
|
|
27
|
+
this.timeout(10000);
|
|
28
|
+
|
|
29
|
+
const testUserData = {
|
|
30
|
+
username: 'test-bruteforce-user',
|
|
31
|
+
email: 'bruteforce@test.com',
|
|
32
|
+
enabled: true,
|
|
33
|
+
credentials: [{ type: 'password', value: 'wrongpassword123', temporary: false }]
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
let createdUserId;
|
|
37
|
+
|
|
38
|
+
before(async function () {
|
|
39
|
+
await KeycloakManager.configure(config);
|
|
40
|
+
|
|
41
|
+
// Create a test user for brute force testing
|
|
42
|
+
const result = await KeycloakManager.users.create(testUserData);
|
|
43
|
+
createdUserId = result.id;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
after(async function () {
|
|
47
|
+
// Clean up test user
|
|
48
|
+
if (createdUserId) {
|
|
49
|
+
await KeycloakManager.users.del({ id: createdUserId });
|
|
50
|
+
}
|
|
51
|
+
KeycloakManager.stop();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('Brute Force Status', function () {
|
|
55
|
+
it('should get brute force status for user', async function () {
|
|
56
|
+
try {
|
|
57
|
+
const status = await KeycloakManager.attackDetection.getUserBruteForceStatus({
|
|
58
|
+
id: createdUserId
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Status should exist (even if no failures yet)
|
|
62
|
+
expect(status).to.exist;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
// API might not be available in all Keycloak versions
|
|
65
|
+
if (error.response?.status === 404) {
|
|
66
|
+
this.skip();
|
|
67
|
+
}
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should clear user login failures', async function () {
|
|
73
|
+
try {
|
|
74
|
+
await KeycloakManager.attackDetection.clearUserLoginFailures({
|
|
75
|
+
id: createdUserId
|
|
76
|
+
});
|
|
77
|
+
// If no error thrown, operation succeeded
|
|
78
|
+
expect(true).to.be.true;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
// API might not be available in all Keycloak versions
|
|
81
|
+
if (error.response?.status === 404) {
|
|
82
|
+
this.skip();
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should clear all login failures in realm', async function () {
|
|
89
|
+
try {
|
|
90
|
+
await KeycloakManager.attackDetection.clearAllLoginFailures({});
|
|
91
|
+
// If no error thrown, operation succeeded
|
|
92
|
+
expect(true).to.be.true;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
// API might not be available in all Keycloak versions
|
|
95
|
+
if (error.response?.status === 404) {
|
|
96
|
+
this.skip();
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
|
|
4
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
5
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', 'config');
|
|
6
|
+
|
|
7
|
+
const keycloakManager = require('keycloak-api-manager');
|
|
8
|
+
const { KEYCLOAK_CONFIG, TEST_CLIENT_ID, TEST_REALM } = require('../testConfig');
|
|
9
|
+
|
|
10
|
+
function buildConfig(overrides = {}) {
|
|
11
|
+
return {
|
|
12
|
+
...KEYCLOAK_CONFIG,
|
|
13
|
+
...overrides,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('Authentication - client_credentials grant', function () {
|
|
18
|
+
this.timeout(20000);
|
|
19
|
+
|
|
20
|
+
let testClientId = null;
|
|
21
|
+
let testClientSecret = null;
|
|
22
|
+
|
|
23
|
+
before(async function () {
|
|
24
|
+
// Ensure we're using the test realm
|
|
25
|
+
keycloakManager.setConfig({ realmName: TEST_REALM });
|
|
26
|
+
|
|
27
|
+
const clients = await keycloakManager.clients.find({ clientId: TEST_CLIENT_ID });
|
|
28
|
+
const testClient = clients.find((client) => client.clientId === TEST_CLIENT_ID);
|
|
29
|
+
|
|
30
|
+
if (!testClient) {
|
|
31
|
+
this.skip();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
testClientId = testClient.clientId;
|
|
36
|
+
const secret = await keycloakManager.clients.getClientSecret({ id: testClient.id });
|
|
37
|
+
testClientSecret = secret?.value;
|
|
38
|
+
|
|
39
|
+
if (!testClientSecret) {
|
|
40
|
+
this.skip();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
after(async function () {
|
|
45
|
+
if (!KEYCLOAK_CONFIG?.username || !KEYCLOAK_CONFIG?.password) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await keycloakManager.configure(
|
|
50
|
+
buildConfig({
|
|
51
|
+
grantType: KEYCLOAK_CONFIG.grantType || 'password',
|
|
52
|
+
tokenLifeSpan: KEYCLOAK_CONFIG.tokenLifeSpan || 60,
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('authenticates without refresh token errors', async function () {
|
|
58
|
+
if (!testClientId || !testClientSecret) {
|
|
59
|
+
this.skip();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await keycloakManager.configure(
|
|
64
|
+
buildConfig({
|
|
65
|
+
realmName: TEST_REALM,
|
|
66
|
+
clientId: testClientId,
|
|
67
|
+
clientSecret: testClientSecret,
|
|
68
|
+
grantType: 'client_credentials',
|
|
69
|
+
tokenLifeSpan: 60,
|
|
70
|
+
username: undefined,
|
|
71
|
+
password: undefined,
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const token = keycloakManager.getToken();
|
|
76
|
+
expect(token).to.have.property('accessToken');
|
|
77
|
+
expect(token.accessToken).to.be.a('string').and.to.have.length.greaterThan(0);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
|
|
4
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
5
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', 'config');
|
|
6
|
+
|
|
7
|
+
const { conf } = require('propertiesmanager');
|
|
8
|
+
const KeycloakManager = require('../../index');
|
|
9
|
+
const { TEST_REALM, generateUniqueName } = require('../testConfig');
|
|
10
|
+
|
|
11
|
+
const config = {
|
|
12
|
+
baseUrl: conf.keycloak.baseUrl,
|
|
13
|
+
realmName: conf.keycloak.realmName,
|
|
14
|
+
clientId: conf.keycloak.clientId,
|
|
15
|
+
clientSecret: conf.keycloak.clientSecret,
|
|
16
|
+
grantType: conf.keycloak.grantType,
|
|
17
|
+
username: conf.keycloak.username,
|
|
18
|
+
password: conf.keycloak.password,
|
|
19
|
+
tokenLifeSpan: conf.keycloak.tokenLifeSpan
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Integration tests for Client Policies Handler
|
|
24
|
+
* Tests client policies and profiles configuration (Keycloak 12+)
|
|
25
|
+
*/
|
|
26
|
+
describe('Client Policies Handler Tests', function () {
|
|
27
|
+
this.timeout(10000);
|
|
28
|
+
|
|
29
|
+
before(async function () {
|
|
30
|
+
await KeycloakManager.configure(config);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
after(async function () {
|
|
34
|
+
KeycloakManager.stop();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('Client Policies', function () {
|
|
38
|
+
let originalPolicies;
|
|
39
|
+
|
|
40
|
+
it('should get client policies', async function () {
|
|
41
|
+
try {
|
|
42
|
+
const policiesResult = await KeycloakManager.clientPolicies.getPolicies({});
|
|
43
|
+
|
|
44
|
+
expect(policiesResult).to.exist;
|
|
45
|
+
expect(policiesResult).to.have.property('policies');
|
|
46
|
+
expect(policiesResult.policies).to.be.an('array');
|
|
47
|
+
|
|
48
|
+
originalPolicies = policiesResult;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
// Client Policies API only available in Keycloak 12+
|
|
51
|
+
if (error.response?.status === 404 || error.message?.includes('clientPolicies')) {
|
|
52
|
+
this.skip();
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should update client policies', async function () {
|
|
59
|
+
if (!originalPolicies) this.skip();
|
|
60
|
+
|
|
61
|
+
const updatedPolicies = JSON.parse(JSON.stringify(originalPolicies));
|
|
62
|
+
|
|
63
|
+
// Add a test policy if it doesn't exist
|
|
64
|
+
const testPolicyExists = updatedPolicies.policies.some(
|
|
65
|
+
p => p.name === 'test-policy'
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (!testPolicyExists) {
|
|
69
|
+
updatedPolicies.policies.push({
|
|
70
|
+
name: 'test-policy',
|
|
71
|
+
description: 'Test policy for integration tests',
|
|
72
|
+
enabled: false,
|
|
73
|
+
conditions: [],
|
|
74
|
+
profiles: []
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
await KeycloakManager.clientPolicies.updatePolicies({}, updatedPolicies);
|
|
80
|
+
|
|
81
|
+
// Verify the update
|
|
82
|
+
const verifyPolicies = await KeycloakManager.clientPolicies.getPolicies({});
|
|
83
|
+
const testPolicyFound = verifyPolicies.policies.some(
|
|
84
|
+
p => p.name === 'test-policy'
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
expect(testPolicyFound).to.be.true;
|
|
88
|
+
|
|
89
|
+
// Restore original policies
|
|
90
|
+
await KeycloakManager.clientPolicies.updatePolicies({}, originalPolicies);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Restore on error
|
|
93
|
+
if (originalPolicies) {
|
|
94
|
+
await KeycloakManager.clientPolicies.updatePolicies({}, originalPolicies);
|
|
95
|
+
}
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('Client Profiles', function () {
|
|
102
|
+
let originalProfiles;
|
|
103
|
+
|
|
104
|
+
it('should get client profiles', async function () {
|
|
105
|
+
try {
|
|
106
|
+
const profilesResult = await KeycloakManager.clientPolicies.getProfiles({});
|
|
107
|
+
|
|
108
|
+
expect(profilesResult).to.exist;
|
|
109
|
+
expect(profilesResult).to.have.property('profiles');
|
|
110
|
+
expect(profilesResult.profiles).to.be.an('array');
|
|
111
|
+
|
|
112
|
+
originalProfiles = profilesResult;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
// API might not be available
|
|
115
|
+
if (error.response?.status === 404) {
|
|
116
|
+
this.skip();
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should update client profiles', async function () {
|
|
123
|
+
if (!originalProfiles) this.skip();
|
|
124
|
+
|
|
125
|
+
const updatedProfiles = JSON.parse(JSON.stringify(originalProfiles));
|
|
126
|
+
|
|
127
|
+
// Add a test profile if it doesn't exist
|
|
128
|
+
const testProfileExists = updatedProfiles.profiles.some(
|
|
129
|
+
p => p.name === 'test-profile'
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (!testProfileExists) {
|
|
133
|
+
updatedProfiles.profiles.push({
|
|
134
|
+
name: 'test-profile',
|
|
135
|
+
description: 'Test profile for integration tests',
|
|
136
|
+
executors: []
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
await KeycloakManager.clientPolicies.updateProfiles({}, updatedProfiles);
|
|
142
|
+
|
|
143
|
+
// Verify the update
|
|
144
|
+
const verifyProfiles = await KeycloakManager.clientPolicies.getProfiles({});
|
|
145
|
+
const testProfileFound = verifyProfiles.profiles.some(
|
|
146
|
+
p => p.name === 'test-profile'
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(testProfileFound).to.be.true;
|
|
150
|
+
|
|
151
|
+
// Restore original profiles
|
|
152
|
+
await KeycloakManager.clientPolicies.updateProfiles({}, originalProfiles);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
// Restore on error
|
|
155
|
+
if (originalProfiles) {
|
|
156
|
+
await KeycloakManager.clientPolicies.updateProfiles({}, originalProfiles);
|
|
157
|
+
}
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
@@ -4,11 +4,11 @@ const https = require('https');
|
|
|
4
4
|
const { expect } = require('chai');
|
|
5
5
|
|
|
6
6
|
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
7
|
-
process.env.PROPERTIES_PATH = path.join(__dirname, '..', 'config');
|
|
7
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', '..', 'config');
|
|
8
8
|
|
|
9
9
|
const { conf } = require('propertiesmanager');
|
|
10
10
|
const keycloakManager = require('keycloak-api-manager');
|
|
11
|
-
const { TEST_REALM } = require('
|
|
11
|
+
const { TEST_REALM } = require('../../testConfig');
|
|
12
12
|
|
|
13
13
|
describe('Protocol Mappers - Debug Client Library', function () {
|
|
14
14
|
this.timeout(10000);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
|
|
4
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
5
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', 'config');
|
|
6
|
+
|
|
7
|
+
const { conf } = require('propertiesmanager');
|
|
8
|
+
const KeycloakManager = require('../../index');
|
|
9
|
+
const { TEST_REALM, generateUniqueName } = require('../testConfig');
|
|
10
|
+
|
|
11
|
+
const config = {
|
|
12
|
+
baseUrl: conf.keycloak.baseUrl,
|
|
13
|
+
realmName: conf.keycloak.realmName,
|
|
14
|
+
clientId: conf.keycloak.clientId,
|
|
15
|
+
clientSecret: conf.keycloak.clientSecret,
|
|
16
|
+
grantType: conf.keycloak.grantType,
|
|
17
|
+
username: conf.keycloak.username,
|
|
18
|
+
password: conf.keycloak.password,
|
|
19
|
+
tokenLifeSpan: conf.keycloak.tokenLifeSpan
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Integration tests for Group Permissions
|
|
24
|
+
* Tests new permission management methods added to groupsHandler
|
|
25
|
+
*/
|
|
26
|
+
describe('Group Permissions Tests', function () {
|
|
27
|
+
this.timeout(10000);
|
|
28
|
+
|
|
29
|
+
const testGroupData = {
|
|
30
|
+
name: `test-permissions-group-${Date.now()}`
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
let createdGroupId;
|
|
34
|
+
|
|
35
|
+
before(async function () {
|
|
36
|
+
await KeycloakManager.configure(config);
|
|
37
|
+
|
|
38
|
+
// Create a test group
|
|
39
|
+
const result = await KeycloakManager.groups.create(testGroupData);
|
|
40
|
+
createdGroupId = result.id;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
after(async function () {
|
|
44
|
+
// Clean up test group
|
|
45
|
+
if (createdGroupId) {
|
|
46
|
+
await KeycloakManager.groups.del({ id: createdGroupId });
|
|
47
|
+
}
|
|
48
|
+
KeycloakManager.stop();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('Group Permission Management', function () {
|
|
52
|
+
it('should enable permissions for a group', async function () {
|
|
53
|
+
await KeycloakManager.groups.setPermissions(
|
|
54
|
+
{ id: createdGroupId },
|
|
55
|
+
{ enabled: true }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
expect(true).to.be.true;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should get group permissions', async function () {
|
|
62
|
+
const permissions = await KeycloakManager.groups.listPermissions({
|
|
63
|
+
id: createdGroupId
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
expect(permissions).to.exist;
|
|
67
|
+
expect(permissions).to.have.property('enabled');
|
|
68
|
+
expect(permissions.enabled).to.be.true;
|
|
69
|
+
|
|
70
|
+
// Should have resource information when enabled
|
|
71
|
+
expect(permissions).to.have.property('resource');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should disable permissions for a group', async function () {
|
|
75
|
+
await KeycloakManager.groups.setPermissions(
|
|
76
|
+
{ id: createdGroupId },
|
|
77
|
+
{ enabled: false }
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const permissions = await KeycloakManager.groups.listPermissions({
|
|
81
|
+
id: createdGroupId
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
expect(permissions.enabled).to.be.false;
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
|
|
4
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
5
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', '..', 'config');
|
|
6
|
+
|
|
7
|
+
const keycloakManager = require('keycloak-api-manager');
|
|
8
|
+
const { KEYCLOAK_CONFIG, TEST_REALM, TEST_CLIENT_ID, TEST_USER_USERNAME, TEST_USER_PASSWORD } = require('../../testConfig');
|
|
9
|
+
const { loadMatrix } = require('../../helpers/matrix');
|
|
10
|
+
|
|
11
|
+
function buildConfig(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
...KEYCLOAK_CONFIG,
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('Matrix - Authentication', function () {
|
|
19
|
+
this.timeout(30000);
|
|
20
|
+
|
|
21
|
+
const matrix = loadMatrix('auth');
|
|
22
|
+
|
|
23
|
+
let clientSecret = null;
|
|
24
|
+
|
|
25
|
+
before(async function () {
|
|
26
|
+
// Ensure we're using the test realm
|
|
27
|
+
keycloakManager.setConfig({ realmName: TEST_REALM });
|
|
28
|
+
|
|
29
|
+
const clients = await keycloakManager.clients.find({ clientId: TEST_CLIENT_ID });
|
|
30
|
+
const testClient = clients.find((client) => client.clientId === TEST_CLIENT_ID);
|
|
31
|
+
if (!testClient) {
|
|
32
|
+
this.skip();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const secret = await keycloakManager.clients.getClientSecret({ id: testClient.id });
|
|
37
|
+
clientSecret = secret?.value || null;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
after(async function () {
|
|
41
|
+
await keycloakManager.configure(
|
|
42
|
+
buildConfig({
|
|
43
|
+
grantType: KEYCLOAK_CONFIG.grantType || 'password',
|
|
44
|
+
tokenLifeSpan: KEYCLOAK_CONFIG.tokenLifeSpan || 60,
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
matrix.cases.forEach((testCase) => {
|
|
50
|
+
it(`auth case: ${testCase.name}`, async function () {
|
|
51
|
+
if (testCase.grantType === 'client_credentials' && !clientSecret) {
|
|
52
|
+
this.skip();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (testCase.grantType === 'refresh_token') {
|
|
57
|
+
// First obtain a refresh token using password grant
|
|
58
|
+
await keycloakManager.configure(
|
|
59
|
+
buildConfig({
|
|
60
|
+
realmName: TEST_REALM,
|
|
61
|
+
username: TEST_USER_USERNAME,
|
|
62
|
+
password: TEST_USER_PASSWORD,
|
|
63
|
+
grantType: 'password',
|
|
64
|
+
tokenLifeSpan: 60,
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
const token = keycloakManager.getToken();
|
|
68
|
+
if (!token?.refreshToken) {
|
|
69
|
+
this.skip();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await keycloakManager.configure(
|
|
74
|
+
buildConfig({
|
|
75
|
+
realmName: TEST_REALM,
|
|
76
|
+
grantType: 'refresh_token',
|
|
77
|
+
refreshToken: token.refreshToken,
|
|
78
|
+
tokenLifeSpan: 60,
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
} else if (testCase.grantType === 'client_credentials') {
|
|
82
|
+
await keycloakManager.configure(
|
|
83
|
+
buildConfig({
|
|
84
|
+
realmName: TEST_REALM,
|
|
85
|
+
clientId: TEST_CLIENT_ID,
|
|
86
|
+
clientSecret,
|
|
87
|
+
grantType: 'client_credentials',
|
|
88
|
+
tokenLifeSpan: 60,
|
|
89
|
+
username: undefined,
|
|
90
|
+
password: undefined,
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
} else {
|
|
94
|
+
await keycloakManager.configure(
|
|
95
|
+
buildConfig({
|
|
96
|
+
realmName: TEST_REALM,
|
|
97
|
+
username: TEST_USER_USERNAME,
|
|
98
|
+
password: TEST_USER_PASSWORD,
|
|
99
|
+
grantType: testCase.grantType,
|
|
100
|
+
offlineToken: testCase.offlineToken || false,
|
|
101
|
+
scope: testCase.scope,
|
|
102
|
+
tokenLifeSpan: 60,
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const token = keycloakManager.getToken();
|
|
108
|
+
expect(token).to.have.property('accessToken');
|
|
109
|
+
expect(token.accessToken).to.be.a('string').and.to.have.length.greaterThan(0);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { expect } = require('chai');
|
|
3
|
+
|
|
4
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
5
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, '..', '..', 'config');
|
|
6
|
+
|
|
7
|
+
const keycloakManager = require('keycloak-api-manager');
|
|
8
|
+
const { TEST_REALM } = require('../../testConfig');
|
|
9
|
+
const { loadMatrix, uniqueName } = require('../../helpers/matrix');
|
|
10
|
+
|
|
11
|
+
describe('Matrix - Clients', function () {
|
|
12
|
+
this.timeout(30000);
|
|
13
|
+
|
|
14
|
+
const matrix = loadMatrix('clients');
|
|
15
|
+
|
|
16
|
+
before(function () {
|
|
17
|
+
keycloakManager.setConfig({ realmName: TEST_REALM });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
matrix.cases.forEach((testCase) => {
|
|
21
|
+
it(`client case: ${testCase.name}`, async function () {
|
|
22
|
+
const clientId = uniqueName(`matrix-client-${testCase.name}`);
|
|
23
|
+
|
|
24
|
+
const created = await keycloakManager.clients.create({
|
|
25
|
+
clientId,
|
|
26
|
+
enabled: true,
|
|
27
|
+
protocol: 'openid-connect',
|
|
28
|
+
publicClient: testCase.publicClient,
|
|
29
|
+
serviceAccountsEnabled: testCase.serviceAccountsEnabled,
|
|
30
|
+
directAccessGrantsEnabled: testCase.directAccessGrantsEnabled,
|
|
31
|
+
standardFlowEnabled: testCase.standardFlowEnabled,
|
|
32
|
+
consentRequired: testCase.consentRequired,
|
|
33
|
+
redirectUris: ['http://localhost:*'],
|
|
34
|
+
webOrigins: ['*'],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(created).to.exist;
|
|
38
|
+
|
|
39
|
+
const found = await keycloakManager.clients.find({ clientId });
|
|
40
|
+
expect(found).to.be.an('array');
|
|
41
|
+
const stored = found.find((item) => item.clientId === clientId);
|
|
42
|
+
expect(stored).to.exist;
|
|
43
|
+
|
|
44
|
+
await keycloakManager.clients.update(
|
|
45
|
+
{ id: stored.id },
|
|
46
|
+
{
|
|
47
|
+
description: `updated-${clientId}`,
|
|
48
|
+
consentRequired: false,
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const updated = await keycloakManager.clients.findOne({ id: stored.id });
|
|
53
|
+
expect(updated).to.exist;
|
|
54
|
+
expect(updated.description).to.equal(`updated-${clientId}`);
|
|
55
|
+
|
|
56
|
+
await keycloakManager.clients.del({ id: stored.id });
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|