@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,53 @@
1
+ /*
2
+ customDomains: [
3
+ {
4
+ domain: 'apac-tam-team.oauth101.net',
5
+ primary: true,
6
+ status: 'ready',
7
+ tls_policy: 'recommended',
8
+ type: 'auth0_managed_certs',
9
+ verification: [Object]
10
+ }
11
+ ]
12
+ */
13
+ const _ = require("lodash");
14
+ const executeCheck = require("../executeCheck");
15
+ const CONSTANTS = require("../constants");
16
+
17
+ function checkCustomDomain(options) {
18
+ const { customDomains } = options;
19
+ return executeCheck("checkCustomDomain", (callback) => {
20
+ const report = [];
21
+ if (_.isEmpty(customDomains)) {
22
+ report.push({
23
+ field: "not_configured",
24
+ status: CONSTANTS.FAIL,
25
+ });
26
+ } else if (customDomains.some((domain) => domain.status === "ready")) {
27
+ report.push({
28
+ field: "ready",
29
+ status: CONSTANTS.SUCCESS,
30
+ value: customDomains
31
+ .map((d) => {
32
+ return d.domain;
33
+ })
34
+ .join(","),
35
+ });
36
+ } else if (
37
+ customDomains.some((domain) => domain.status === "pending_verification")
38
+ ) {
39
+ report.push({
40
+ field: "pending_verification",
41
+ status: CONSTANTS.FAIL,
42
+ value: customDomains
43
+ .map((d) => {
44
+ return d.domain;
45
+ })
46
+ .join(","),
47
+ });
48
+ }
49
+ return callback(report);
50
+ });
51
+ }
52
+
53
+ module.exports = checkCustomDomain;
@@ -0,0 +1,98 @@
1
+ /*
2
+ {
3
+ databases: [
4
+ {
5
+ "id": "con_JBv3Nu3wcKQni7Vv",
6
+ "options": {
7
+ "import_mode": false,
8
+ "configuration": {},
9
+ "disable_signup": true,
10
+ "passwordPolicy": "good",
11
+ "passkey_options": {
12
+ "challenge_ui": "both",
13
+ "local_enrollment_enabled": true,
14
+ "progressive_enrollment_enabled": true
15
+ },
16
+ "password_history": {
17
+ "size": 5,
18
+ "enable": false
19
+ },
20
+ "strategy_version": 2,
21
+ "password_dictionary": {
22
+ "enable": false,
23
+ "dictionary": []
24
+ },
25
+ "authentication_methods": {
26
+ "passkey": {
27
+ "enabled": false
28
+ },
29
+ "password": {
30
+ "enabled": true
31
+ }
32
+ },
33
+ "brute_force_protection": true,
34
+ "password_no_personal_info": {
35
+ "enable": false
36
+ },
37
+ "password_complexity_options": {
38
+ "min_length": 8
39
+ },
40
+ "enabledDatabaseCustomization": false
41
+ },
42
+ "strategy": "auth0",
43
+ "name": "Username-Password-Authentication",
44
+ "is_domain_connection": false,
45
+ "realms": [
46
+ "Username-Password-Authentication"
47
+ ],
48
+ "enabled_clients": [
49
+ ]
50
+ }
51
+ ]
52
+ }
53
+ */
54
+ const _ = require("lodash");
55
+ const executeCheck = require("../executeCheck");
56
+ const CONSTANTS = require("../constants");
57
+
58
+ function checkAuthenticationMethods(options) {
59
+ const { databases } = options || [];
60
+ return executeCheck("checkAuthenticationMethods", (callback) => {
61
+ const report = [];
62
+ if (_.isEmpty(databases)) {
63
+ report.push({
64
+ field: "no_database_connections_found",
65
+ status: CONSTANTS.FAIL,
66
+ });
67
+ return callback(report);
68
+ }
69
+ databases.forEach((connection) => {
70
+ if (_.isEmpty(connection.options.authentication_methods)) {
71
+ //defaults to password
72
+ report.push({
73
+ name: connection.name,
74
+ status: CONSTANTS.FAIL,
75
+ field: "only_password_method",
76
+ });
77
+ } else if (
78
+ connection.options.authentication_methods.password.enabled &&
79
+ !connection.options.authentication_methods.passkey.enabled
80
+ ) {
81
+ report.push({
82
+ name: connection.name,
83
+ status: CONSTANTS.FAIL,
84
+ field: "only_password_method",
85
+ });
86
+ } else {
87
+ report.push({
88
+ name: connection.name,
89
+ status: CONSTANTS.SUCCESS,
90
+ field: "passkey_enabled",
91
+ });
92
+ }
93
+ });
94
+ return callback(report);
95
+ });
96
+ }
97
+
98
+ module.exports = checkAuthenticationMethods;
@@ -0,0 +1,163 @@
1
+ /*
2
+ {
3
+ databases: [
4
+ {
5
+ "id": "con_JBv3Nu3wcKQni7Vv",
6
+ "options": {
7
+ "import_mode": false,
8
+ "configuration": {},
9
+ "disable_signup": true,
10
+ "passwordPolicy": "good",
11
+ "passkey_options": {
12
+ "challenge_ui": "both",
13
+ "local_enrollment_enabled": true,
14
+ "progressive_enrollment_enabled": true
15
+ },
16
+ "password_history": {
17
+ "size": 5,
18
+ "enable": false
19
+ },
20
+ "strategy_version": 2,
21
+ "password_dictionary": {
22
+ "enable": false,
23
+ "dictionary": []
24
+ },
25
+ "authentication_methods": {
26
+ "passkey": {
27
+ "enabled": false
28
+ },
29
+ "password": {
30
+ "enabled": true
31
+ }
32
+ },
33
+ "brute_force_protection": true,
34
+ "password_no_personal_info": {
35
+ "enable": false
36
+ },
37
+ "password_complexity_options": {
38
+ "min_length": 8
39
+ },
40
+ "customScripts": {
41
+ "login": "function login(identifierValue, password, callback) {\n const mysql = require('mysql');\n const bcrypt = require('bcrypt');\n\n const connection = mysql.createConnection({\n host: 'localhost',\n user: 'me',\n password: 'secret',\n database: 'mydb'\n });\n\n connection.connect();\n\n const query = 'SELECT id, nickname, email, password FROM users WHERE email = ?';\n\n connection.query(query, [ identifierValue ], function(err, results) {\n if (err) return callback(err);\n if (results.length === 0) return callback(new WrongUsernameOrPasswordError(identifierValue));\n const user = results[0];\n\n bcrypt.compare(password, user.password, function(err, isValid) {\n if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(identifierValue));\n\n callback(null, {\n user_id: user.id.toString(),\n nickname: user.nickname,\n email: user.email\n });\n });\n });\n}\n",
42
+ "create": "function create(user, callback) {\n const mysql = require('mysql');\n const bcrypt = require('bcrypt');\n\n const connection = mysql.createConnection({\n host: 'localhost',\n user: 'me',\n password: 'secret',\n database: 'mydb'\n });\n\n connection.connect();\n\n const query = 'INSERT INTO users SET ?';\n\n bcrypt.hash(user.password, 10, function(err, hash) {\n if (err) return callback(err);\n\n const insert = {\n password: hash,\n email: user.email\n };\n\n connection.query(query, insert, function(err, results) {\n if (err) return callback(err);\n if (results.length === 0) return callback();\n callback(null);\n });\n });\n}\n",
43
+ "delete": "function remove(id, callback) {\n // This script remove a user from your existing database.\n // It is executed whenever a user is deleted from the API or Auth0 dashboard.\n //\n // There are two ways that this script can finish:\n // 1. The user was removed successfully:\n // callback(null);\n // 2. Something went wrong while trying to reach your database:\n // callback(new Error(\"my error message\"));\n\n const msg = 'Please implement the Delete script for this database ' +\n 'connection at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n",
44
+ "verify": "function verify(email, callback) {\n const mysql = require('mysql');\n\n const connection = mysql.createConnection({\n host: 'localhost',\n user: 'me',\n password: 'secret',\n database: 'mydb'\n });\n\n connection.connect();\n\n const query = 'UPDATE users SET email_Verified = true WHERE email_Verified = false AND email = ?';\n\n connection.query(query, [ email ], function(err, results) {\n if (err) return callback(err);\n\n callback(null, results.length > 0);\n });\n\n}\n",
45
+ "get_user": "function getUser(identifierValue, callback) {\n const mysql = require('mysql');\n\n const connection = mysql.createConnection({\n host: 'localhost',\n user: 'me',\n password: 'secret',\n database: 'mydb'\n });\n\n connection.connect();\n\n const query = 'SELECT id, nickname, email FROM users WHERE email = ?';\n\n connection.query(query, [ identifierValue ], function(err, results) {\n if (err || results.length === 0) return callback(err || null);\n\n const user = results[0];\n callback(null, {\n user_id: user.id.toString(),\n nickname: user.nickname,\n email: user.email\n });\n });\n}\n",
46
+ "change_password": "function changePassword(email, newPassword, callback) {\n const mysql = require('mysql');\n const bcrypt = require('bcrypt');\n\n const connection = mysql.createConnection({\n host: 'localhost',\n user: 'me',\n password: 'secret',\n database: 'mydb'\n });\n\n connection.connect();\n\n const query = 'UPDATE users SET password = ? WHERE email = ?';\n\n bcrypt.hash(newPassword, 10, function(err, hash) {\n if (err) return callback(err);\n\n connection.query(query, [ hash, email ], function(err, results) {\n if (err) return callback(err);\n callback(null, results.length > 0);\n });\n });\n}\n"
47
+ },
48
+ "enabledDatabaseCustomization": true,
49
+
50
+ },
51
+ "strategy": "auth0",
52
+ "name": "Username-Password-Authentication",
53
+ "is_domain_connection": false,
54
+ "realms": [
55
+ "Username-Password-Authentication"
56
+ ],
57
+ "enabled_clients": [
58
+ ]
59
+ }
60
+ ]
61
+ }
62
+ */
63
+ const _ = require("lodash");
64
+ const executeCheck = require("../executeCheck");
65
+ const CONSTANTS = require("../constants");
66
+ const acorn = require("acorn");
67
+ const walk = require("estree-walker").walk;
68
+
69
+ function detectHardcodedValues(code, scriptName) {
70
+ let processedCode = code.replace(/(?!\w+#)\b#(\w+)/g, "_$1");
71
+ const ast = acorn.parse(processedCode, {
72
+ ecmaVersion: "latest",
73
+ locations: true,
74
+ });
75
+
76
+ const hardcodedValues = [];
77
+
78
+ walk(ast, {
79
+ enter(node) {
80
+ // Variable assignments
81
+ if (node.type === "VariableDeclaration") {
82
+ node.declarations.forEach((declaration) => {
83
+ if (
84
+ declaration.init &&
85
+ declaration.init.type === "Literal" &&
86
+ typeof declaration.init.value === "string" &&
87
+ !isCommonException(declaration.init.value)
88
+ ) {
89
+ hardcodedValues.push({
90
+ scriptName: scriptName,
91
+ variableName: declaration.id.name,
92
+ field: "hard_coded_value_detected",
93
+ status: CONSTANTS.FAIL,
94
+ type: typeof declaration.init.value,
95
+ line: declaration.loc.start.line,
96
+ column: declaration.loc.start.column,
97
+ });
98
+ }
99
+ });
100
+ }
101
+
102
+ // Object literals
103
+ if (
104
+ node.type === "Property" &&
105
+ node.value.type === "Literal" &&
106
+ typeof node.value.value === "string" &&
107
+ !isCommonException(node.value.value)
108
+ ) {
109
+ hardcodedValues.push({
110
+ scriptName: scriptName,
111
+ variableName: node.key.name || node.key.value,
112
+ field: "hard_coded_value_detected",
113
+ status: CONSTANTS.FAIL,
114
+ type: typeof node.value.value,
115
+ line: node.loc.start.line,
116
+ column: node.loc.start.column,
117
+ });
118
+ }
119
+ },
120
+ });
121
+
122
+ return hardcodedValues;
123
+ }
124
+
125
+ // Helper functions
126
+ function isCommonException(value) {
127
+ const exceptions = [
128
+ /^[0-1]$/, // Allow 0 and 1
129
+ /^[a-z]$/i, // Single letters
130
+ /^\s*$/, // Whitespace-only
131
+ /^[{}()[]<>]+$/, // Common brackets
132
+ ];
133
+ return exceptions.some((regex) => regex.test(String(value)));
134
+ }
135
+
136
+
137
+ function checkDASHardCodedValues(options) {
138
+ const { databases } = options || [];
139
+ return executeCheck("checkDASHardCodedValues", (callback) => {
140
+ const reports = [];
141
+ if (_.isEmpty(databases)) {
142
+ reports.push({
143
+ field: "no_database_connections_found",
144
+ status: CONSTANTS.FAIL,
145
+ });
146
+ return callback(reports);
147
+ }
148
+ databases.forEach((connection) => {
149
+ const { enabledDatabaseCustomization, customScripts } = connection.options;
150
+ if (enabledDatabaseCustomization) {
151
+ Object.entries(customScripts).forEach(([scriptName, scriptCode]) => {
152
+ var report = detectHardcodedValues(scriptCode, scriptName);
153
+ if (report.length > 0) {
154
+ reports.push({ name: connection.name, report: report });
155
+ }
156
+ });
157
+ }
158
+ });
159
+ return callback(reports);
160
+ });
161
+ }
162
+
163
+ module.exports = checkDASHardCodedValues;
@@ -0,0 +1,114 @@
1
+ /*
2
+ {
3
+ "id": "con_GVkgEDMhImBiBt2j",
4
+ "options": {
5
+ "mfa": {
6
+ "active": true,
7
+ "return_enroll_settings": true
8
+ },
9
+ "attributes": {
10
+ "email": {
11
+ "signup": {
12
+ "status": "required",
13
+ "verification": {
14
+ "active": true
15
+ }
16
+ },
17
+ "identifier": {
18
+ "active": true
19
+ },
20
+ "profile_required": true,
21
+ "verification_method": "otp" //link
22
+ }
23
+ },
24
+ "import_mode": false,
25
+ "configuration": {},
26
+ "customScripts": {
27
+ "login": "function login(identifierValue, password, callback) {\n // This script should authenticate a user against the credentials stored in\n // your database.\n // It is executed when a user attempts to log in or immediately after signing\n // up (as a verification that the user was successfully signed up).\n //\n // Everything returned by this script will be set as part of the user profile\n // and will be visible by any of the tenant admins. Avoid adding attributes\n // with values such as passwords, keys, secrets, etc.\n //\n // The `password` parameter of this function is in plain text. It must be\n // hashed/salted to match whatever is stored in your database. For example:\n //\n // var bcrypt = require('bcrypt@0.8.5');\n // bcrypt.compare(password, dbPasswordHash, function(err, res)) { ... }\n //\n // There are three ways this script can finish:\n // 1. The user's credentials are valid. The returned user profile should be in\n // the following format: https://auth0.com/docs/users/normalized/auth0/normalized-user-profile-schema\n // var profile = {\n // user_id: ..., // user_id is mandatory\n // email: ...,\n // [...]\n // };\n // callback(null, profile);\n // 2. The user's credentials are invalid\n // callback(new WrongUsernameOrPasswordError(email, \"my error message\"));\n //\n // Note: Passing no arguments or a falsey first argument to\n // `WrongUsernameOrPasswordError` will result in the error being logged as\n // an `fu` event (invalid username/email) with an empty string for a user_id.\n // Providing a truthy first argument will result in the error being logged\n // as an `fp` event (the user exists, but the password is invalid) with a\n // user_id value of \"auth0|<first argument>\". See the `Log Event Type Codes`\n // documentation for more information about these event types:\n // https://auth0.com/docs/deploy-monitor/logs/log-event-type-codes\n // 3. Something went wrong while trying to reach your database\n // callback(new Error(\"my error message\"));\n //\n // A list of Node.js modules which can be referenced is available here:\n //\n // https://tehsis.github.io/webtaskio-canirequire/\n\n const msg = 'Please implement the Login script for this database connection ' +\n 'at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n",
28
+ "create": "function create(user, callback) {\n // This script should create a user entry in your existing database. It will\n // be executed when a user attempts to sign up, or when a user is created\n // through the Auth0 dashboard or API.\n // When this script has finished executing, the Login script will be\n // executed immediately afterwards, to verify that the user was created\n // successfully.\n //\n // The user object will always contain the following properties:\n // * email: the user's email\n // * password: the password entered by the user, in plain text\n // * tenant: the name of this Auth0 account\n // * client_id: the client ID of the application where the user signed up, or\n // API key if created through the API or Auth0 dashboard\n // * connection: the name of this database connection\n //\n // There are three ways this script can finish:\n // 1. A user was successfully created\n // callback(null);\n // 2. This user already exists in your database\n // callback(new ValidationError(\"user_exists\", \"my error message\"));\n // 3. Something went wrong while trying to reach your database\n // callback(new Error(\"my error message\"));\n\n const msg = 'Please implement the Create script for this database connection ' +\n 'at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n",
29
+ "delete": "function remove(id, callback) {\n // This script remove a user from your existing database.\n // It is executed whenever a user is deleted from the API or Auth0 dashboard.\n //\n // There are two ways that this script can finish:\n // 1. The user was removed successfully:\n // callback(null);\n // 2. Something went wrong while trying to reach your database:\n // callback(new Error(\"my error message\"));\n\n const msg = 'Please implement the Delete script for this database ' +\n 'connection at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n",
30
+ "verify": "function verify(email, callback) {\n // This script should mark the current user's email address as verified in\n // your database.\n // It is executed whenever a user clicks the verification link sent by email.\n // These emails can be customized at https://manage.auth0.com/#/emails.\n // It is safe to assume that the user's email already exists in your database,\n // because verification emails, if enabled, are sent immediately after a\n // successful signup.\n //\n // There are two ways that this script can finish:\n // 1. The user's email was verified successfully\n // callback(null, true);\n // 2. Something went wrong while trying to reach your database:\n // callback(new Error(\"my error message\"));\n //\n // If an error is returned, it will be passed to the query string of the page\n // where the user is being redirected to after clicking the verification link.\n // For example, returning `callback(new Error(\"error\"))` and redirecting to\n // https://example.com would redirect to the following URL:\n // https://example.com?email=alice%40example.com&message=error&success=false\n\n const msg = 'Please implement the Verify script for this database connection ' +\n 'at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n",
31
+ "get_user": "function getUser(identifierValue, callback) {\n // This script should retrieve a user profile from your existing database,\n // without authenticating the user.\n // It is used to check if a user exists before executing flows that do not\n // require authentication (signup and password reset).\n //\n // There are three ways this script can finish:\n // 1. A user was successfully found. The profile should be in the following\n // format: https://auth0.com/docs/users/normalized/auth0/normalized-user-profile-schema.\n // callback(null, profile);\n // 2. A user was not found\n // callback(null);\n // 3. Something went wrong while trying to reach your database:\n // callback(new Error(\"my error message\"));\n\n const msg = 'Please implement the Get User script for this database connection ' +\n 'at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n",
32
+ "change_password": "function changePassword(identifierValue, newPassword, callback) {\n // This script should change the password stored for the current user in your\n // database. It is executed when the user clicks on the confirmation link\n // after a reset password request.\n // The content and behavior of password confirmation emails can be customized\n // here: https://manage.auth0.com/#/emails\n // The `newPassword` parameter of this function is in plain text. It must be\n // hashed/salted to match whatever is stored in your database.\n //\n // There are three ways that this script can finish:\n // 1. The user's password was updated successfully:\n // callback(null, true);\n // 2. The user's password was not updated:\n // callback(null, false);\n // 3. Something went wrong while trying to reach your database:\n // callback(new Error(\"my error message\"));\n //\n // If an error is returned, it will be passed to the query string of the page\n // where the user is being redirected to after clicking the confirmation link.\n // For example, returning `callback(new Error(\"error\"))` and redirecting to\n // https://example.com would redirect to the following URL:\n // https://example.com?email=alice%40example.com&message=error&success=false\n\n const msg = 'Please implement the Change Password script for this database ' +\n 'connection at https://manage.auth0.com/#/connections/database';\n return callback(new Error(msg));\n}\n"
33
+ },
34
+ "passwordPolicy": "fair",
35
+ "passkey_options": {
36
+ "challenge_ui": "both",
37
+ "local_enrollment_enabled": true,
38
+ "progressive_enrollment_enabled": true
39
+ },
40
+ "password_history": {
41
+ "size": 5,
42
+ "enable": false
43
+ },
44
+ "strategy_version": 2,
45
+ "password_dictionary": {
46
+ "enable": false,
47
+ "dictionary": []
48
+ },
49
+ "authentication_methods": {
50
+ "passkey": {
51
+ "enabled": false
52
+ },
53
+ "password": {
54
+ "enabled": true
55
+ }
56
+ },
57
+ "brute_force_protection": true,
58
+ "password_no_personal_info": {
59
+ "enable": false
60
+ },
61
+ "password_complexity_options": {
62
+ "min_length": 8
63
+ },
64
+ "enabledDatabaseCustomization": false
65
+ },
66
+ "strategy": "auth0",
67
+ "name": "Username-Password-Authentication",
68
+ "is_domain_connection": false,
69
+ "enabled_clients": [
70
+ ],
71
+ "realms": [
72
+ "Username-Password-Authentication"
73
+ ]
74
+ }
75
+ */
76
+ const _ = require("lodash");
77
+ const executeCheck = require("../executeCheck");
78
+ const CONSTANTS = require("../constants");
79
+
80
+ function checkEmailAttributeVerification(options) {
81
+ const { databases } = options || [];
82
+ return executeCheck("checkEmailAttributeVerification", (callback) => {
83
+ const report = [];
84
+ if (_.isEmpty(databases)) {
85
+ report.push({
86
+ field: "no_database_connections_found",
87
+ status: CONSTANTS.FAIL,
88
+ });
89
+ return callback(report);
90
+ }
91
+ databases.forEach((connection) => {
92
+ if (_.isEmpty(connection.options.attributes)) {
93
+ //defaults to email
94
+ report.push({
95
+ name: connection.name,
96
+ status: CONSTANTS.FAIL,
97
+ field: "flexible_identifiers_disabled",
98
+ });
99
+ } else if (
100
+ connection.options.attributes.email?.verification_method &&
101
+ connection.options.attributes.email?.verification_method !== 'otp'
102
+ ) {
103
+ report.push({
104
+ name: connection.name,
105
+ status: CONSTANTS.FAIL,
106
+ field: "verification_by_link_method",
107
+ });
108
+ }
109
+ });
110
+ return callback(report);
111
+ });
112
+ }
113
+
114
+ module.exports = checkEmailAttributeVerification;
@@ -0,0 +1,83 @@
1
+ /*
2
+ {
3
+ databases: [
4
+ {
5
+ "id": "con_JBv3Nu3wcKQni7Vv",
6
+ "options": {
7
+ "import_mode": false,
8
+ "configuration": {},
9
+ "disable_signup": true,
10
+ "passwordPolicy": "good",
11
+ "passkey_options": {
12
+ "challenge_ui": "both",
13
+ "local_enrollment_enabled": true,
14
+ "progressive_enrollment_enabled": true
15
+ },
16
+ "password_history": {
17
+ "size": 5,
18
+ "enable": false
19
+ },
20
+ "strategy_version": 2,
21
+ "password_dictionary": {
22
+ "enable": false,
23
+ "dictionary": []
24
+ },
25
+ "authentication_methods": {
26
+ "passkey": {
27
+ "enabled": false
28
+ },
29
+ "password": {
30
+ "enabled": true
31
+ }
32
+ },
33
+ "brute_force_protection": true,
34
+ "password_no_personal_info": {
35
+ "enable": false
36
+ },
37
+ "password_complexity_options": {
38
+ "min_length": 8
39
+ },
40
+ "enabledDatabaseCustomization": false
41
+ },
42
+ "strategy": "auth0",
43
+ "name": "Username-Password-Authentication",
44
+ "is_domain_connection": false,
45
+ "realms": [
46
+ "Username-Password-Authentication"
47
+ ],
48
+ "enabled_clients": [
49
+ ]
50
+ }
51
+ ]
52
+ }
53
+ */
54
+ const _ = require("lodash");
55
+ const executeCheck = require("../executeCheck");
56
+ const CONSTANTS = require("../constants");
57
+
58
+ function checkEnabledDatabaseCustomization(options) {
59
+ const { databases } = options || [];
60
+ return executeCheck("checkEnabledDatabaseCustomization", (callback) => {
61
+ const report = [];
62
+ if (_.isEmpty(databases)) {
63
+ report.push({
64
+ field: "no_database_connections_found",
65
+ status: CONSTANTS.FAIL,
66
+ });
67
+ return callback(report);
68
+ }
69
+ databases.forEach((connection) => {
70
+ const { import_mode, enabledDatabaseCustomization} = connection.options;
71
+ if (!import_mode && enabledDatabaseCustomization) {
72
+ report.push({
73
+ name: connection.name,
74
+ status: CONSTANTS.FAIL,
75
+ field: "external_user_store",
76
+ });
77
+ }
78
+ });
79
+ return callback(report);
80
+ });
81
+ }
82
+
83
+ module.exports = checkEnabledDatabaseCustomization;
@@ -0,0 +1,100 @@
1
+ /*
2
+ {
3
+ databases: [
4
+ {
5
+ "id": "con_JBv3Nu3wcKQni7Vv",
6
+ "options": {
7
+ "import_mode": false,
8
+ "configuration": {},
9
+ "disable_signup": true,
10
+ "passwordPolicy": "good",
11
+ "passkey_options": {
12
+ "challenge_ui": "both",
13
+ "local_enrollment_enabled": true,
14
+ "progressive_enrollment_enabled": true
15
+ },
16
+ "password_history": {
17
+ "size": 5,
18
+ "enable": false
19
+ },
20
+ "strategy_version": 2,
21
+ "password_dictionary": {
22
+ "enable": false,
23
+ "dictionary": []
24
+ },
25
+ "authentication_methods": {
26
+ "passkey": {
27
+ "enabled": false
28
+ },
29
+ "password": {
30
+ "enabled": true
31
+ }
32
+ },
33
+ "brute_force_protection": true,
34
+ "password_no_personal_info": {
35
+ "enable": false
36
+ },
37
+ "password_complexity_options": {
38
+ "min_length": 8
39
+ },
40
+ "enabledDatabaseCustomization": false
41
+ },
42
+ "strategy": "auth0",
43
+ "name": "Username-Password-Authentication",
44
+ "is_domain_connection": false,
45
+ "realms": [
46
+ "Username-Password-Authentication"
47
+ ],
48
+ "enabled_clients": [
49
+ ]
50
+ }
51
+ ]
52
+ }
53
+ */
54
+ const _ = require("lodash");
55
+ const executeCheck = require("../executeCheck");
56
+ const CONSTANTS = require("../constants");
57
+
58
+ function checkPasswordComplexity(options) {
59
+ const { databases } = options || [];
60
+ return executeCheck("checkPasswordComplexity", (callback) => {
61
+ const report = [];
62
+ if (_.isEmpty(databases)) {
63
+ report.push({
64
+ field: "no_database_connections_found",
65
+ status: CONSTANTS.FAIL,
66
+ });
67
+ return callback(report);
68
+ }
69
+ databases.forEach((connection) => {
70
+ //Check password complexity and minimum length.
71
+ if (!_.isEmpty(connection.options.password_complexity_options)) {
72
+ // Recommend NIST standards
73
+ if (connection.options.password_complexity_options.min_length < 12) {
74
+ report.push({
75
+ name: connection.name,
76
+ field: "password_min_length_fail",
77
+ status: CONSTANTS.FAIL,
78
+ value: connection.options.password_complexity_options.min_length,
79
+ });
80
+ } else {
81
+ report.push({
82
+ name: connection.name,
83
+ status: CONSTANTS.SUCCESS,
84
+ field: "password_min_length_success",
85
+ value: connection.options.password_complexity_options.min_length,
86
+ });
87
+ }
88
+ } else {
89
+ report.push({
90
+ name: connection.name,
91
+ field: "password_complexity_not_configured",
92
+ status: CONSTANTS.FAIL,
93
+ });
94
+ }
95
+ });
96
+ return callback(report);
97
+ });
98
+ }
99
+
100
+ module.exports = checkPasswordComplexity;