@auth0/auth0-checkmate 1.4.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/.github/CODEOWNERS +1 -0
- package/.github/workflows/npm-release.yml +77 -0
- package/.github/workflows/sca_scan.yml +10 -0
- package/.github/workflows/test.yml +48 -0
- package/AUTHORS +5 -0
- package/LICENSE +203 -0
- package/README.md +166 -0
- package/THIRD-PARTY-NOTICES +226 -0
- package/analyzer/lib/actions/checkActionsHardCodedValues.js +151 -0
- package/analyzer/lib/actions/checkActionsRuntime.js +105 -0
- package/analyzer/lib/actions/checkDependencies.js +111 -0
- package/analyzer/lib/attack_protection/checkBotDetectionSetting.js +76 -0
- package/analyzer/lib/attack_protection/checkBreachedPassword.js +140 -0
- package/analyzer/lib/attack_protection/checkBruteForce.js +89 -0
- package/analyzer/lib/attack_protection/checkSuspiciousIPThrottling.js +89 -0
- package/analyzer/lib/canonical_domain/checkCanonicalDomain.js +63 -0
- package/analyzer/lib/clients/checkAllowedCallbacks.js +122 -0
- package/analyzer/lib/clients/checkAllowedLogoutUrl.js +124 -0
- package/analyzer/lib/clients/checkApplicationLoginUri.js +125 -0
- package/analyzer/lib/clients/checkCrossOriginAuthentication.js +91 -0
- package/analyzer/lib/clients/checkGrantTypes.js +138 -0
- package/analyzer/lib/clients/checkJWTSignAlg.js +118 -0
- package/analyzer/lib/clients/checkRefreshToken.js +108 -0
- package/analyzer/lib/clients/checkWebOrigins.js +55 -0
- package/analyzer/lib/constants.js +63 -0
- package/analyzer/lib/custom_domain/checkCustomDomain.js +53 -0
- package/analyzer/lib/databases/checkAuthenticationMethods.js +98 -0
- package/analyzer/lib/databases/checkDASHardCodedValues.js +163 -0
- package/analyzer/lib/databases/checkEmailAttributeVerification.js +114 -0
- package/analyzer/lib/databases/checkEnabledDatabaseCustomization.js +83 -0
- package/analyzer/lib/databases/checkPasswordComplexity.js +100 -0
- package/analyzer/lib/databases/checkPasswordHistory.js +92 -0
- package/analyzer/lib/databases/checkPasswordNoPersonalInfo.js +91 -0
- package/analyzer/lib/databases/checkPasswordPolicy.js +95 -0
- package/analyzer/lib/databases/checkPromotedDBConnection.js +96 -0
- package/analyzer/lib/email_provider/checkEmailProvider.js +37 -0
- package/analyzer/lib/email_templates/checkEmailTemplates.js +71 -0
- package/analyzer/lib/error_page_template/checkErrorPageTemplate.js +153 -0
- package/analyzer/lib/event_streams/checkEventStreams.js +71 -0
- package/analyzer/lib/executeCheck.js +12 -0
- package/analyzer/lib/hooks/checkHooks.js +43 -0
- package/analyzer/lib/listOfAnalyser.js +24 -0
- package/analyzer/lib/log_streams/checkLogStream.js +60 -0
- package/analyzer/lib/logger.js +16 -0
- package/analyzer/lib/multifactor/checkGuardianFactors.js +72 -0
- package/analyzer/lib/multifactor/checkGuardianPolicy.js +40 -0
- package/analyzer/lib/network_acl/checkNetworkACL.js +35 -0
- package/analyzer/lib/rules/checkRules.js +102 -0
- package/analyzer/lib/tenant_settings/checkDefaultAudience.js +53 -0
- package/analyzer/lib/tenant_settings/checkDefaultDirectory.js +48 -0
- package/analyzer/lib/tenant_settings/checkEnabledDynamicClientRegistration.js +60 -0
- package/analyzer/lib/tenant_settings/checkSandboxVersion.js +37 -0
- package/analyzer/lib/tenant_settings/checkSessionLifetime.js +95 -0
- package/analyzer/lib/tenant_settings/checkSupportEmail.js +61 -0
- package/analyzer/lib/tenant_settings/checkSupportUrl.js +61 -0
- package/analyzer/lib/tenant_settings/checkTenantLoginUrl.js +71 -0
- package/analyzer/lib/tenant_settings/checkTenantLogoutUrl.js +60 -0
- package/analyzer/report.js +404 -0
- package/analyzer/tools/auth0.js +443 -0
- package/analyzer/tools/helpers.js +71 -0
- package/analyzer/tools/summary.js +84 -0
- package/analyzer/tools/utils.js +72 -0
- package/bin/index.js +393 -0
- package/eslint.config.mjs +16 -0
- package/images/auth0.png +0 -0
- package/images/okta.png +0 -0
- package/locales/en.json +1417 -0
- package/package.json +66 -0
- package/tests/actions/checkActionsHardCodedValues.test.js +106 -0
- package/tests/actions/checkActionsRuntime.test.js +102 -0
- package/tests/actions/checkDependencies.test.js +131 -0
- package/tests/attack_protection/checkBreachedPassword.test.js +253 -0
- package/tests/attack_protection/checkBruteForce.test.js +181 -0
- package/tests/attack_protection/checkSuspiciousIPThrottling.test.js +222 -0
- package/tests/canonical_domain/checkCanonicalDomain.test.js +94 -0
- package/tests/clients/checkAllowedCallbacks.test.js +149 -0
- package/tests/clients/checkAllowedLogoutUrl.test.js +149 -0
- package/tests/clients/checkApplicationLoginUri.test.js +180 -0
- package/tests/clients/checkCrossOriginAuthentication.test.js +99 -0
- package/tests/clients/checkGrantTypes.test.js +154 -0
- package/tests/clients/checkJWTSignAlg.test.js +121 -0
- package/tests/clients/checkRefreshToken.test.js +63 -0
- package/tests/clients/checkWebOrigins.test.js +140 -0
- package/tests/custom_domain/checkCustomDomain.test.js +73 -0
- package/tests/databases/checkAuthenticationMethods.test.js +124 -0
- package/tests/databases/checkDASHardCodedValues.test.js +77 -0
- package/tests/databases/checkEmailAttributeVerification.test.js +79 -0
- package/tests/databases/checkEnabledDatabaseCustomization.test.js +68 -0
- package/tests/databases/checkPasswordComplexity.test.js +127 -0
- package/tests/databases/checkPasswordHistory.test.js +100 -0
- package/tests/databases/checkPasswordNoPersonalInfo.test.js +94 -0
- package/tests/databases/checkPasswordPolicy.test.js +161 -0
- package/tests/databases/checkPromotedDBConnection.test.js +62 -0
- package/tests/email_provider/checkEmailProvider.test.js +58 -0
- package/tests/email_templates/checkEmailTemplates.test.js +120 -0
- package/tests/error_page_template/checkErrorPageTemplate.test.js +315 -0
- package/tests/event_streams/checkEventStreams.test.js +118 -0
- package/tests/hooks/checkHooks.test.js +112 -0
- package/tests/log_streams/checkLogStream.test.js +140 -0
- package/tests/multifactor/checkGuardianFactors.test.js +94 -0
- package/tests/multifactor/checkGuardianPolicy.test.js +49 -0
- package/tests/rules/checkRules.test.js +102 -0
- package/tests/tenant_settings/checkDefaultAudience.test.js +62 -0
- package/tests/tenant_settings/checkDefaultDirectory.test.js +62 -0
- package/tests/tenant_settings/checkEnabledDynamicClientRegistration.test.js +97 -0
- package/tests/tenant_settings/checkSandboxVersion.test.js +50 -0
- package/tests/tenant_settings/checkSessionLifetime.test.js +108 -0
- package/tests/tenant_settings/checkSupportEmail.test.js +77 -0
- package/tests/tenant_settings/checkSupportUrl.test.js +77 -0
- package/tests/tenant_settings/checkTenantLoginUri.test.js +82 -0
- package/tests/tenant_settings/checkTenantLogoutUrl.test.js +108 -0
- package/tests/tools/auth0.test.js +833 -0
- package/tests/tools/helpers.test.js +692 -0
- package/views/pdf_cli_report.handlebars +571 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const chai = require("chai");
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
|
|
4
|
+
const checkAllowedLogoutUrl = require("../../analyzer/lib/clients/checkAllowedLogoutUrl");
|
|
5
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
6
|
+
|
|
7
|
+
describe("checkAllowedLogoutUrl", function () {
|
|
8
|
+
it("should return an empty report when there are no clients", function () {
|
|
9
|
+
const options = {
|
|
10
|
+
clients: [], // No clients
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
checkAllowedLogoutUrl(options, (reports) => {
|
|
14
|
+
expect(reports).to.deep.equal([]); // No reports expected
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should return a fail report when client has no allowed logout URLs and app_type is not non_interactive", function () {
|
|
19
|
+
const options = {
|
|
20
|
+
clients: [
|
|
21
|
+
{
|
|
22
|
+
name: "Test App",
|
|
23
|
+
client_id: "client_id",
|
|
24
|
+
app_type: "spa", // Not non_interactive
|
|
25
|
+
allowed_logout_urls: [], // No allowed logout URLs
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
checkAllowedLogoutUrl(options, (reports) => {
|
|
31
|
+
expect(reports).to.deep.equal([
|
|
32
|
+
{
|
|
33
|
+
name: "Test App",
|
|
34
|
+
report: [
|
|
35
|
+
{
|
|
36
|
+
name: "Test App",
|
|
37
|
+
client_id: "client_id",
|
|
38
|
+
field: "missing_allowed_logout_urls",
|
|
39
|
+
url: "missing_allowed_logout_urls",
|
|
40
|
+
status: CONSTANTS.FAIL,
|
|
41
|
+
app_type: "spa",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should return a fail report when client has insecure allowed logout URLs (http://localhost)", function () {
|
|
50
|
+
const options = {
|
|
51
|
+
clients: [
|
|
52
|
+
{
|
|
53
|
+
name: "Test App",
|
|
54
|
+
client_id: "client_id",
|
|
55
|
+
allowed_logout_urls: ["http://localhost:3000"], // Insecure logout URL
|
|
56
|
+
app_type: "spa",
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
checkAllowedLogoutUrl(options, (reports) => {
|
|
62
|
+
expect(reports).to.deep.equal([
|
|
63
|
+
{
|
|
64
|
+
name: "Test App",
|
|
65
|
+
report: [
|
|
66
|
+
{
|
|
67
|
+
name: "Test App",
|
|
68
|
+
client_id: "client_id",
|
|
69
|
+
field: "insecure_allowed_logout_urls",
|
|
70
|
+
url: "http://localhost:3000",
|
|
71
|
+
status: CONSTANTS.FAIL,
|
|
72
|
+
app_type: "spa",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should return a success report when client has secure allowed logout URLs (https://contoso.com)", function () {
|
|
81
|
+
const options = {
|
|
82
|
+
clients: [
|
|
83
|
+
{
|
|
84
|
+
name: "Test App",
|
|
85
|
+
client_id: "client_id",
|
|
86
|
+
allowed_logout_urls: ["https://contoso.com"], // Secure logout URL
|
|
87
|
+
app_type: "spa",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
checkAllowedLogoutUrl(options, (reports) => {
|
|
93
|
+
expect(reports).to.deep.equal([
|
|
94
|
+
{
|
|
95
|
+
name: "Test App",
|
|
96
|
+
report: [
|
|
97
|
+
{
|
|
98
|
+
name: "Test App",
|
|
99
|
+
client_id: "client_id",
|
|
100
|
+
field: "secure_allowed_logout_urls",
|
|
101
|
+
status: CONSTANTS.SUCCESS,
|
|
102
|
+
url: "https://contoso.com",
|
|
103
|
+
app_type: "spa",
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should return both fail and success reports when client has both insecure and secure allowed logout URLs", function () {
|
|
112
|
+
const options = {
|
|
113
|
+
clients: [
|
|
114
|
+
{
|
|
115
|
+
name: "Test App",
|
|
116
|
+
client_id: "client_id",
|
|
117
|
+
allowed_logout_urls: ["http://localhost:3000", "https://contoso.com"], // Mix of insecure and secure URLs
|
|
118
|
+
app_type: "spa",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
checkAllowedLogoutUrl(options, (reports) => {
|
|
124
|
+
expect(reports).to.deep.equal([
|
|
125
|
+
{
|
|
126
|
+
name: "Test App",
|
|
127
|
+
report: [
|
|
128
|
+
{
|
|
129
|
+
name: "Test App",
|
|
130
|
+
client_id: "client_id",
|
|
131
|
+
field: "insecure_allowed_logout_urls",
|
|
132
|
+
url: "http://localhost:3000",
|
|
133
|
+
status: CONSTANTS.FAIL,
|
|
134
|
+
app_type: "spa",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "Test App",
|
|
138
|
+
client_id: "client_id",
|
|
139
|
+
field: "secure_allowed_logout_urls",
|
|
140
|
+
status: CONSTANTS.SUCCESS,
|
|
141
|
+
url: "https://contoso.com",
|
|
142
|
+
app_type: "spa",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const chai = require("chai");
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
|
|
4
|
+
const checkApplicationLoginUri = require("../../analyzer/lib/clients/checkApplicationLoginUri");
|
|
5
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
6
|
+
|
|
7
|
+
describe("checkApplicationLoginUri", function () {
|
|
8
|
+
it("should return an empty report when there are no clients", function () {
|
|
9
|
+
const options = {
|
|
10
|
+
clients: [], // No clients
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
checkApplicationLoginUri(options, (reports) => {
|
|
14
|
+
expect(reports).to.deep.equal([]); // No reports expected
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should return a fail report when client has missing initiate_login_uri for spa app type", function () {
|
|
19
|
+
const options = {
|
|
20
|
+
clients: [
|
|
21
|
+
{
|
|
22
|
+
name: "Test App",
|
|
23
|
+
client_id: "client_id",
|
|
24
|
+
app_type: "spa", // spa app type
|
|
25
|
+
initiate_login_uri: "", // Missing initiate_login_uri
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
checkApplicationLoginUri(options, (reports) => {
|
|
31
|
+
expect(reports).to.deep.equal([
|
|
32
|
+
{
|
|
33
|
+
name: "Test App",
|
|
34
|
+
report: [
|
|
35
|
+
{
|
|
36
|
+
name: "Test App",
|
|
37
|
+
client_id: "client_id",
|
|
38
|
+
field: "missing_initiate_login_uri",
|
|
39
|
+
url: "missing_initiate_login_uri",
|
|
40
|
+
status: CONSTANTS.FAIL,
|
|
41
|
+
app_type: "spa",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should return a fail report when client has insecure initiate_login_uri containing localhost", function () {
|
|
50
|
+
const options = {
|
|
51
|
+
clients: [
|
|
52
|
+
{
|
|
53
|
+
name: "Test App",
|
|
54
|
+
client_id: "client_id",
|
|
55
|
+
app_type: "spa", // spa app type
|
|
56
|
+
initiate_login_uri: "http://localhost:3000", // Insecure URI (localhost)
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
checkApplicationLoginUri(options, (reports) => {
|
|
62
|
+
expect(reports).to.deep.equal([
|
|
63
|
+
{
|
|
64
|
+
name: "Test App",
|
|
65
|
+
report: [
|
|
66
|
+
{
|
|
67
|
+
name: "Test App",
|
|
68
|
+
client_id: "client_id",
|
|
69
|
+
field: "insecure_initiate_login_uri",
|
|
70
|
+
url: "http://localhost:3000",
|
|
71
|
+
status: CONSTANTS.FAIL,
|
|
72
|
+
app_type: "spa",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should return a fail report when client has insecure initiate_login_uri containing http://", function () {
|
|
81
|
+
const options = {
|
|
82
|
+
clients: [
|
|
83
|
+
{
|
|
84
|
+
name: "Test App",
|
|
85
|
+
client_id: "client_id",
|
|
86
|
+
app_type: "spa", // spa app type
|
|
87
|
+
initiate_login_uri: "http://example.com", // Insecure URI (http://)
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
checkApplicationLoginUri(options, (reports) => {
|
|
93
|
+
expect(reports).to.deep.equal([
|
|
94
|
+
{
|
|
95
|
+
name: "Test App",
|
|
96
|
+
report: [
|
|
97
|
+
{
|
|
98
|
+
name: "Test App",
|
|
99
|
+
client_id: "client_id",
|
|
100
|
+
field: "insecure_initiate_login_uri",
|
|
101
|
+
url: "http://example.com",
|
|
102
|
+
status: CONSTANTS.FAIL,
|
|
103
|
+
app_type: "spa",
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should return a success report when client has a secure initiate_login_uri", function () {
|
|
112
|
+
const options = {
|
|
113
|
+
clients: [
|
|
114
|
+
{
|
|
115
|
+
name: "Test App",
|
|
116
|
+
client_id: "client_id",
|
|
117
|
+
app_type: "spa", // spa app type
|
|
118
|
+
initiate_login_uri: "https://secure-example.com", // Secure URI
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
checkApplicationLoginUri(options, (reports) => {
|
|
124
|
+
expect(reports).to.deep.equal([
|
|
125
|
+
{
|
|
126
|
+
name: "Test App",
|
|
127
|
+
report: [
|
|
128
|
+
{
|
|
129
|
+
name: "Test App",
|
|
130
|
+
client_id: "client_id",
|
|
131
|
+
field: "secure_initiate_login_uri",
|
|
132
|
+
status: CONSTANTS.SUCCESS,
|
|
133
|
+
url: "https://secure-example.com",
|
|
134
|
+
app_type: "spa",
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
]);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should return both missing and insecure initiate_login_uri reports for a client with both issues", function () {
|
|
143
|
+
const options = {
|
|
144
|
+
clients: [
|
|
145
|
+
{
|
|
146
|
+
name: "Test App",
|
|
147
|
+
client_id: "client_id",
|
|
148
|
+
app_type: "spa", // spa app type
|
|
149
|
+
initiate_login_uri: "http://localhost:3000", // Insecure URI and missing URI issue
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
checkApplicationLoginUri(options, (reports) => {
|
|
155
|
+
expect(reports).to.deep.equal([
|
|
156
|
+
{
|
|
157
|
+
name: "Test App",
|
|
158
|
+
report: [
|
|
159
|
+
{
|
|
160
|
+
name: "Test App",
|
|
161
|
+
client_id: "client_id",
|
|
162
|
+
field: "missing_initiate_login_uri",
|
|
163
|
+
url: "missing_initiate_login_uri",
|
|
164
|
+
status: CONSTANTS.FAIL,
|
|
165
|
+
app_type: "spa",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "Test App",
|
|
169
|
+
client_id: "client_id",
|
|
170
|
+
field: "insecure_initiate_login_uri",
|
|
171
|
+
url: "http://localhost:3000",
|
|
172
|
+
status: CONSTANTS.FAIL,
|
|
173
|
+
app_type: "spa",
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
]);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const chai = require('chai');
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
const checkCrossOriginAuthentication = require('../../analyzer/lib/clients/checkCrossOriginAuthentication');
|
|
4
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
5
|
+
|
|
6
|
+
describe('checkCrossOriginAuthentication', function() {
|
|
7
|
+
|
|
8
|
+
it('should return an empty report when clients array is empty', function() {
|
|
9
|
+
const options = {
|
|
10
|
+
clients: []
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
checkCrossOriginAuthentication(options, (report) => {
|
|
14
|
+
expect(report).to.be.an('array').that.is.empty;
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return a report when cross_origin_authentication is enabled', function() {
|
|
19
|
+
const options = {
|
|
20
|
+
clients: [
|
|
21
|
+
{
|
|
22
|
+
client_id: 'client_id_1',
|
|
23
|
+
name: 'Client 1',
|
|
24
|
+
cross_origin_authentication: true,
|
|
25
|
+
app_type: 'spa',
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
checkCrossOriginAuthentication(options, (report) => {
|
|
31
|
+
expect(report).to.have.lengthOf(1);
|
|
32
|
+
expect(report[0]).to.include({
|
|
33
|
+
client_id: 'client_id_1',
|
|
34
|
+
field: 'cross_origin_authentication_enabled',
|
|
35
|
+
status: CONSTANTS.FAIL,
|
|
36
|
+
app_type: 'spa'
|
|
37
|
+
});
|
|
38
|
+
expect(report[0].name).to.equal('Client 1 (client_id_1)');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should not return a report when cross_origin_authentication is disabled', function() {
|
|
43
|
+
const options = {
|
|
44
|
+
clients: [
|
|
45
|
+
{
|
|
46
|
+
client_id: 'client_id_2',
|
|
47
|
+
name: 'Client 2',
|
|
48
|
+
cross_origin_authentication: false,
|
|
49
|
+
app_type: 'spa',
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
checkCrossOriginAuthentication(options, (report) => {
|
|
55
|
+
expect(report).to.be.an('array').that.is.empty;
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should handle cases where client_id is missing', function() {
|
|
60
|
+
const options = {
|
|
61
|
+
clients: [
|
|
62
|
+
{
|
|
63
|
+
name: 'Client 3',
|
|
64
|
+
cross_origin_authentication: true,
|
|
65
|
+
app_type: 'spa',
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
checkCrossOriginAuthentication(options, (report) => {
|
|
71
|
+
expect(report).to.have.lengthOf(1);
|
|
72
|
+
expect(report[0]).to.include({
|
|
73
|
+
client_id: 'Client 3',
|
|
74
|
+
field: 'cross_origin_authentication_enabled',
|
|
75
|
+
status: CONSTANTS.FAIL,
|
|
76
|
+
app_type: 'spa'
|
|
77
|
+
});
|
|
78
|
+
expect(report[0].name).to.equal('Client 3');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should return an empty report if cross_origin_authentication is false and other properties exist', function() {
|
|
83
|
+
const options = {
|
|
84
|
+
clients: [
|
|
85
|
+
{
|
|
86
|
+
client_id: 'client_id_4',
|
|
87
|
+
name: 'Client 4',
|
|
88
|
+
cross_origin_authentication: false,
|
|
89
|
+
app_type: 'spa',
|
|
90
|
+
callbacks: ['http://localhost:3000'],
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
checkCrossOriginAuthentication(options, (report) => {
|
|
96
|
+
expect(report).to.be.an('array').that.is.empty;
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const chai = require("chai");
|
|
2
|
+
const expect = chai.expect;
|
|
3
|
+
|
|
4
|
+
const checkGrantTypes = require("../../analyzer/lib/clients/checkGrantTypes");
|
|
5
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
6
|
+
|
|
7
|
+
describe("checkGrantTypes", function () {
|
|
8
|
+
it("should return an empty report when there are no clients", function () {
|
|
9
|
+
const options = {
|
|
10
|
+
clients: [], // No clients
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
checkGrantTypes(options, (reports) => {
|
|
14
|
+
expect(reports).to.deep.equal([]); // No reports expected
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should return a fail report when client has missing grant types for spa app type", function () {
|
|
19
|
+
const options = {
|
|
20
|
+
clients: [
|
|
21
|
+
{
|
|
22
|
+
name: "Test App",
|
|
23
|
+
client_id: "client_id",
|
|
24
|
+
app_type: "spa", // spa app type
|
|
25
|
+
grant_types: ["authorization_code"], // Missing refresh_token
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
checkGrantTypes(options, (reports) => {
|
|
31
|
+
expect(reports).to.deep.equal([
|
|
32
|
+
{
|
|
33
|
+
name: "Test App",
|
|
34
|
+
report: [
|
|
35
|
+
{
|
|
36
|
+
name: "Test App",
|
|
37
|
+
client_id: "client_id",
|
|
38
|
+
field: "missing_grant_type_for_app_type",
|
|
39
|
+
grant_type: "refresh_token",
|
|
40
|
+
status: CONSTANTS.FAIL,
|
|
41
|
+
app_type: "spa",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should return a fail report when client has unexpected grant types for spa app type", function () {
|
|
50
|
+
const options = {
|
|
51
|
+
clients: [
|
|
52
|
+
{
|
|
53
|
+
name: "Test App",
|
|
54
|
+
client_id: "client_id",
|
|
55
|
+
app_type: "spa", // spa app type
|
|
56
|
+
grant_types: [
|
|
57
|
+
"authorization_code",
|
|
58
|
+
"implicit",
|
|
59
|
+
"refresh_token",
|
|
60
|
+
"client_credentials",
|
|
61
|
+
], // Unexpected client_credentials
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
checkGrantTypes(options, (reports) => {
|
|
67
|
+
expect(reports).to.deep.equal([
|
|
68
|
+
{
|
|
69
|
+
name: "Test App",
|
|
70
|
+
report: [
|
|
71
|
+
{
|
|
72
|
+
name: "Test App",
|
|
73
|
+
client_id: "client_id",
|
|
74
|
+
field: "unexpected_grant_type_for_app_type",
|
|
75
|
+
grant_type: "client_credentials",
|
|
76
|
+
status: CONSTANTS.FAIL,
|
|
77
|
+
app_type: "spa",
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should return a success report when client has the correct grant types for spa app type", function () {
|
|
86
|
+
const options = {
|
|
87
|
+
clients: [
|
|
88
|
+
{
|
|
89
|
+
name: "Test App",
|
|
90
|
+
client_id: "client_id",
|
|
91
|
+
app_type: "spa", // spa app type
|
|
92
|
+
grant_types: ["authorization_code", "refresh_token"], // Correct grant types for spa
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
checkGrantTypes(options, (reports) => {
|
|
98
|
+
expect(reports).to.deep.equal([
|
|
99
|
+
{
|
|
100
|
+
name: "Test App",
|
|
101
|
+
report: [
|
|
102
|
+
{
|
|
103
|
+
name: "Test App",
|
|
104
|
+
client_id: "client_id",
|
|
105
|
+
field: "grant_types_passed",
|
|
106
|
+
status: CONSTANTS.SUCCESS,
|
|
107
|
+
grant_type: "authorization_code, refresh_token",
|
|
108
|
+
app_type: "spa",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
]);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("should return both missing and unexpected grant type reports for a client with both issues", function () {
|
|
117
|
+
const options = {
|
|
118
|
+
clients: [
|
|
119
|
+
{
|
|
120
|
+
name: "Test App",
|
|
121
|
+
client_id: "client_id",
|
|
122
|
+
app_type: "spa", // spa app type
|
|
123
|
+
grant_types: ["authorization_code", "client_credentials"], // Missing refresh_token and unexpected client_credentials
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
checkGrantTypes(options, (reports) => {
|
|
129
|
+
expect(reports).to.deep.equal([
|
|
130
|
+
{
|
|
131
|
+
name: "Test App",
|
|
132
|
+
report: [
|
|
133
|
+
{
|
|
134
|
+
name: "Test App",
|
|
135
|
+
client_id: "client_id",
|
|
136
|
+
field: "missing_grant_type_for_app_type",
|
|
137
|
+
grant_type: "refresh_token",
|
|
138
|
+
status: CONSTANTS.FAIL,
|
|
139
|
+
app_type: "spa",
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "Test App",
|
|
143
|
+
client_id: "client_id",
|
|
144
|
+
field: "unexpected_grant_type_for_app_type",
|
|
145
|
+
grant_type: "client_credentials",
|
|
146
|
+
status: CONSTANTS.FAIL,
|
|
147
|
+
app_type: "spa",
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
]);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const { expect } = require("chai");
|
|
2
|
+
const checkJWTSignAlg = require("../../analyzer/lib/clients/checkJWTSignAlg");
|
|
3
|
+
const CONSTANTS = require("../../analyzer/lib/constants");
|
|
4
|
+
|
|
5
|
+
describe("checkJWTSignAlg", function () {
|
|
6
|
+
it("should return RS256 when no jwt_configuration is provided", function () {
|
|
7
|
+
const options = {
|
|
8
|
+
clients: [
|
|
9
|
+
{
|
|
10
|
+
name: "Default App",
|
|
11
|
+
client_id: "client_id",
|
|
12
|
+
jwt_configuration: undefined, // No jwt_configuration provided, defaults to RS256
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
checkJWTSignAlg(options, (report) => {
|
|
18
|
+
expect(report).to.have.lengthOf(1);
|
|
19
|
+
expect(report[0].field).to.equal("missing_jwt_alg");
|
|
20
|
+
expect(report[0].status).to.equal(CONSTANTS.SUCCESS);
|
|
21
|
+
expect(report[0].alg).to.equal("RS256");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should return success for clients using an asymmetric algorithm (e.g., RS512)", function () {
|
|
26
|
+
const options = {
|
|
27
|
+
clients: [
|
|
28
|
+
{
|
|
29
|
+
name: "Default App",
|
|
30
|
+
client_id: "client_id",
|
|
31
|
+
jwt_configuration: {
|
|
32
|
+
alg: "RS512", // Custom asymmetric algorithm
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
checkJWTSignAlg(options, (report) => {
|
|
39
|
+
expect(report).to.have.lengthOf(1);
|
|
40
|
+
expect(report[0].field).to.equal("using_asymmetric_alg");
|
|
41
|
+
expect(report[0].status).to.equal(CONSTANTS.SUCCESS);
|
|
42
|
+
expect(report[0].alg).to.equal("RS512");
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should return fail for clients using HS256 (symmetric algorithm)", function () {
|
|
47
|
+
const options = {
|
|
48
|
+
clients: [
|
|
49
|
+
{
|
|
50
|
+
name: "Default App",
|
|
51
|
+
client_id: "client_id",
|
|
52
|
+
jwt_configuration: {
|
|
53
|
+
alg: "HS256", // Symmetric algorithm, flagged as an issue
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
checkJWTSignAlg(options, (report) => {
|
|
60
|
+
expect(report).to.have.lengthOf(1);
|
|
61
|
+
expect(report[0].field).to.equal("not_using_asymmetric_alg");
|
|
62
|
+
expect(report[0].status).to.equal(CONSTANTS.FAIL);
|
|
63
|
+
expect(report[0].alg).to.equal("HS256");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should return an empty report when no clients are provided", function () {
|
|
68
|
+
const options = {
|
|
69
|
+
clients: [], // Empty clients list
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
checkJWTSignAlg(options, (report) => {
|
|
73
|
+
expect(report).to.have.lengthOf(0); // No reports should be generated
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should handle multiple clients with different JWT configurations", function () {
|
|
78
|
+
const options = {
|
|
79
|
+
clients: [
|
|
80
|
+
{
|
|
81
|
+
name: "Client 1",
|
|
82
|
+
client_id: "client_1_id",
|
|
83
|
+
jwt_configuration: undefined, // No jwt_configuration provided, defaults to RS256
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "Client 2",
|
|
87
|
+
client_id: "client_2_id",
|
|
88
|
+
jwt_configuration: {
|
|
89
|
+
alg: "RS256",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "Client 3",
|
|
94
|
+
client_id: "client_3_id",
|
|
95
|
+
jwt_configuration: {
|
|
96
|
+
alg: "HS256",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
checkJWTSignAlg(options, (report) => {
|
|
103
|
+
expect(report).to.have.lengthOf(3);
|
|
104
|
+
|
|
105
|
+
// Client 1: Missing JWT configuration, defaults to RS256
|
|
106
|
+
expect(report[0].field).to.equal("missing_jwt_alg");
|
|
107
|
+
expect(report[0].status).to.equal(CONSTANTS.SUCCESS);
|
|
108
|
+
expect(report[0].alg).to.equal("RS256");
|
|
109
|
+
|
|
110
|
+
// Client 2: Uses RS256 (asymmetric)
|
|
111
|
+
expect(report[1].field).to.equal("using_asymmetric_alg");
|
|
112
|
+
expect(report[1].status).to.equal(CONSTANTS.SUCCESS);
|
|
113
|
+
expect(report[1].alg).to.equal("RS256");
|
|
114
|
+
|
|
115
|
+
// Client 3: Uses HS256 (symmetric)
|
|
116
|
+
expect(report[2].field).to.equal("not_using_asymmetric_alg");
|
|
117
|
+
expect(report[2].status).to.equal(CONSTANTS.FAIL);
|
|
118
|
+
expect(report[2].alg).to.equal("HS256");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|