@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.
Files changed (114) hide show
  1. package/.github/CODEOWNERS +1 -0
  2. package/.github/workflows/npm-release.yml +77 -0
  3. package/.github/workflows/sca_scan.yml +10 -0
  4. package/.github/workflows/test.yml +48 -0
  5. package/AUTHORS +5 -0
  6. package/LICENSE +203 -0
  7. package/README.md +166 -0
  8. package/THIRD-PARTY-NOTICES +226 -0
  9. package/analyzer/lib/actions/checkActionsHardCodedValues.js +151 -0
  10. package/analyzer/lib/actions/checkActionsRuntime.js +105 -0
  11. package/analyzer/lib/actions/checkDependencies.js +111 -0
  12. package/analyzer/lib/attack_protection/checkBotDetectionSetting.js +76 -0
  13. package/analyzer/lib/attack_protection/checkBreachedPassword.js +140 -0
  14. package/analyzer/lib/attack_protection/checkBruteForce.js +89 -0
  15. package/analyzer/lib/attack_protection/checkSuspiciousIPThrottling.js +89 -0
  16. package/analyzer/lib/canonical_domain/checkCanonicalDomain.js +63 -0
  17. package/analyzer/lib/clients/checkAllowedCallbacks.js +122 -0
  18. package/analyzer/lib/clients/checkAllowedLogoutUrl.js +124 -0
  19. package/analyzer/lib/clients/checkApplicationLoginUri.js +125 -0
  20. package/analyzer/lib/clients/checkCrossOriginAuthentication.js +91 -0
  21. package/analyzer/lib/clients/checkGrantTypes.js +138 -0
  22. package/analyzer/lib/clients/checkJWTSignAlg.js +118 -0
  23. package/analyzer/lib/clients/checkRefreshToken.js +108 -0
  24. package/analyzer/lib/clients/checkWebOrigins.js +55 -0
  25. package/analyzer/lib/constants.js +63 -0
  26. package/analyzer/lib/custom_domain/checkCustomDomain.js +53 -0
  27. package/analyzer/lib/databases/checkAuthenticationMethods.js +98 -0
  28. package/analyzer/lib/databases/checkDASHardCodedValues.js +163 -0
  29. package/analyzer/lib/databases/checkEmailAttributeVerification.js +114 -0
  30. package/analyzer/lib/databases/checkEnabledDatabaseCustomization.js +83 -0
  31. package/analyzer/lib/databases/checkPasswordComplexity.js +100 -0
  32. package/analyzer/lib/databases/checkPasswordHistory.js +92 -0
  33. package/analyzer/lib/databases/checkPasswordNoPersonalInfo.js +91 -0
  34. package/analyzer/lib/databases/checkPasswordPolicy.js +95 -0
  35. package/analyzer/lib/databases/checkPromotedDBConnection.js +96 -0
  36. package/analyzer/lib/email_provider/checkEmailProvider.js +37 -0
  37. package/analyzer/lib/email_templates/checkEmailTemplates.js +71 -0
  38. package/analyzer/lib/error_page_template/checkErrorPageTemplate.js +153 -0
  39. package/analyzer/lib/event_streams/checkEventStreams.js +71 -0
  40. package/analyzer/lib/executeCheck.js +12 -0
  41. package/analyzer/lib/hooks/checkHooks.js +43 -0
  42. package/analyzer/lib/listOfAnalyser.js +24 -0
  43. package/analyzer/lib/log_streams/checkLogStream.js +60 -0
  44. package/analyzer/lib/logger.js +16 -0
  45. package/analyzer/lib/multifactor/checkGuardianFactors.js +72 -0
  46. package/analyzer/lib/multifactor/checkGuardianPolicy.js +40 -0
  47. package/analyzer/lib/network_acl/checkNetworkACL.js +35 -0
  48. package/analyzer/lib/rules/checkRules.js +102 -0
  49. package/analyzer/lib/tenant_settings/checkDefaultAudience.js +53 -0
  50. package/analyzer/lib/tenant_settings/checkDefaultDirectory.js +48 -0
  51. package/analyzer/lib/tenant_settings/checkEnabledDynamicClientRegistration.js +60 -0
  52. package/analyzer/lib/tenant_settings/checkSandboxVersion.js +37 -0
  53. package/analyzer/lib/tenant_settings/checkSessionLifetime.js +95 -0
  54. package/analyzer/lib/tenant_settings/checkSupportEmail.js +61 -0
  55. package/analyzer/lib/tenant_settings/checkSupportUrl.js +61 -0
  56. package/analyzer/lib/tenant_settings/checkTenantLoginUrl.js +71 -0
  57. package/analyzer/lib/tenant_settings/checkTenantLogoutUrl.js +60 -0
  58. package/analyzer/report.js +404 -0
  59. package/analyzer/tools/auth0.js +443 -0
  60. package/analyzer/tools/helpers.js +71 -0
  61. package/analyzer/tools/summary.js +84 -0
  62. package/analyzer/tools/utils.js +72 -0
  63. package/bin/index.js +393 -0
  64. package/eslint.config.mjs +16 -0
  65. package/images/auth0.png +0 -0
  66. package/images/okta.png +0 -0
  67. package/locales/en.json +1417 -0
  68. package/package.json +66 -0
  69. package/tests/actions/checkActionsHardCodedValues.test.js +106 -0
  70. package/tests/actions/checkActionsRuntime.test.js +102 -0
  71. package/tests/actions/checkDependencies.test.js +131 -0
  72. package/tests/attack_protection/checkBreachedPassword.test.js +253 -0
  73. package/tests/attack_protection/checkBruteForce.test.js +181 -0
  74. package/tests/attack_protection/checkSuspiciousIPThrottling.test.js +222 -0
  75. package/tests/canonical_domain/checkCanonicalDomain.test.js +94 -0
  76. package/tests/clients/checkAllowedCallbacks.test.js +149 -0
  77. package/tests/clients/checkAllowedLogoutUrl.test.js +149 -0
  78. package/tests/clients/checkApplicationLoginUri.test.js +180 -0
  79. package/tests/clients/checkCrossOriginAuthentication.test.js +99 -0
  80. package/tests/clients/checkGrantTypes.test.js +154 -0
  81. package/tests/clients/checkJWTSignAlg.test.js +121 -0
  82. package/tests/clients/checkRefreshToken.test.js +63 -0
  83. package/tests/clients/checkWebOrigins.test.js +140 -0
  84. package/tests/custom_domain/checkCustomDomain.test.js +73 -0
  85. package/tests/databases/checkAuthenticationMethods.test.js +124 -0
  86. package/tests/databases/checkDASHardCodedValues.test.js +77 -0
  87. package/tests/databases/checkEmailAttributeVerification.test.js +79 -0
  88. package/tests/databases/checkEnabledDatabaseCustomization.test.js +68 -0
  89. package/tests/databases/checkPasswordComplexity.test.js +127 -0
  90. package/tests/databases/checkPasswordHistory.test.js +100 -0
  91. package/tests/databases/checkPasswordNoPersonalInfo.test.js +94 -0
  92. package/tests/databases/checkPasswordPolicy.test.js +161 -0
  93. package/tests/databases/checkPromotedDBConnection.test.js +62 -0
  94. package/tests/email_provider/checkEmailProvider.test.js +58 -0
  95. package/tests/email_templates/checkEmailTemplates.test.js +120 -0
  96. package/tests/error_page_template/checkErrorPageTemplate.test.js +315 -0
  97. package/tests/event_streams/checkEventStreams.test.js +118 -0
  98. package/tests/hooks/checkHooks.test.js +112 -0
  99. package/tests/log_streams/checkLogStream.test.js +140 -0
  100. package/tests/multifactor/checkGuardianFactors.test.js +94 -0
  101. package/tests/multifactor/checkGuardianPolicy.test.js +49 -0
  102. package/tests/rules/checkRules.test.js +102 -0
  103. package/tests/tenant_settings/checkDefaultAudience.test.js +62 -0
  104. package/tests/tenant_settings/checkDefaultDirectory.test.js +62 -0
  105. package/tests/tenant_settings/checkEnabledDynamicClientRegistration.test.js +97 -0
  106. package/tests/tenant_settings/checkSandboxVersion.test.js +50 -0
  107. package/tests/tenant_settings/checkSessionLifetime.test.js +108 -0
  108. package/tests/tenant_settings/checkSupportEmail.test.js +77 -0
  109. package/tests/tenant_settings/checkSupportUrl.test.js +77 -0
  110. package/tests/tenant_settings/checkTenantLoginUri.test.js +82 -0
  111. package/tests/tenant_settings/checkTenantLogoutUrl.test.js +108 -0
  112. package/tests/tools/auth0.test.js +833 -0
  113. package/tests/tools/helpers.test.js +692 -0
  114. package/views/pdf_cli_report.handlebars +571 -0
@@ -0,0 +1,404 @@
1
+ const i18n = require("i18n");
2
+ const _ = require("lodash");
3
+ const listOfAnalyser = require("./lib/listOfAnalyser");
4
+ const {
5
+ getAccessToken,
6
+ getCustomDomains,
7
+ getApplications,
8
+ getConnections,
9
+ getAttackProtection,
10
+ getEmailProvider,
11
+ getLogStreams,
12
+ getEmailTemplates,
13
+ getErrorPageTemplate,
14
+ getTenantSettings,
15
+ getGuardianFactors,
16
+ getGuardianPolicies,
17
+ getRules,
18
+ getHooks,
19
+ getActions,
20
+ getLogs,
21
+ getNetworkACL,
22
+ getEventStreams,
23
+ } = require("./tools/auth0");
24
+
25
+ const logger = require("./lib/logger");
26
+ const { getSummaryReport } = require("./tools/summary");
27
+ const { convertToTitleCase, tranformReport } = require("./tools/utils");
28
+ async function runProductionChecks(tenant, validators) {
29
+ try {
30
+ logger.log("info", "Checking your configuration...");
31
+ const validatorsToRun = new Set(validators);
32
+ const checksPromises = listOfAnalyser.checks.map((check) => {
33
+ return new Promise((resolve) => {
34
+ if (!_.isEmpty(validatorsToRun) && !validatorsToRun.has(check.name)) {
35
+ //console.log(`Skipping ${check.name} `);
36
+ resolve({ name: check.name, details: [] });
37
+ }
38
+ logger.log(
39
+ "info",
40
+ `Running validator ${convertToTitleCase(check.name)}`,
41
+ );
42
+ check(tenant)
43
+ .then((checkResult) => {
44
+ resolve({ name: check.name, details: checkResult.details });
45
+ })
46
+ .catch((e) => {
47
+ resolve({ name: check.name, error: e });
48
+ });
49
+ });
50
+ });
51
+ return Promise.all(checksPromises);
52
+ } catch (e) {
53
+ logger.log("info", e);
54
+ }
55
+ }
56
+ async function generateReport(locale, tenantConfig, config) {
57
+ i18n.setLocale(locale);
58
+ try {
59
+ if (_.isEmpty(tenantConfig)) {
60
+ if (!config.auth0MgmtToken) {
61
+ config.auth0MgmtToken = await getAccessToken(
62
+ config.auth0Domain,
63
+ config.auth0ClientId,
64
+ config.auth0ClientSecret,
65
+ config.auth0MgmtToken,
66
+ );
67
+ }
68
+ tenantConfig.customDomains = await getCustomDomains(
69
+ config.auth0Domain,
70
+ config.auth0MgmtToken,
71
+ );
72
+ tenantConfig.clients = await getApplications(
73
+ config.auth0Domain,
74
+ config.auth0MgmtToken,
75
+ );
76
+ tenantConfig.databases = await getConnections(
77
+ config.auth0Domain,
78
+ config.auth0MgmtToken,
79
+ );
80
+ tenantConfig.attackProtection = await getAttackProtection(
81
+ config.auth0Domain,
82
+ config.auth0MgmtToken,
83
+ );
84
+ tenantConfig.emailProvider = await getEmailProvider(
85
+ config.auth0Domain,
86
+ config.auth0MgmtToken,
87
+ );
88
+ tenantConfig.logStreams = await getLogStreams(
89
+ config.auth0Domain,
90
+ config.auth0MgmtToken,
91
+ );
92
+ tenantConfig.emailTemplates = await getEmailTemplates(
93
+ config.auth0Domain,
94
+ config.auth0MgmtToken,
95
+ );
96
+ tenantConfig.errorPageTemplate = await getErrorPageTemplate(
97
+ config.auth0Domain,
98
+ config.auth0MgmtToken,
99
+ );
100
+ tenantConfig.tenant = await getTenantSettings(
101
+ config.auth0Domain,
102
+ config.auth0MgmtToken,
103
+ );
104
+ tenantConfig.guardianFactors = await getGuardianFactors(
105
+ config.auth0Domain,
106
+ config.auth0MgmtToken,
107
+ );
108
+ tenantConfig.guardianPolicies = await getGuardianPolicies(
109
+ config.auth0Domain,
110
+ config.auth0MgmtToken,
111
+ );
112
+ tenantConfig.rules = await getRules(
113
+ config.auth0Domain,
114
+ config.auth0MgmtToken,
115
+ );
116
+ tenantConfig.hooks = await getHooks(
117
+ config.auth0Domain,
118
+ config.auth0MgmtToken,
119
+ );
120
+ tenantConfig.actions = await getActions(
121
+ config.auth0Domain,
122
+ config.auth0MgmtToken,
123
+ );
124
+ const { log_query, logs } = await getLogs(
125
+ config.auth0Domain,
126
+ config.auth0MgmtToken,
127
+ );
128
+ tenantConfig.logs = logs;
129
+ tenantConfig.log_query = log_query;
130
+
131
+ tenantConfig.networkAcl = await getNetworkACL(
132
+ config.auth0Domain,
133
+ config.auth0MgmtToken
134
+ );
135
+
136
+ tenantConfig.eventStreams = await getEventStreams(
137
+ config.auth0Domain,
138
+ config.auth0MgmtToken
139
+ );
140
+ }
141
+ const statusOrder = ["green", "amber", "red"];
142
+ let fullReport =
143
+ (await runProductionChecks(tenantConfig, config.selectedValidators)) ||
144
+ [];
145
+ fullReport.forEach((report) => {
146
+ let grouped = [],
147
+ res = [],
148
+ sortedData = [];
149
+ report.title = i18n.__(`${report.name}.title`);
150
+ report.description = i18n.__(`${report.name}.description`);
151
+ report.docsPath = i18n.__(`${report.name}.docsPath`);
152
+ report.severity = i18n.__(`${report.name}.severity`);
153
+ report.severity_message = i18n.__(`${report.name}.severity_message`);
154
+ report.status = i18n.getCatalog("en")[`${report.name}`].status;
155
+ report.advisory = i18n.__(`${report.name}.advisory`);
156
+ let transformedDetails = [];
157
+ switch (report.name) {
158
+ case "checkCustomDomain":
159
+ report.details.forEach((cd) => {
160
+ cd.message = i18n.__(`checkCustomDomain.${cd.field}`, cd.value);
161
+ });
162
+ break;
163
+ case "checkEmailProvider":
164
+ report.details.forEach((cd) => {
165
+ cd.message = i18n.__(`checkEmailProvider.${cd.field}`, cd.value);
166
+ });
167
+ break;
168
+ case "checkEmailTemplates":
169
+ report.details.forEach((cd) => {
170
+ cd.message = i18n.__(`checkEmailTemplates.${cd.field}`, cd.value);
171
+ });
172
+ break;
173
+ case "checkErrorPageTemplate":
174
+ report.details.forEach((cd) => {
175
+ cd.message = i18n.__(`checkErrorPageTemplate.${cd.field}`, cd.value);
176
+ });
177
+ break;
178
+ case "checkLogStream":
179
+ case "checkEventStreams":
180
+ report.details.forEach((cd) => {
181
+ cd.message = i18n.__(
182
+ `${report.name}.${cd.field}`,
183
+ cd.name,
184
+ cd.type,
185
+ cd.stream_status,
186
+ );
187
+ });
188
+ break;
189
+ case "checkTenantSettings":
190
+ report.details.forEach((cd) => {
191
+ cd.message = i18n.__(`checkTenantSettings.${cd.field}`, cd.value);
192
+ });
193
+ break;
194
+ case "checkPasswordPolicy":
195
+ case "checkPasswordHistory":
196
+ case "checkPasswordNoPersonalInfo":
197
+ case "checkPromotedDBConnection":
198
+ case "checkPasswordComplexity":
199
+ report.details.forEach((cd) => {
200
+ cd.message = i18n.__(
201
+ `${report.name}.${cd.field}`,
202
+ cd.name,
203
+ cd.value,
204
+ );
205
+ });
206
+ break;
207
+ case "checkEmailAttributeVerification":
208
+ case "checkAuthenticationMethods":
209
+ report.pre_requisites = i18n.__(`${report.name}.pre_requisites`);
210
+ report.details.forEach((cd) => {
211
+ cd.message = i18n.__(
212
+ `${report.name}.${cd.field}`,
213
+ cd.name,
214
+ cd.value,
215
+ );
216
+ });
217
+ break;
218
+ case "checkJWTSignAlg":
219
+ report.advisory = i18n.__(`${report.name}.advisory`);
220
+ grouped = _.groupBy(report.details, "name");
221
+ res = tranformReport(grouped);
222
+ // Apply i18n translation to all reports
223
+ res.forEach((client) => {
224
+ client.values.forEach((detail) => {
225
+ detail.report.forEach((c) => {
226
+ c.name = client.name;
227
+ c.message = i18n.__(
228
+ `${report.name}.${c.field}`,
229
+ c.client_id,
230
+ c.value || "RS256",
231
+ );
232
+ });
233
+ });
234
+ });
235
+ break;
236
+ case "checkGrantTypes":
237
+ report.advisory = i18n.__(`${report.name}.advisory`);
238
+ grouped = _.groupBy(report.details, "name");
239
+ res = tranformReport(grouped);
240
+ // Apply i18n translation to all reports
241
+ res.forEach((client) => {
242
+ client.values.forEach((detail) => {
243
+ detail.report.forEach((c) => {
244
+ c.name = client.name;
245
+ c.message = i18n.__(
246
+ `${report.name}.${c.field}`,
247
+ c.value,
248
+ c.name,
249
+ c.app_type || "unknown",
250
+ );
251
+ });
252
+ });
253
+ });
254
+ break;
255
+ case "checkAllowedLogoutUrl":
256
+ case "checkApplicationLoginUri":
257
+ case "checkAllowedCallbacks":
258
+ case "checkWebOrigins":
259
+ grouped = _.groupBy(report.details, "name");
260
+
261
+ res = tranformReport(grouped);
262
+ // Apply i18n translation to all reports
263
+ res.forEach((client) => {
264
+ client.values.forEach((detail) => {
265
+ detail.report.forEach((c) => {
266
+ c.name = client.name;
267
+ c.message = i18n.__(`${report.name}.${c.field}`, c.value);
268
+ });
269
+ });
270
+ });
271
+ break;
272
+ case "checkCrossOriginAuthentication":
273
+ report.advisory = i18n.__(`${report.name}.advisory`);
274
+ grouped = _.groupBy(report.details, "name");
275
+ res = tranformReport(grouped);
276
+ // Apply i18n translation to all reports
277
+ res.forEach((client) => {
278
+ client.values.forEach((detail) => {
279
+ detail.report.forEach((c) => {
280
+ c.name = client.name;
281
+ c.message = i18n.__(
282
+ `${report.name}.${c.field}`,
283
+ c.name,
284
+ c.app_type,
285
+ );
286
+ });
287
+ });
288
+ });
289
+ break;
290
+ case "checkRefreshToken":
291
+ report.advisory = i18n.__(`${report.name}.advisory`);
292
+ grouped = _.groupBy(report.details, "name");
293
+ res = _.map(grouped, (values, name) => ({
294
+ name,
295
+ values: values,
296
+ }));
297
+ res.forEach((client) => {
298
+ sortedData = _.sortBy(client.values[0].report, (item) =>
299
+ statusOrder.indexOf(item.status),
300
+ );
301
+ sortedData.forEach((c) => {
302
+ c.message = i18n.__(
303
+ `checkRefreshToken.${c.field}`,
304
+ c.name,
305
+ c.value
306
+ );
307
+ });
308
+ });
309
+ break;
310
+ case "checkActionsHardCodedValues":
311
+ case "checkDASHardCodedValues":
312
+ report.disclaimer = i18n.__(`${report.name}.disclaimer`);
313
+
314
+ grouped = _.groupBy(report.details, "name");
315
+
316
+ _.forEach(grouped, (detailsArray) => {
317
+ detailsArray.forEach((detailItem) => {
318
+ const reportItems = detailItem.report;
319
+
320
+ // Group messages by scriptName
321
+ const groupedByScript = _.groupBy(reportItems, "scriptName");
322
+
323
+ // Build HTML per script
324
+ const htmlSections = Object.entries(groupedByScript).map(([scriptName, items]) => {
325
+ const listItems = items.map((c) => {
326
+ const message = i18n.__(
327
+ `${report.name}.${c.field}`,
328
+ c.variableName,
329
+ c.line,
330
+ c.column
331
+ );
332
+ return `<li>${message}</li>`;
333
+ }).join("\n");
334
+ const dasTitle = i18n.__(`${report.name}.action_script_title`,
335
+ scriptName);
336
+ return `<p>${dasTitle}<p>\n<ul>\n${listItems}\n</ul>`;
337
+ });
338
+
339
+ const fullHtml = `<div>\n${htmlSections.join("\n")}\n</div>`;
340
+
341
+ // Push transformed object to new structure
342
+ transformedDetails.push({
343
+ status: "red",
344
+ name: detailItem.name, // e.g., "login", "create"
345
+ field: "hard_coded_value_detected",
346
+ message: fullHtml
347
+ });
348
+ });
349
+ });
350
+
351
+ // Replace original report.details with the new structure
352
+ report.details = transformedDetails;
353
+ break;
354
+ case "checkDependencies":
355
+ report.details.forEach((cd) => {
356
+ cd.message = i18n.__(`${report.name}.${cd.field}`, cd.value);
357
+ cd.vulnFindings = cd.vulnFindings || [];
358
+ });
359
+ break;
360
+ case "checkNetworkACL":
361
+ report.disclaimer = i18n.__(`${report.name}.disclaimer`);
362
+ report.details.forEach((cd) => {
363
+ cd.message = i18n.__(`${report.name}.${cd.field}`, cd.value);
364
+ });
365
+ break;
366
+ default:
367
+ report.details.forEach((cd) => {
368
+ cd.message = i18n.__(`${report.name}.${cd.field}`, cd.value);
369
+ });
370
+ break;
371
+ }
372
+ });
373
+ const list_of_validators = i18n.__("list_of_validators");
374
+ let all_validators = [];
375
+ list_of_validators.forEach((validator) => {
376
+ all_validators =
377
+ validator.items.length > 0
378
+ ? all_validators.concat(validator.items)
379
+ : all_validators.concat([validator.title]);
380
+ });
381
+ const total_validators = all_validators.length;
382
+ const summary = await getSummaryReport(fullReport);
383
+ const report = {};
384
+ report.preamble = i18n.getCatalog(locale).preamble;
385
+ report.report_title = i18n.__("report_title");
386
+ (report.summary = summary), (report.full_report = fullReport);
387
+ report.tenantConfig = tenantConfig;
388
+ report.list_of_validators = list_of_validators;
389
+ report.validator_summary = i18n.__(
390
+ "validator_summary",
391
+ total_validators,
392
+ config.auth0Domain,
393
+ );
394
+ return report;
395
+ } catch (error) {
396
+ console.log(error);
397
+ logger.log("error", `Error generating report: ${error}`);
398
+ return {};
399
+ }
400
+ }
401
+
402
+ module.exports = {
403
+ generateReport,
404
+ };