@blazedpath/commons 0.0.4

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 (224) hide show
  1. package/README.md +3 -0
  2. package/blz-base/health/index.js +215 -0
  3. package/blz-base/index.js +1466 -0
  4. package/blz-cache/LruCache.js +44 -0
  5. package/blz-cache/index.js +29 -0
  6. package/blz-config/index.js +434 -0
  7. package/blz-core/index.js +364 -0
  8. package/blz-cryptography/index.js +54 -0
  9. package/blz-datetimes/index.js +356 -0
  10. package/blz-file/example.dat +2545 -0
  11. package/blz-file/fileService.js +205 -0
  12. package/blz-file/index.js +94 -0
  13. package/blz-file/index.test.js +31 -0
  14. package/blz-file/lab.js +33 -0
  15. package/blz-hazelcast/index.js +189 -0
  16. package/blz-hazelcast/lib/credentials.js +25 -0
  17. package/blz-hazelcast/lib/credentialsFactory.js +12 -0
  18. package/blz-hazelcast/lib/hazelcastCache.js +234 -0
  19. package/blz-iterable/index.js +446 -0
  20. package/blz-json-schema/index.js +11 -0
  21. package/blz-jwt/index.js +121 -0
  22. package/blz-kafka/index.js +522 -0
  23. package/blz-math/index.js +131 -0
  24. package/blz-mongodb/index.js +326 -0
  25. package/blz-rds/__test__/scape.test.js +58 -0
  26. package/blz-rds/blz-rds-executor.js +578 -0
  27. package/blz-rds/blz-rds-helper.js +310 -0
  28. package/blz-rds/commands/core/add.js +13 -0
  29. package/blz-rds/commands/core/and.js +18 -0
  30. package/blz-rds/commands/core/asc.js +10 -0
  31. package/blz-rds/commands/core/avg.js +10 -0
  32. package/blz-rds/commands/core/column-ref.js +8 -0
  33. package/blz-rds/commands/core/count-distinct.js +10 -0
  34. package/blz-rds/commands/core/count.js +10 -0
  35. package/blz-rds/commands/core/decimal.js +8 -0
  36. package/blz-rds/commands/core/desc.js +10 -0
  37. package/blz-rds/commands/core/distinct.js +10 -0
  38. package/blz-rds/commands/core/divide.js +11 -0
  39. package/blz-rds/commands/core/embedded-exists.js +17 -0
  40. package/blz-rds/commands/core/embedded-select.js +17 -0
  41. package/blz-rds/commands/core/equals.js +9 -0
  42. package/blz-rds/commands/core/false.js +8 -0
  43. package/blz-rds/commands/core/greater-or-equal.js +9 -0
  44. package/blz-rds/commands/core/greater.js +9 -0
  45. package/blz-rds/commands/core/in.js +9 -0
  46. package/blz-rds/commands/core/integer.js +8 -0
  47. package/blz-rds/commands/core/is-not-null.js +11 -0
  48. package/blz-rds/commands/core/is-null-or-value.js +10 -0
  49. package/blz-rds/commands/core/is-null.js +11 -0
  50. package/blz-rds/commands/core/less-or-equal.js +9 -0
  51. package/blz-rds/commands/core/less-unary.js +12 -0
  52. package/blz-rds/commands/core/less.js +9 -0
  53. package/blz-rds/commands/core/like.js +12 -0
  54. package/blz-rds/commands/core/max.js +10 -0
  55. package/blz-rds/commands/core/min.js +10 -0
  56. package/blz-rds/commands/core/multiply.js +13 -0
  57. package/blz-rds/commands/core/not-equals.js +9 -0
  58. package/blz-rds/commands/core/not-in.js +9 -0
  59. package/blz-rds/commands/core/not.js +13 -0
  60. package/blz-rds/commands/core/null.js +8 -0
  61. package/blz-rds/commands/core/nvl.js +11 -0
  62. package/blz-rds/commands/core/or.js +13 -0
  63. package/blz-rds/commands/core/parameter.js +34 -0
  64. package/blz-rds/commands/core/remainder.js +16 -0
  65. package/blz-rds/commands/core/string.js +8 -0
  66. package/blz-rds/commands/core/subtract.js +13 -0
  67. package/blz-rds/commands/core/sum.js +10 -0
  68. package/blz-rds/commands/core/true.js +8 -0
  69. package/blz-rds/commands/core/tuple.js +13 -0
  70. package/blz-rds/commands/datetimes/add-days.js +11 -0
  71. package/blz-rds/commands/datetimes/add-hours.js +11 -0
  72. package/blz-rds/commands/datetimes/add-milliseconds.js +11 -0
  73. package/blz-rds/commands/datetimes/add-minutes.js +11 -0
  74. package/blz-rds/commands/datetimes/add-months.js +11 -0
  75. package/blz-rds/commands/datetimes/add-seconds.js +11 -0
  76. package/blz-rds/commands/datetimes/add-years.js +11 -0
  77. package/blz-rds/commands/datetimes/date-diff.js +11 -0
  78. package/blz-rds/commands/datetimes/date.js +12 -0
  79. package/blz-rds/commands/datetimes/datetime-diff.js +11 -0
  80. package/blz-rds/commands/datetimes/datetime.js +15 -0
  81. package/blz-rds/commands/datetimes/day.js +10 -0
  82. package/blz-rds/commands/datetimes/hour.js +10 -0
  83. package/blz-rds/commands/datetimes/millisecond.js +10 -0
  84. package/blz-rds/commands/datetimes/minute.js +10 -0
  85. package/blz-rds/commands/datetimes/month-text.js +10 -0
  86. package/blz-rds/commands/datetimes/month.js +10 -0
  87. package/blz-rds/commands/datetimes/now.js +9 -0
  88. package/blz-rds/commands/datetimes/second.js +10 -0
  89. package/blz-rds/commands/datetimes/subtract-days.js +11 -0
  90. package/blz-rds/commands/datetimes/subtract-hours.js +11 -0
  91. package/blz-rds/commands/datetimes/subtract-milliseconds.js +11 -0
  92. package/blz-rds/commands/datetimes/subtract-minutes.js +11 -0
  93. package/blz-rds/commands/datetimes/subtract-seconds.js +11 -0
  94. package/blz-rds/commands/datetimes/time-diff.js +11 -0
  95. package/blz-rds/commands/datetimes/time.js +13 -0
  96. package/blz-rds/commands/datetimes/today.js +9 -0
  97. package/blz-rds/commands/datetimes/week-day-text.js +10 -0
  98. package/blz-rds/commands/datetimes/week-day.js +10 -0
  99. package/blz-rds/commands/datetimes/week.js +10 -0
  100. package/blz-rds/commands/datetimes/year.js +10 -0
  101. package/blz-rds/commands/math/abs.js +10 -0
  102. package/blz-rds/commands/math/acos.js +10 -0
  103. package/blz-rds/commands/math/asin.js +10 -0
  104. package/blz-rds/commands/math/atan.js +10 -0
  105. package/blz-rds/commands/math/atan2.js +11 -0
  106. package/blz-rds/commands/math/ceil.js +10 -0
  107. package/blz-rds/commands/math/cos.js +10 -0
  108. package/blz-rds/commands/math/cosh.js +10 -0
  109. package/blz-rds/commands/math/exp.js +10 -0
  110. package/blz-rds/commands/math/floor.js +10 -0
  111. package/blz-rds/commands/math/log.js +18 -0
  112. package/blz-rds/commands/math/log10.js +10 -0
  113. package/blz-rds/commands/math/pow.js +11 -0
  114. package/blz-rds/commands/math/random.js +9 -0
  115. package/blz-rds/commands/math/round.js +18 -0
  116. package/blz-rds/commands/math/sign.js +10 -0
  117. package/blz-rds/commands/math/sin.js +10 -0
  118. package/blz-rds/commands/math/sinh.js +10 -0
  119. package/blz-rds/commands/math/sqrt.js +10 -0
  120. package/blz-rds/commands/math/tan.js +10 -0
  121. package/blz-rds/commands/math/tanh.js +10 -0
  122. package/blz-rds/commands/math/trunc.js +18 -0
  123. package/blz-rds/commands/strings/concat.js +20 -0
  124. package/blz-rds/commands/strings/contains.js +12 -0
  125. package/blz-rds/commands/strings/ends-with.js +12 -0
  126. package/blz-rds/commands/strings/index-of.js +11 -0
  127. package/blz-rds/commands/strings/is-null-or-empty.js +11 -0
  128. package/blz-rds/commands/strings/is-null-or-white-space.js +11 -0
  129. package/blz-rds/commands/strings/join.js +22 -0
  130. package/blz-rds/commands/strings/last-index-of.js +11 -0
  131. package/blz-rds/commands/strings/length.js +10 -0
  132. package/blz-rds/commands/strings/pad-left.js +20 -0
  133. package/blz-rds/commands/strings/pad-right.js +20 -0
  134. package/blz-rds/commands/strings/replace.js +12 -0
  135. package/blz-rds/commands/strings/starts-with.js +12 -0
  136. package/blz-rds/commands/strings/substring.js +12 -0
  137. package/blz-rds/commands/strings/to-lower.js +10 -0
  138. package/blz-rds/commands/strings/to-upper.js +10 -0
  139. package/blz-rds/commands/strings/trim-end.js +10 -0
  140. package/blz-rds/commands/strings/trim-start.js +10 -0
  141. package/blz-rds/commands/strings/trim.js +10 -0
  142. package/blz-rds/index.js +744 -0
  143. package/blz-rds-mysql/base.js +857 -0
  144. package/blz-rds-mysql/connection-manager.js +129 -0
  145. package/blz-rds-mysql/execute-bulk-insert.js +35 -0
  146. package/blz-rds-mysql/execute-bulk-merge.js +45 -0
  147. package/blz-rds-mysql/execute-non-query.js +34 -0
  148. package/blz-rds-mysql/execute-query.js +50 -0
  149. package/blz-rds-mysql/index.js +41 -0
  150. package/blz-rds-mysql/stored-procedure.js +207 -0
  151. package/blz-rds-mysql/syntaxis.json +114 -0
  152. package/blz-rds-mysqlx/base.js +846 -0
  153. package/blz-rds-mysqlx/connection-manager.js +141 -0
  154. package/blz-rds-mysqlx/execute-bulk-insert.js +35 -0
  155. package/blz-rds-mysqlx/execute-bulk-merge.js +45 -0
  156. package/blz-rds-mysqlx/execute-non-query.js +29 -0
  157. package/blz-rds-mysqlx/execute-query.js +39 -0
  158. package/blz-rds-mysqlx/index.js +41 -0
  159. package/blz-rds-mysqlx/stored-procedure.js +179 -0
  160. package/blz-rds-mysqlx/syntaxis.json +105 -0
  161. package/blz-rds-oracle/index.js +540 -0
  162. package/blz-rds-oracle/syntaxis.json +112 -0
  163. package/blz-rds-postgres/base.js +861 -0
  164. package/blz-rds-postgres/connection-manager.js +225 -0
  165. package/blz-rds-postgres/execute-bulk-insert.js +81 -0
  166. package/blz-rds-postgres/execute-bulk-merge.js +93 -0
  167. package/blz-rds-postgres/execute-non-query.js +23 -0
  168. package/blz-rds-postgres/execute-query.js +37 -0
  169. package/blz-rds-postgres/index.js +41 -0
  170. package/blz-rds-postgres/result-set.js +51 -0
  171. package/blz-rds-postgres/stored-procedure.js +116 -0
  172. package/blz-rds-postgres/syntaxis.json +114 -0
  173. package/blz-redis/index.js +217 -0
  174. package/blz-redis/lib/redisCache.js +265 -0
  175. package/blz-regex/index.js +25 -0
  176. package/blz-security/.eslintrc.js +15 -0
  177. package/blz-security/__test__/AuthorizationKpn.yaml +1043 -0
  178. package/blz-security/__test__/FinancingSetting.yaml +177 -0
  179. package/blz-security/__test__/KpnConfigPortal.yaml +330 -0
  180. package/blz-security/__test__/OrderManagement.yaml +5190 -0
  181. package/blz-security/__test__/Security.yaml +128 -0
  182. package/blz-security/__test__/autorization.test.js +105 -0
  183. package/blz-security/__test__/orderManagement.test.js +26 -0
  184. package/blz-security/__test__/secureUrl.test.js +79 -0
  185. package/blz-security/__test__/solveMergeRule.test.js +109 -0
  186. package/blz-security/__test__/sqlInjectionGuard.test.js +203 -0
  187. package/blz-security/__test__/xssGuard.test.js +204 -0
  188. package/blz-security/authorizationService.js +536 -0
  189. package/blz-security/config/global.js +8 -0
  190. package/blz-security/config/welcome +8 -0
  191. package/blz-security/doc/README.md +75 -0
  192. package/blz-security/filescanner/index.js +46 -0
  193. package/blz-security/helpers/consts.js +229 -0
  194. package/blz-security/helpers/utils.js +267 -0
  195. package/blz-security/implementations/cache.js +90 -0
  196. package/blz-security/implementations/oidc.js +404 -0
  197. package/blz-security/implementations/pkceCacheStore.js +23 -0
  198. package/blz-security/implementations/saml.js +10 -0
  199. package/blz-security/implementations/uma.js +63 -0
  200. package/blz-security/implementations/webAuthn.js +9 -0
  201. package/blz-security/implementations/wstg.js +72 -0
  202. package/blz-security/index.js +77 -0
  203. package/blz-security/lab/index.js +27 -0
  204. package/blz-security/middleware/HapiServerAzureAd.js +641 -0
  205. package/blz-security/middleware/HapiServerKeycloak.js +840 -0
  206. package/blz-security/middleware/HapiServerSimToken.js +247 -0
  207. package/blz-security/middleware/hapi.js +515 -0
  208. package/blz-security/middleware/hapiServer.js +974 -0
  209. package/blz-security/navigationMemoryRepository.js +15 -0
  210. package/blz-security/navigationMongoDbRepository.js +73 -0
  211. package/blz-security/secureUrlService.js +47 -0
  212. package/blz-security/securityService.js +409 -0
  213. package/blz-security/sqlInjectionGuard.js +162 -0
  214. package/blz-security/templates/forbidden.html +0 -0
  215. package/blz-security/templates/session-iframe-azure-ad.html +7 -0
  216. package/blz-security/templates/session-iframe.html +73 -0
  217. package/blz-security/templates/unauthorized.html +1 -0
  218. package/blz-security/xssGuard.js +87 -0
  219. package/blz-strings/index.js +167 -0
  220. package/blz-uuid/index.js +7 -0
  221. package/blz-yaml/index.js +19 -0
  222. package/index.js +84 -0
  223. package/package.json +97 -0
  224. package/process-managers/index.js +422 -0
@@ -0,0 +1,15 @@
1
+ module.exports = class NavigationMemoryRepository {
2
+ constructor() {
3
+ this._navigation = [];
4
+ }
5
+
6
+ async push(navigation) {
7
+ this._navigation.push(navigation);
8
+ }
9
+
10
+ async get () {
11
+ return structuredClone(this._navigation)
12
+ }
13
+
14
+ }
15
+
@@ -0,0 +1,73 @@
1
+ const { MongoClient } = require("mongodb");
2
+ const fs = require('fs');
3
+
4
+ module.exports = class NavigationMongoDbRepository {
5
+ constructor(url, database, collectionName,certificate) {
6
+ if (certificate) {
7
+ const tempFile = '/tmp/mongo-cert.pem';
8
+ fs.writeFileSync(tempFile, certificate);
9
+ this.client = new MongoClient(url,{ tls: true,tlsCAFile: tempFile})
10
+ } else {
11
+ this.client = new MongoClient(url);
12
+ }
13
+ this.database = database;
14
+ this.collectionName = collectionName;
15
+ this.connected = false;
16
+ }
17
+
18
+ async connect() {
19
+ if (!this.connected) {
20
+ try {
21
+ await this.client.connect();
22
+ this.db = this.client.db(this.database);
23
+ this.collection = this.db.collection(this.collectionName);
24
+ this.connected = true;
25
+ console.log("Navigation info Connected to MongoDB.");
26
+ } catch (error) {
27
+ console.error("Failed Navigation info to connect to MongoDB:", error);
28
+ throw error;
29
+ }
30
+ }
31
+ }
32
+
33
+ async close() {
34
+ if (this.connected) {
35
+ try {
36
+ await this.client.close();
37
+ this.connected = false;
38
+ console.log("Connection to MongoDB closed.");
39
+ } catch (error) {
40
+ console.error("Failed to close MongoDB connection:", error);
41
+ throw error;
42
+ }
43
+ }
44
+ }
45
+
46
+ async push(navigation) {
47
+ if (!this.connected) {
48
+ await this.connect();
49
+ }
50
+
51
+ try {
52
+ const result = await this.collection.insertOne(navigation);
53
+ return result.insertedId.toString();
54
+ } catch (error) {
55
+ console.error("Failed to insert navigation:", error);
56
+ throw error;
57
+ }
58
+ }
59
+
60
+ async get () {
61
+ if (!this.connected) {
62
+ await this.connect();
63
+ }
64
+
65
+ try {
66
+ const cursor = this.collection.find({});
67
+ return await cursor.toArray();
68
+ } catch (error) {
69
+ console.error("Failed to get navigation:", error);
70
+ throw error;
71
+ }
72
+ }
73
+ };
@@ -0,0 +1,47 @@
1
+ const { Exception, isBase64 } = require('./helpers/utils')
2
+ const CryptoJS = require('crypto-js');
3
+
4
+ module.exports = class SecureUrlService {
5
+ constructor(logger = console) {
6
+ this.logger = logger;
7
+ }
8
+
9
+ validate(url, token, _session_key, timeoutMs) {
10
+ const path = decodeURIComponent(url.split('?')[0]);
11
+ if (!token) {
12
+ this.logger.error(`Token parameter 'tt' is missing in the URL. path:${path}`)
13
+ throw new Exception("Token parameter 'tt' is missing in the URL.", 'SecureUrlError', 404);
14
+ }
15
+ const session_key = isBase64(_session_key)?atob(_session_key):_session_key
16
+ const key = `${session_key}${btoa(path)}`;
17
+ const bytes = CryptoJS.AES.decrypt(decodeURIComponent(token), key);
18
+ const requestTimeStr = bytes.toString(CryptoJS.enc.Utf8);
19
+ if (!requestTimeStr) {
20
+ this.logger.error(`Token decryption failed or is invalid. token:${token} path:${path} session: ${session_key}`)
21
+ throw new Exception("Token decryption failed or is invalid.", 'SecureUrlError', 404);
22
+ }
23
+ let requestTime
24
+ try {
25
+ requestTime = parseInt(JSON.parse(requestTimeStr));
26
+ } catch (e) {
27
+ this.logger.error(`Malformed token content. path:${path} error: ${e.message}`)
28
+ throw new Exception("Malformed token content.", 'SecureUrlError', 400);
29
+ }
30
+ const timeout = requestTime + timeoutMs
31
+ const time = Date.now()
32
+ const isValid = time < timeout && requestTime < time;
33
+ if (!isValid) {
34
+ this.logger.error(`The token has expired. path:${path} timeout:${timeout} time: ${time}`)
35
+ throw new Exception("The token has expired.", 'SecureUrlError', 408);
36
+ }
37
+ }
38
+
39
+ createToken(url, _session_key){
40
+ const path = url.split('?')[0];
41
+ const session_key = isBase64(_session_key)?atob(_session_key):_session_key
42
+ const key = `${session_key}${btoa(decodeURIComponent(path))}`;
43
+ const getNow = () => Function('"use strict";return (' + atob("bmV3IERhdGUoKS5nZXRUaW1lKCk=") + ')')();
44
+ const token = CryptoJS.AES.encrypt((getNow()).toString(), key).toString();
45
+ return encodeURIComponent(token);
46
+ }
47
+ }
@@ -0,0 +1,409 @@
1
+ const { Hapi } = require('./middleware/hapi')
2
+ const { Oidc } = require('./implementations/oidc')
3
+ const { HapiServerSimToken } = require('./middleware/HapiServerSimToken');
4
+ const { HapiServerKeycloak } = require('./middleware/HapiServerKeycloak');
5
+ const { HapiServerAzureAd } = require('./middleware/HapiServerAzureAd');
6
+ const { RedisCache, LruCache } = require('./implementations/cache')
7
+ const { Exception, getMappingValues } = require('./helpers/utils')
8
+ const Jsonwebtoken = require('jsonwebtoken')
9
+ const micromatch = require('micromatch');
10
+ module.exports = class SecurityService {
11
+ constructor(authorizationService, sqlInjectionGuard, xssGuard, navigationRepository,secureUrlService, logger) {
12
+ this.authorizationService = authorizationService
13
+ this.sqlInjectionGuard = sqlInjectionGuard
14
+ this.xssGuard = xssGuard
15
+ this.navigationRepository = navigationRepository
16
+ this.secureUrlService = secureUrlService
17
+ this.logger = logger
18
+ this.cookiesName = null
19
+ this.blzConfig = null
20
+ this.oidc = null
21
+ this.hapi = null
22
+ this.config = null
23
+ this.middleware = null
24
+ this.protected = false
25
+ this.unProtected = []
26
+ this.useHapiServerFullStack = false;
27
+ }
28
+
29
+ async pushNavigation(navigation) {
30
+ if (this.navigationRepository) {
31
+ return this.navigationRepository.push(navigation)
32
+ } else {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ async getNavigation() {
38
+ return this.navigationRepository ? this.navigationRepository.get() : {};
39
+ }
40
+
41
+ setBlzConfig(blzConfig) {
42
+ this.blzConfig = blzConfig
43
+ }
44
+
45
+ // Same signature as your current function
46
+ sanitizeSqlParams(params) {
47
+ return this.sqlInjectionGuard.validateParamList(params);
48
+ }
49
+
50
+ // New helper for full SQL validation
51
+ sanitizeSql(sql) {
52
+ return this.sqlInjectionGuard.validateRawSql(sql);
53
+ }
54
+
55
+ isExcludedFromSanitize(method, path) {
56
+ const raw = process.env.blz_securityExcludeSanitizePaths;
57
+
58
+ if (!raw || !raw.trim()) {
59
+ // No rules defined — sanitize by default
60
+ return false;
61
+ }
62
+
63
+ const rules = raw
64
+ .split(',')
65
+ .map(rule => rule.trim().toLowerCase())
66
+ .filter(Boolean);
67
+
68
+ if (rules.length === 0) {
69
+ // All rules were empty or invalid
70
+ return false;
71
+ }
72
+
73
+ return rules.some(rule => {
74
+ let [ruleMethod, rulePath] = rule.includes(':')
75
+ ? rule.split(':')
76
+ : [null, rule]; // if no method is specified, apply to all methods
77
+
78
+ ruleMethod = ruleMethod?.toLowerCase();
79
+
80
+ // Normalize rulePath to use compatible wildcards
81
+ const normalizedPattern = rulePath
82
+ .replace(/\*\*/g, '**') // double wildcard
83
+ .replace(/\*/g, '*'); // single wildcard
84
+
85
+ return (!ruleMethod || ruleMethod === method.toLowerCase()) &&
86
+ micromatch.isMatch(path.toLowerCase(), normalizedPattern);
87
+ });
88
+ }
89
+
90
+ validateObject(obj) {
91
+ return this.sqlInjectionGuard.validateObject(this.xssGuard.sanitizeObject(obj));
92
+ }
93
+
94
+ validateSqlObject(obj) {
95
+ return this.sqlInjectionGuard.validateObject(obj);
96
+ }
97
+
98
+ initializeCookiesNames() {
99
+ this.cookiesName = {
100
+ ACCESS_TOKEN: this.getCookieName('access_token'),
101
+ SID: this.getCookieName('sid'),
102
+ SESSION_STATE: this.getCookieName('session_state'),
103
+ SESSION: this.getCookieName('session')
104
+ }
105
+ }
106
+
107
+ getRoleProperty() {
108
+ const config = this.blzConfig.getConfig() || {}
109
+ if (config && config.authServer && config.authServer.roleProperty && config.authServer.roleProperty.trim() !== '') {
110
+ return config.authServer.roleProperty
111
+ }
112
+ return 'authorities'
113
+ }
114
+
115
+ getUseTonkenName() {
116
+ return this.config.authServer.useTokenType || 'access_token'
117
+ }
118
+
119
+ async getRoles(request) {
120
+ if (this.useHapiServerFullStack) {
121
+ const token = request.headers.authorization?.replace('Bearer ', ''); // From Authorization header
122
+ // Decode and verify the token
123
+ const decoded = Jsonwebtoken.decode(token);
124
+ const rolePropertyName = this.getRoleProperty()
125
+ return decoded[rolePropertyName] || []
126
+ } else {
127
+ const sessionState = this.getSessionState(request)
128
+ const tokenSet = await this.tokenSet()
129
+ const tokens = await tokenSet.tokens(sessionState)
130
+ const tokenName = this.getUseTonkenName()
131
+ const token = tokens[tokenName]
132
+ const decodeToken = Jsonwebtoken.decode(token)
133
+ const rolePropertyName = this.getRoleProperty()
134
+ return decodeToken[rolePropertyName] || []
135
+ }
136
+ }
137
+
138
+ getCookieName(cookieName = '') {
139
+ const config = this.blzConfig.getConfig() || {}
140
+ const prefix = (config.authServer && config.authServer.sessionCookiesPrefix) || ''
141
+ return prefix + cookieName
142
+ }
143
+
144
+ getCache(config) {
145
+ if (process.env.SECURITY_REDIS_CACHE) {
146
+ return new RedisCache(process.env.SECURITY_REDIS_CACHE)
147
+ } else if (config && config.securityCache) {
148
+ const cnx = config.connections[config.securityCache]
149
+ if (cnx && cnx.type === 'Redis') {
150
+ const connection = `redis://${cnx.user || ''}:${cnx.password}@${cnx.host
151
+ }:${cnx.port || '6379'}/${cnx.db || '0'}`
152
+ return new RedisCache(connection)
153
+ } else {
154
+ return new LruCache()
155
+ }
156
+ } else {
157
+ return new LruCache()
158
+ }
159
+ }
160
+
161
+ // This receives:
162
+ // middlehare: receives the hapiServer instance from the proxy
163
+ // config: the config options
164
+ async protect(middleware, config) {
165
+ if (!middleware) {
166
+ this.logger.error('The middleware context could not be analyzed')
167
+ throw new Exception(
168
+ 'The middleware context could not be analyzed',
169
+ 'MiddlewareError',
170
+ 403
171
+ )
172
+ }
173
+ if (!config || (!config.callee && !config.authServer && !config.accessTokenSimulation)) {
174
+ this.logger.error('Authorization server configuration is mandatory')
175
+ throw new Exception(
176
+ 'Authorization server configuration is mandatory',
177
+ 'ConfigurationError',
178
+ 403
179
+ )
180
+ }
181
+ this.config = config
182
+ this.middleware = middleware
183
+ const cache = this.getCache(this.config)
184
+
185
+ // Choose the hapi server version
186
+ if (this.config.accessTokenSimulation) {
187
+ this.oidc = new Oidc(cache, this.config);
188
+ this.openIdConnect = new Oidc(this.getCache(this.config), this.config);
189
+ this.hapiServer = new HapiServerSimToken(this.openIdConnect, this.cookiesName, cache);
190
+ await this.hapiServer.connect(this, this.middleware, this.config)
191
+ } else if (config.authServer.useHapiServerFullStack) {
192
+ // Use oauth0 with signing and authentication with an external oauth server
193
+ this.useHapiServerFullStack = true;
194
+ this.oidc = new Oidc(cache, this.config);
195
+ await this.protectExperimental(cache);
196
+ this.protected = true
197
+ return;
198
+ } else {
199
+ // legacy oauth0 authentication with local key signing
200
+ this.oidc = new Oidc(cache, this.config);
201
+ this.hapi = new Hapi(this.oidc, this.cookiesName);
202
+ this.protected = true
203
+ if (this.config.queryStringLimit) {
204
+ this.hapi.queryStringLimit = this.config.queryStringLimit
205
+ }
206
+ if (this.config.securityLoginTokenExpToleranceSeconds) {
207
+ this.hapi.securityLoginTokenExpToleranceSeconds = this.config.securityLoginTokenExpToleranceSeconds
208
+ }
209
+ await this.hapi.connect(this, this.middleware, this.config)
210
+ this.protected = true
211
+ }
212
+ }
213
+
214
+ async protectExperimental(cache) {
215
+ //this.openIdConnect = new OpenIdConnect(this.getCache(this.config), this.config);
216
+ if (this.config.authServer.provider !== "ad-azure") {
217
+ this.hapiServer = new HapiServerKeycloak(this.openIdConnect, this.cookiesName, cache);
218
+ } else {
219
+ this.hapiServer = new HapiServerAzureAd(this.openIdConnect, this.cookiesName, cache);
220
+ }
221
+ this.openIdConnect = null
222
+ // heck for options in the config
223
+ if (this.config.queryStringLimit) {
224
+ this.hapiServer.queryStringLimit = this.config.queryStringLimit
225
+ }
226
+ if (this.config.securityLoginTokenExpToleranceSeconds) {
227
+ this.hapiServer.securityLoginTokenExpToleranceSeconds = this.config.securityLoginTokenExpToleranceSeconds
228
+ }
229
+ await this.hapiServer.connect(this, this.middleware, this.config)
230
+ }
231
+
232
+ async tokenSet() {
233
+ if (!this.oidc) {
234
+ this.logger.error('authServer and accessTokenSimulation undefined')
235
+ throw new Error('authServer and accessTokenSimulation undefined')
236
+ }
237
+ return await this.oidc.tokenSet()
238
+ }
239
+
240
+ async getUseToken(sessionState, request) {
241
+ if (this.useHapiServerFullStack) {
242
+ return this.extractTokenhNoDecode(request, this.config.authServer.PublicKey)
243
+ } else if (this.config.accessTokenSimulation) { } else {
244
+ return this.oidc.getUseToken(sessionState);
245
+ }
246
+ }
247
+
248
+ getSessionState(request) {
249
+ const sessionState = request.state[this.cookiesName.SESSION_STATE]
250
+ const session = request.state[this.cookiesName.SESSION]
251
+ if (sessionState) {
252
+ return sessionState;
253
+ } else if (session) {
254
+ return session.id;
255
+ } else {
256
+ this.logger.error("getSessionState: Session cookie doesn't exist.")
257
+ throw new Exception("getSessionState: Session cookie doesn't exist.", 'CookiesError', 404)
258
+ }
259
+ }
260
+
261
+ getSecureUrlSessionKey(request) {
262
+ const session = request.state[this.blzConfig.getConfig()?.parameters?.SecureUrlCookieKey]
263
+ if (session) {
264
+ return session;
265
+ } else {
266
+ this.logger.error("getSecureUrlSessionKey: Session cookie doesn't exist.")
267
+ throw new Exception("getSecureUrlSessionKey: Session cookie doesn't exist.", 'CookiesError', 404)
268
+ }
269
+ }
270
+
271
+ enableSecureUrl() {
272
+ const key = this.blzConfig.getConfig()?.parameters?.SecureUrlCookieKey;
273
+ return !!key && key !== 'none';
274
+ }
275
+
276
+ getSecureUrlCookieKey() {
277
+ if (this.enableSecureUrl()) {
278
+ return this.blzConfig.getConfig()?.parameters?.SecureUrlCookieKey;
279
+ }
280
+ return undefined;
281
+ }
282
+
283
+ validateSecureRequest(request) {
284
+ if (!request) return;
285
+ if (!this.enableSecureUrl()) {
286
+ return
287
+ }
288
+ let _session_key = this.getSecureUrlSessionKey(request);
289
+ const params = new URLSearchParams(request.query);
290
+ const token = params.get('sut');
291
+ const timeoutMs = this.blzConfig.getConfig()?.parameters?.SecureUrlTimeoutMs || 15000;
292
+ this.secureUrlService.validate(request.path,token,_session_key,timeoutMs)
293
+ }
294
+
295
+ async getUserInfo(request) {
296
+ let sourceData = null
297
+ let userInfo = {}
298
+ if (this.useHapiServerFullStack) {
299
+ sourceData = await this.extractAndDecodeToken(request, this.config.authServer.PublicKey)
300
+ return sourceData;
301
+ } else {
302
+ const sessionState = this.getSessionState(request)
303
+ const tokenSet = await this.tokenSet()
304
+ if (this.config.parameters && this.config.parameters.UserInfoSource) {
305
+ const strToken = await tokenSet.tokens(sessionState)
306
+ sourceData = Jsonwebtoken.decode(strToken[this.config.parameters.UserInfoSource])
307
+ } else {
308
+ userInfo = await tokenSet.userInfo(sessionState)
309
+ sourceData = userInfo
310
+ }
311
+ }
312
+
313
+ // Solve mapping form UserInfoMapping parameter
314
+ if (this.config.parameters && this.config.parameters.UserInfoMapping) {
315
+ const mappings = JSON.parse(this.config.parameters.UserInfoMapping)
316
+ const values = getMappingValues(sourceData, mappings)
317
+ return { ...userInfo, ...values }
318
+ }
319
+ return userInfo
320
+ }
321
+ async extractAndDecodeToken(request, secretOrPublicKey) {
322
+ const authorization = request.headers.authorization;
323
+
324
+ if (!authorization) {
325
+ this.logger.error('Authorization header is missing')
326
+ throw new Error('Authorization header is missing');
327
+ }
328
+ const [scheme, token] = authorization.split(' ');
329
+
330
+ if ((scheme !== 'Bearer' && scheme !== 'bearer') || !token) {
331
+ this.logger.error('Authorization header must be in the format: Bearer <token>')
332
+ throw new Error('Authorization header must be in the format: Bearer <token>');
333
+ }
334
+ if (this.hapiServer.authServerConfig.authServer.provider !== "ad-azure") {
335
+ const { artifacts } = request.auth;
336
+ secretOrPublicKey = await this.hapiServer.publicKeyFetch(artifacts);
337
+ }
338
+
339
+ try {
340
+ // Decode and verify the JWT token
341
+ //const decoded = Jsonwebtoken.decode(token, secretOrPublicKey);
342
+ const decoded = Jsonwebtoken.decode(token);
343
+ return decoded;
344
+ } catch (err) {
345
+ this.logger.error(`Failed to decode token: ${err.message}`)
346
+ throw new Error(`Failed to decode token: ${err.message}`);
347
+ }
348
+ }
349
+ async extractTokenhNoDecode(request) {
350
+ const authorization = request.headers.authorization;
351
+
352
+ if (!authorization) {
353
+ this.logger.error('Authorization header is missing')
354
+ throw new Error('Authorization header is missing');
355
+ }
356
+ const [scheme, rawToken] = authorization.split(' ');
357
+
358
+ if ((scheme !== 'Bearer' && scheme !== 'bearer') || !rawToken) {
359
+ this.logger.error('Authorization header must be in the format: Bearer <token>')
360
+ throw new Error('Authorization header must be in the format: Bearer <token>');
361
+ }
362
+ return rawToken
363
+ }
364
+
365
+ importSecurityConfig(config) {
366
+ this.authorizationService.importSecurityConfig(config)
367
+ }
368
+
369
+ async getFrontendSecurityRules(request) {
370
+ if (!this.protected) {
371
+ this.logger.error('Cannot get the security rules if the application is not using JWt.')
372
+ throw new Exception('Cannot get the security rules if the application is not using JWt.', 'SecurityRulesError', 500)
373
+ }
374
+ const domains = request.headers.domains ? request.headers.domains.split(',') : []
375
+ const roles = await this.getRoles(request)
376
+ const securityRules = this.authorizationService.getFrontendSecurityRules(roles, domains)
377
+ return securityRules
378
+ }
379
+
380
+ async getPermissions() {
381
+ return this.authorizationService.getPermissions()
382
+ }
383
+
384
+ async authorized(request) {
385
+ if (!this.protected) {
386
+ return true
387
+ }
388
+ let roles = null;
389
+ if (this.useHapiServerFullStack) {
390
+ // Token decoded
391
+ const userInfo = await this.getUserInfo(request);
392
+ roles = userInfo[this.getRoleProperty()]
393
+ } else {
394
+ roles = await this.getRoles(request)
395
+ }
396
+ const result = this.authorizationService.authorized(request.path, request.method, roles)
397
+ if (result !== null && result !== undefined) {
398
+ return result
399
+ }
400
+ if (this.config.activateTraceApiMethod && !this.unProtected.some((item) => item.path === request.path && item.method === request.method)) {
401
+ this.unProtected.push({ path: request.path, method: request.method })
402
+ }
403
+ return true
404
+ }
405
+
406
+ logUnProtected() {
407
+ this.logger.info('unprotected: ' + JSON.stringify(this.unProtected))
408
+ }
409
+ }