@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,125 @@
1
+ /*
2
+ {
3
+ clients: [
4
+ {
5
+ "tenant": "contos0",
6
+ "global": false,
7
+ "is_token_endpoint_ip_header_trusted": false,
8
+ "name": "Default App",
9
+ "is_first_party": true,
10
+ "oidc_conformant": true,
11
+ "sso_disabled": false,
12
+ "cross_origin_auth": false,
13
+ "refresh_token": {
14
+ "expiration_type": "expiring",
15
+ "leeway": 0,
16
+ "token_lifetime": 2592000,
17
+ "idle_token_lifetime": 1296000,
18
+ "infinite_token_lifetime": false,
19
+ "infinite_idle_token_lifetime": false,
20
+ "rotation_type": "rotating"
21
+ },
22
+ "allowed_clients": [],
23
+ "allowed_logout_urls": [
24
+ "http://localhost:3000"
25
+ ],
26
+ "callbacks": [
27
+ "http://localhost:3000"
28
+ ],
29
+ "native_social_login": {
30
+ "apple": {
31
+ "enabled": false
32
+ },
33
+ "facebook": {
34
+ "enabled": false
35
+ }
36
+ },
37
+ "client_id": "client_id",
38
+ "callback_url_template": false,
39
+ "jwt_configuration": {
40
+ "alg": "RS256",
41
+ "lifetime_in_seconds": 36000,
42
+ "secret_encoded": false
43
+ },
44
+ "client_aliases": [],
45
+ "token_endpoint_auth_method": "none",
46
+ "app_type": "spa",
47
+ "grant_types": [
48
+ "authorization_code",
49
+ "implicit",
50
+ "refresh_token"
51
+ ],
52
+ "web_origins": [
53
+ "http://localhost:3000"
54
+ ],
55
+ "custom_login_page_on": true
56
+ }
57
+ ]
58
+ }
59
+ */
60
+ const _ = require("lodash");
61
+ const executeCheck = require("../executeCheck");
62
+ const CONSTANTS = require("../constants");
63
+ // Function to check callback URLs for insecure patterns (localhost, http, 127.0.0.1)
64
+ function checkURLsForApp(app) {
65
+ const initiate_login_uri = app.initiate_login_uri || "";
66
+ const report = [];
67
+ const insecurePatterns = ["localhost", "http://", "127.0.0.1"];
68
+ if (
69
+ _.isEmpty(initiate_login_uri) &&
70
+ (app.app_type === "spa" || app.app_type === "regular_web")
71
+ ) {
72
+ report.push({
73
+ name: app.client_id ? app.name.concat(` (${app.client_id})`) : app.name,
74
+ client_id: app.client_id || app.name,
75
+ field: "missing_initiate_login_uri",
76
+ value: "missing_initiate_login_uri",
77
+ status: CONSTANTS.FAIL,
78
+ app_type: app.app_type,
79
+ is_first_party: app.is_first_party
80
+ });
81
+ }
82
+ const subArr = insecurePatterns.filter((str) =>
83
+ initiate_login_uri.includes(str),
84
+ );
85
+ if (subArr.length > 0) {
86
+ report.push({
87
+ name: app.client_id ? app.name.concat(` (${app.client_id})`) : app.name,
88
+ client_id: app.client_id || app.name,
89
+ field: "insecure_initiate_login_uri",
90
+ value: initiate_login_uri,
91
+ status: CONSTANTS.FAIL,
92
+ app_type: app.app_type,
93
+ is_first_party: app.is_first_party
94
+ });
95
+ }
96
+ return report;
97
+ }
98
+
99
+ function checkApplicationLoginUri(options) {
100
+ return executeCheck("checkApplicationLoginUri", (callback) => {
101
+ const { clients } = options;
102
+ const reports = [];
103
+ if (_.isEmpty(clients)) {
104
+ return callback(reports);
105
+ }
106
+ clients.forEach((client) => {
107
+ var report = checkURLsForApp(client);
108
+ if (report.length === 0) {
109
+ report.push({
110
+ name: client.name,
111
+ client_id: client.client_id || client.name,
112
+ field: "secure_initiate_login_uri",
113
+ status: CONSTANTS.SUCCESS,
114
+ value: client.initiate_login_uri ? client.initiate_login_uri : "",
115
+ app_type: client.app_type || "unknown",
116
+ is_first_party: client.is_first_party
117
+ });
118
+ }
119
+ reports.push({ name: client.name.concat(` (${client.client_id})`), report: report });
120
+ });
121
+ return callback(reports);
122
+ });
123
+ }
124
+
125
+ module.exports = checkApplicationLoginUri;
@@ -0,0 +1,91 @@
1
+ /*
2
+ {
3
+ clients: [
4
+ {
5
+ "tenant": "contos0",
6
+ "global": false,
7
+ "is_token_endpoint_ip_header_trusted": false,
8
+ "name": "Default App",
9
+ "is_first_party": true,
10
+ "oidc_conformant": true,
11
+ "sso_disabled": false,
12
+ "cross_origin_auth": false,
13
+ "cross_origin_authentication": false,
14
+ "refresh_token": {
15
+ "expiration_type": "expiring",
16
+ "leeway": 0,
17
+ "token_lifetime": 2592000,
18
+ "idle_token_lifetime": 1296000,
19
+ "infinite_token_lifetime": false,
20
+ "infinite_idle_token_lifetime": false,
21
+ "rotation_type": "rotating"
22
+ },
23
+ "allowed_clients": [],
24
+ "allowed_logout_urls": [
25
+ "http://localhost:3000"
26
+ ],
27
+ "callbacks": [
28
+ "http://localhost:3000"
29
+ ],
30
+ "native_social_login": {
31
+ "apple": {
32
+ "enabled": false
33
+ },
34
+ "facebook": {
35
+ "enabled": false
36
+ }
37
+ },
38
+ "client_id": "client_id",
39
+ "callback_url_template": false,
40
+ "jwt_configuration": {
41
+ "alg": "RS256",
42
+ "lifetime_in_seconds": 36000,
43
+ "secret_encoded": false
44
+ },
45
+ "client_aliases": [],
46
+ "token_endpoint_auth_method": "none",
47
+ "app_type": "spa",
48
+ "grant_types": [
49
+ "authorization_code",
50
+ "implicit",
51
+ "refresh_token"
52
+ ],
53
+ "web_origins": [
54
+ "http://localhost:3000"
55
+ ],
56
+ "custom_login_page_on": true
57
+ }
58
+ ]
59
+ }
60
+ */
61
+ const _ = require("lodash");
62
+ const executeCheck = require("../executeCheck");
63
+ const CONSTANTS = require("../constants");
64
+
65
+ function checkCrossOriginAuthentication(options) {
66
+ return executeCheck("checkCrossOriginAuthentication", (callback) => {
67
+ const { clients } = options;
68
+ const reports = [];
69
+ if (_.isEmpty(clients)) {
70
+ return callback(reports);
71
+ }
72
+ // https://community.auth0.com/t/action-required-update-applications-that-use-cross-origin-authentication/132819
73
+ clients.forEach((client) => {
74
+ var report = [];
75
+ report.push({
76
+ name: client.client_id
77
+ ? client.name.concat(` (${client.client_id})`)
78
+ : client.name,
79
+ client_id: client.client_id || client.name,
80
+ field: client.cross_origin_authentication ? "cross_origin_authentication_enabled" : "cross_origin_authentication_disabled",
81
+ status: client.cross_origin_authentication ? CONSTANTS.FAIL : CONSTANTS.SUCCESS,
82
+ app_type: client.app_type || "unknown",
83
+ is_first_party: client.is_first_party
84
+ });
85
+ reports.push({ name: client.name.concat(` (${client.client_id})`), report: report });
86
+ });
87
+ return callback(reports);
88
+ });
89
+ }
90
+
91
+ module.exports = checkCrossOriginAuthentication;
@@ -0,0 +1,138 @@
1
+ /*
2
+ {
3
+ clients: [
4
+ {
5
+ "tenant": "contos0",
6
+ "global": false,
7
+ "is_token_endpoint_ip_header_trusted": false,
8
+ "name": "Default App",
9
+ "is_first_party": true,
10
+ "oidc_conformant": true,
11
+ "sso_disabled": false,
12
+ "cross_origin_auth": false,
13
+ "refresh_token": {
14
+ "expiration_type": "expiring",
15
+ "leeway": 0,
16
+ "token_lifetime": 2592000,
17
+ "idle_token_lifetime": 1296000,
18
+ "infinite_token_lifetime": false,
19
+ "infinite_idle_token_lifetime": false,
20
+ "rotation_type": "rotating"
21
+ },
22
+ "allowed_clients": [],
23
+ "allowed_logout_urls": [
24
+ "http://localhost:3000"
25
+ ],
26
+ "callbacks": [
27
+ "http://localhost:3000"
28
+ ],
29
+ "native_social_login": {
30
+ "apple": {
31
+ "enabled": false
32
+ },
33
+ "facebook": {
34
+ "enabled": false
35
+ }
36
+ },
37
+ "client_id": "client_id",
38
+ "callback_url_template": false,
39
+ "jwt_configuration": {
40
+ "alg": "RS256",
41
+ "lifetime_in_seconds": 36000,
42
+ "secret_encoded": false
43
+ },
44
+ "client_aliases": [],
45
+ "token_endpoint_auth_method": "none",
46
+ "app_type": "spa",
47
+ "grant_types": [
48
+ "authorization_code",
49
+ "implicit",
50
+ "refresh_token"
51
+ ],
52
+ "web_origins": [
53
+ "http://localhost:3000"
54
+ ],
55
+ "custom_login_page_on": true
56
+ }
57
+ ]
58
+ }
59
+ */
60
+ const _ = require("lodash");
61
+ const executeCheck = require("../executeCheck");
62
+ const CONSTANTS = require("../constants");
63
+
64
+ function validateGrantTypesForApp(app) {
65
+ const enabledGrantTypes = app.grant_types || [];
66
+ const appType = app.app_type || "unknown";
67
+ const report = [];
68
+ let requiredGrantTypes = [];
69
+
70
+ // Define expected grant types based on appType (OAuth2.0 best practices)
71
+ switch (appType) {
72
+ case "regular_web":
73
+ requiredGrantTypes = [
74
+ "authorization_code",
75
+ "refresh_token",
76
+ "client_credentials",
77
+ ]; // Authorization Code with PKCE and Refresh Tokens
78
+ break;
79
+ case "spa":
80
+ requiredGrantTypes = ["authorization_code", "refresh_token"]; // Implicit (only for older apps) or Authorization Code with PKCE
81
+ break;
82
+ case "native":
83
+ requiredGrantTypes = [
84
+ "authorization_code",
85
+ "refresh_token",
86
+ "urn:ietf:params:oauth:grant-type:device_code",
87
+ ]; // Authorization Code with PKCE and Refresh Tokens, Device Code, this abou thow to skip this if extended granty_type is used
88
+ break;
89
+ case "non_interactive":
90
+ requiredGrantTypes = ["client_credentials"]; // Client Credentials (no user involvement)
91
+ break;
92
+ default:
93
+ requiredGrantTypes = [
94
+ "authorization_code",
95
+ "refresh_token"
96
+ ]; // Authorization Code with PKCE and Refresh Tokens
97
+ break;
98
+ }
99
+
100
+ // Optionally, check for any additional unexpected grant types
101
+ var unexpectedGrantTypes = [];
102
+ enabledGrantTypes.forEach((grantType) => {
103
+ if (!requiredGrantTypes.includes(grantType)) {
104
+ unexpectedGrantTypes.push(grantType);
105
+ }
106
+ });
107
+ if (!_.isEmpty(unexpectedGrantTypes)) {
108
+ report.push({
109
+ name: app.client_id ? app.name.concat(` (${app.client_id})`) : app.name,
110
+ client_id: app.client_id,
111
+ field: "unexpected_grant_type_for_app_type",
112
+ value: unexpectedGrantTypes.join(", "),
113
+ status: CONSTANTS.FAIL,
114
+ app_type: appType,
115
+ is_first_party: app.is_first_party
116
+ });
117
+ }
118
+ return report;
119
+ }
120
+
121
+ function checkGrantTypes(options) {
122
+ return executeCheck("checkGrantTypes", (callback) => {
123
+ const { clients } = options || [];
124
+ const reports = [];
125
+ if (_.isEmpty(clients)) {
126
+ return callback(reports);
127
+ }
128
+ clients.forEach((client) => {
129
+ var report = validateGrantTypesForApp(client);
130
+ var name = client.name.concat(` (${client.client_id})`);
131
+ // removed old code
132
+ reports.push({ name: name, report: report });
133
+ });
134
+ return callback(reports);
135
+ });
136
+ }
137
+
138
+ module.exports = checkGrantTypes;
@@ -0,0 +1,118 @@
1
+ /*
2
+ {
3
+ clients: [
4
+ {
5
+ "tenant": "contos0",
6
+ "global": false,
7
+ "is_token_endpoint_ip_header_trusted": false,
8
+ "name": "Default App",
9
+ "is_first_party": true,
10
+ "oidc_conformant": true,
11
+ "sso_disabled": false,
12
+ "cross_origin_auth": false,
13
+ "refresh_token": {
14
+ "expiration_type": "expiring",
15
+ "leeway": 0,
16
+ "token_lifetime": 2592000,
17
+ "idle_token_lifetime": 1296000,
18
+ "infinite_token_lifetime": false,
19
+ "infinite_idle_token_lifetime": false,
20
+ "rotation_type": "rotating"
21
+ },
22
+ "allowed_clients": [],
23
+ "allowed_logout_urls": [
24
+ "http://localhost:3000"
25
+ ],
26
+ "callbacks": [
27
+ "http://localhost:3000"
28
+ ],
29
+ "native_social_login": {
30
+ "apple": {
31
+ "enabled": false
32
+ },
33
+ "facebook": {
34
+ "enabled": false
35
+ }
36
+ },
37
+ "client_id": "client_id",
38
+ "callback_url_template": false,
39
+ "jwt_configuration": {
40
+ "alg": "RS256",
41
+ "lifetime_in_seconds": 36000,
42
+ "secret_encoded": false
43
+ },
44
+ "client_aliases": [],
45
+ "token_endpoint_auth_method": "none",
46
+ "app_type": "spa",
47
+ "grant_types": [
48
+ "authorization_code",
49
+ "implicit",
50
+ "refresh_token"
51
+ ],
52
+ "web_origins": [
53
+ "http://localhost:3000"
54
+ ],
55
+ "custom_login_page_on": true
56
+ }
57
+ ]
58
+ }
59
+ */
60
+ const _ = require("lodash");
61
+ const executeCheck = require("../executeCheck");
62
+ const CONSTANTS = require("../constants");
63
+
64
+ function checkJWTSignAlg(options) {
65
+ return executeCheck("checkJWTSignAlg", (callback) => {
66
+ const { clients } = options;
67
+ const reports = [];
68
+ if (_.isEmpty(clients)) {
69
+ return callback(reports);
70
+ }
71
+ // If a client does not have a jwtConfiguration, it will use the default configuration of RS256
72
+ // Clients created via API will have an empty jwtConfiguration
73
+ clients.forEach((client) => {
74
+ var report = [];
75
+ if (!client.jwt_configuration) {
76
+ report.push({
77
+ name: client.client_id
78
+ ? client.name.concat(` (${client.client_id})`)
79
+ : client.name,
80
+ client_id: client.client_id || client.name,
81
+ field: "missing_jwt_alg",
82
+ status: CONSTANTS.SUCCESS,
83
+ value: "RS256",
84
+ is_first_party: client.is_first_party
85
+ });
86
+ reports.push({ name: client.name, report: report });
87
+ return;
88
+ }
89
+ if (client.jwt_configuration.alg !== "HS256") {
90
+ report.push({
91
+ name: client.client_id
92
+ ? client.name.concat(` (${client.client_id})`)
93
+ : client.name,
94
+ client_id: client.client_id || client.name,
95
+ field: "using_asymmetric_alg",
96
+ status: CONSTANTS.SUCCESS,
97
+ value: client.jwt_configuration.alg,
98
+ is_first_party: client.is_first_party
99
+ });
100
+ } else {
101
+ report.push({
102
+ name: client.client_id
103
+ ? client.name.concat(` (${client.client_id})`)
104
+ : client.name,
105
+ client_id: client.client_id || client.name,
106
+ field: "not_using_asymmetric_alg",
107
+ status: CONSTANTS.FAIL,
108
+ value: client.jwt_configuration.alg,
109
+ is_first_party: client.is_first_party
110
+ });
111
+ }
112
+ reports.push({ name: client.name.concat(` (${client.client_id})`), report: report });
113
+ });
114
+ return callback(reports);
115
+ });
116
+ }
117
+
118
+ module.exports = checkJWTSignAlg;
@@ -0,0 +1,108 @@
1
+ /*
2
+ {
3
+ clients: [
4
+ {
5
+ "tenant": "contos0",
6
+ "global": false,
7
+ "is_token_endpoint_ip_header_trusted": false,
8
+ "name": "Default App",
9
+ "is_first_party": true,
10
+ "oidc_conformant": true,
11
+ "sso_disabled": false,
12
+ "cross_origin_auth": false,
13
+ "refresh_token": {
14
+ "expiration_type": "expiring",
15
+ "leeway": 0,
16
+ "token_lifetime": 2592000,
17
+ "idle_token_lifetime": 1296000,
18
+ "infinite_token_lifetime": false,
19
+ "infinite_idle_token_lifetime": false,
20
+ "rotation_type": "rotating"
21
+ },
22
+ "allowed_clients": [],
23
+ "allowed_logout_urls": [
24
+ "http://localhost:3000"
25
+ ],
26
+ "callbacks": [
27
+ "http://localhost:3000"
28
+ ],
29
+ "native_social_login": {
30
+ "apple": {
31
+ "enabled": false
32
+ },
33
+ "facebook": {
34
+ "enabled": false
35
+ }
36
+ },
37
+ "client_id": "client_id",
38
+ "callback_url_template": false,
39
+ "jwt_configuration": {
40
+ "alg": "RS256",
41
+ "lifetime_in_seconds": 36000,
42
+ "secret_encoded": false
43
+ },
44
+ "client_aliases": [],
45
+ "token_endpoint_auth_method": "none",
46
+ "app_type": "spa",
47
+ "grant_types": [
48
+ "authorization_code",
49
+ "implicit",
50
+ "refresh_token"
51
+ ],
52
+ "web_origins": [
53
+ "http://localhost:3000"
54
+ ],
55
+ "custom_login_page_on": true
56
+ }
57
+ ]
58
+ }
59
+ */
60
+ const _ = require("lodash");
61
+ const executeCheck = require("../executeCheck");
62
+ const CONSTANTS = require("../constants");
63
+
64
+ function validateRTGrantTypesForApp(app) {
65
+ const enabledGrantTypes = app.grant_types || [];
66
+ const appType = app.app_type || "unknown";
67
+ const report = [];
68
+
69
+ // Define expected grant types based on appType (OAuth2.0 best practices)
70
+ switch (appType) {
71
+ case "regular_web":
72
+ case "spa":
73
+ case "native":
74
+ break;
75
+ default:
76
+ break;
77
+ }
78
+ if (enabledGrantTypes.includes('refresh_token') && app?.refresh_token?.rotation_type && app?.refresh_token?.rotation_type !== 'rotating') {
79
+ // check refresh token configuration
80
+ report.push({
81
+ name: app.client_id ? app.name.concat(` (${app.client_id})`) : app.name,
82
+ client_id: app.client_id,
83
+ field: "use_rotating_refresh_token",
84
+ status: app?.refresh_token?.expiration_type !== 'expiring' ? CONSTANTS.FAIL : CONSTANTS.SUCCESS,
85
+ value: app.refresh_token.rotation_type,
86
+ is_first_party: app.is_first_party
87
+ });
88
+ }
89
+ return report;
90
+ }
91
+
92
+ function checkRefreshToken(options) {
93
+ return executeCheck("checkRefreshToken", (callback) => {
94
+ const { clients } = options || [];
95
+ const reports = [];
96
+ if (_.isEmpty(clients)) {
97
+ return callback(reports);
98
+ }
99
+ clients.forEach((client) => {
100
+ var report = validateRTGrantTypesForApp(client);
101
+ var name = client.name.concat(` (${client.client_id})`);
102
+ reports.push({ name: name, report: report });
103
+ });
104
+ return callback(reports);
105
+ });
106
+ }
107
+
108
+ module.exports = checkRefreshToken;
@@ -0,0 +1,55 @@
1
+ const executeCheck = require("../executeCheck");
2
+ const CONSTANTS = require("../constants");
3
+ // Function to check web origin URLs for insecure patterns (localhost, http, 127.0.0.1)
4
+ function checkURLsForApp(app) {
5
+ const web_origins = app.web_origins || [];
6
+ const report = [];
7
+ const insecurePatterns = ["localhost", "http://", "127.0.0.1"];
8
+ if (
9
+ web_origins.length === 0 &&
10
+ (app.app_type !== "non_interactive" || app.app_type !== "native")
11
+ ) {
12
+ return report;
13
+ }
14
+ web_origins.forEach((url) => {
15
+ const subArr = insecurePatterns.filter((str) => url.includes(str));
16
+ if (subArr.length > 0) {
17
+ report.push({
18
+ name: app.client_id ? app.name.concat(` (${app.client_id})`) : app.name,
19
+ client_id: app.client_id || app.name,
20
+ field: "insecure_web_origins_urls",
21
+ value: url,
22
+ status: CONSTANTS.FAIL,
23
+ app_type: app.app_type,
24
+ is_first_party: app.is_first_party
25
+ });
26
+ }
27
+ });
28
+ return report;
29
+ }
30
+
31
+ function checkWebOrigins(options) {
32
+ return executeCheck("checkWebOrigins", (callback) => {
33
+ const { clients } = options;
34
+ const reports = [];
35
+
36
+ clients.forEach((client) => {
37
+ var report = checkURLsForApp(client);
38
+ if (report.length === 0) {
39
+ report.push({
40
+ name: client.name,
41
+ client_id: client.client_id || client.name,
42
+ field: "secure_web_origins",
43
+ status: CONSTANTS.SUCCESS,
44
+ value: client.web_origins ? client.web_origins.join(", ") : "",
45
+ app_type: client.app_type || "unknown",
46
+ is_first_party: client.is_first_party
47
+ });
48
+ }
49
+ reports.push({ name: client.name.concat(` (${client.client_id})`), report: report });
50
+ });
51
+ return callback(reports);
52
+ });
53
+ }
54
+
55
+ module.exports = checkWebOrigins;
@@ -0,0 +1,63 @@
1
+ module.exports = {
2
+ INSECURE_URL_PATTERN: ["localhost", "http://", "127.0.0.1"],
3
+ FAIL: "red",
4
+ SUCCESS: "green",
5
+ INFO: "blue",
6
+ WARN: "yellow",
7
+ MULTIFACTOR_POLICY: {
8
+ empty: "Never",
9
+ "all-applications": "Always",
10
+ "confidence-score": "Use Adaptive MFA",
11
+ },
12
+ MINIMUM_NODE_VERSION: 18,
13
+ DEFAULT_IDLE_SESSION_LIFETIME: "72h",
14
+ DEFAULT_SESSION_LIFETIME: "168h",
15
+ DEFAULT_SESSION_COOKIE_MODE: "persistent",
16
+ CUSTOM_DOMAIN_SCOPE: "read:custom_domains",
17
+ CLIENTS_SCOPE: "read:clients",
18
+ DBCONNECTIONS_SCOPE: "read:connections",
19
+ ATTACK_PROTECTION_SCOPE: "read:attack_protection",
20
+ TENANT_SETTINGS_SCOPE: "read:tenant_settings",
21
+ EMAIL_PROVIDER_SCOPE: "read:email_provider",
22
+ EMAIL_TEMPLATES_SCOPE: "read:email_templates",
23
+ MFA_POLICIES_SCOPE: "read:mfa_policies",
24
+ MFA_FACTORS_SCOPE: "read:guardian_factors",
25
+ REQUIRED_SCOPES:
26
+ "read:tenant_settings read:custom_domains read:prompts read:clients read:connections read:connections_options read:resource_servers read:client_grants read:roles read:branding read:email_provider read:email_templates read:phone_providers read:phone_templates read:shields read:attack_protection read:self_service_profiles read:guardian_factors read:mfa_policies read:actions read:log_streams read:logs read:network_acls read:event_streams",
27
+ LOG_TYPES: [
28
+ "s",
29
+ "f",
30
+ "fs",
31
+ "ss",
32
+ "fu",
33
+ "fp",
34
+ "scoa",
35
+ "fcoa",
36
+ "sepft",
37
+ "fepft",
38
+ ],
39
+ EMAIL_TEMPLATES_NAMES: {
40
+ verify_email: "Verification Email (Link)",
41
+ verify_email_by_code: "Verification Email (Code)",
42
+ welcome_email: "Welcome Email",
43
+ enrollment_email: "Enroll in Multifactor Authentication",
44
+ reset_email: "Change Password (Link)",
45
+ reset_email_by_code: "Change Password (Code)",
46
+ blocked_account: "Blocked Account Email",
47
+ stolen_credentials: "Password Breach Alert",
48
+ mfa_oob_code: "Verification Code for Email MFA",
49
+ user_invitation: "User Invitation",
50
+ },
51
+ EMAIL_TEMPLATES_TYPES: [
52
+ "verify_email",
53
+ "verify_email_by_code",
54
+ "welcome_email",
55
+ "enrollment_email",
56
+ "reset_email",
57
+ "reset_email_by_code",
58
+ "blocked_account",
59
+ "stolen_credentials",
60
+ "mfa_oob_code",
61
+ "user_invitation",
62
+ ]
63
+ };