perimeterx-js-core 0.7.0 → 0.8.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 (216) hide show
  1. package/lib/action/utils.js +1 -1
  2. package/lib/activities/HttpActivityClient.d.ts +5 -5
  3. package/lib/activities/HttpActivityClient.js +28 -39
  4. package/lib/activities/HttpBatchedActivityClient.d.ts +2 -2
  5. package/lib/activities/HttpBatchedActivityClient.js +19 -32
  6. package/lib/activities/model/AsyncActivity.d.ts +14 -0
  7. package/lib/activities/model/{ActivityDetails.d.ts → AsyncActivityDetails.d.ts} +6 -23
  8. package/lib/activities/model/CommonActivityDetails.d.ts +40 -0
  9. package/lib/activities/model/CommonActivityDetails.js +1 -0
  10. package/lib/activities/model/HeaderEntry.d.ts +4 -0
  11. package/lib/activities/model/HeaderEntry.js +1 -0
  12. package/lib/activities/model/index.d.ts +4 -2
  13. package/lib/activities/model/index.js +4 -2
  14. package/lib/activities/utils.d.ts +6071 -9
  15. package/lib/activities/utils.js +111 -35
  16. package/lib/additional_activity_handler/AdditionalActivityHandler.d.ts +1 -1
  17. package/lib/additional_activity_handler/AdditionalActivityHandlerUtils.js +4 -12
  18. package/lib/config/ConfigurationParams.d.ts +2 -1
  19. package/lib/config/DefaultConfigurations.js +1 -0
  20. package/lib/config/IConfiguration.d.ts +5 -1
  21. package/lib/config/StaticConfigurationBase.d.ts +2 -1
  22. package/lib/config/StaticConfigurationBase.js +6 -1
  23. package/lib/context/DefaultContext.d.ts +1 -1
  24. package/lib/context/DefaultContext.js +40 -8
  25. package/lib/context/interfaces/RiskApiData.d.ts +4 -0
  26. package/lib/cors/DefaultCors.js +21 -31
  27. package/lib/custom_parameters/CustomParametersUtils.js +3 -12
  28. package/lib/enforcer/EnforcerBase.d.ts +2 -1
  29. package/lib/enforcer/EnforcerBase.js +56 -57
  30. package/lib/enforcer/options/EnforcerBaseOptions.d.ts +2 -0
  31. package/lib/graphql/DefaultGraphQLParser.js +30 -39
  32. package/lib/http/index.d.ts +0 -1
  33. package/lib/http/index.js +0 -1
  34. package/lib/http/interfaces/IBody.d.ts +3 -2
  35. package/lib/http/interfaces/IIncomingRequest.d.ts +4 -0
  36. package/lib/http/interfaces/IURL.d.ts +3 -0
  37. package/lib/http/interfaces/IURLSearchParams.d.ts +9 -0
  38. package/lib/http/interfaces/IURLSearchParams.js +1 -0
  39. package/lib/http/interfaces/index.d.ts +1 -0
  40. package/lib/http/interfaces/index.js +1 -0
  41. package/lib/http/{impl → utils}/FormDataImpl.js +4 -4
  42. package/lib/http/{impl → utils}/MinimalResponseImpl.js +3 -0
  43. package/lib/http/utils/MinimalResponseUtils.js +5 -7
  44. package/lib/http/utils/MultipartFormDataUtils.js +4 -5
  45. package/lib/http/{impl → utils}/OutgoingRequestImpl.d.ts +1 -1
  46. package/lib/http/{impl → utils}/OutgoingRequestImpl.js +5 -1
  47. package/lib/http/utils/URLUtils.d.ts +7 -0
  48. package/lib/http/utils/URLUtils.js +62 -0
  49. package/lib/http/utils/UrlImpl.d.ts +18 -0
  50. package/lib/http/utils/UrlImpl.js +54 -0
  51. package/lib/http/utils/UrlSearchParamsImpl.d.ts +19 -0
  52. package/lib/http/utils/UrlSearchParamsImpl.js +116 -0
  53. package/lib/http/utils/index.d.ts +6 -0
  54. package/lib/http/utils/index.js +6 -0
  55. package/lib/{utils → impl}/base64/AtobBase64Utils.d.ts +1 -1
  56. package/lib/{utils → impl}/base64/BufferBase64Utils.d.ts +1 -1
  57. package/lib/{utils → impl}/base64/BufferBase64Utils.js +1 -1
  58. package/lib/{utils → impl}/base64/JSBase64Base64Utils.d.ts +1 -1
  59. package/lib/{utils → impl}/cipher/CryptoCipherUtils.d.ts +1 -1
  60. package/lib/impl/cipher/CryptoCipherUtils.js +18 -0
  61. package/lib/{utils → impl}/cipher/SubtleCryptoCipherUtils.d.ts +1 -2
  62. package/lib/impl/cipher/SubtleCryptoCipherUtils.js +38 -0
  63. package/lib/{utils → impl}/hash/CryptoHashUtils.d.ts +1 -2
  64. package/lib/impl/hash/CryptoHashUtils.js +10 -0
  65. package/lib/{utils → impl}/hash/CryptoJSHashUtils.d.ts +1 -2
  66. package/lib/{utils → impl}/hash/CryptoJSHashUtils.js +1 -1
  67. package/lib/{utils → impl}/hash/SubtleCryptoHashUtils.d.ts +1 -2
  68. package/lib/impl/hash/SubtleCryptoHashUtils.js +21 -0
  69. package/lib/{utils → impl}/hmac/CryptoHmacUtils.d.ts +1 -2
  70. package/lib/{utils → impl}/hmac/CryptoHmacUtils.js +2 -1
  71. package/lib/{utils → impl}/hmac/CryptoJSHmacUtils.d.ts +1 -2
  72. package/lib/{utils → impl}/hmac/CryptoJSHmacUtils.js +1 -1
  73. package/lib/{http/impl → impl/http}/phin/PhinHttpClient.d.ts +1 -1
  74. package/lib/impl/http/phin/PhinHttpClient.js +31 -0
  75. package/lib/{http/impl → impl/http}/phin/PhinIncomingResponse.d.ts +2 -2
  76. package/lib/impl/http/phin/PhinIncomingResponse.js +23 -0
  77. package/lib/{utils → impl}/ip_range_checker/DefaultIpRangeChecker.d.ts +1 -1
  78. package/lib/{utils → impl}/request_id_generator/UuidRequestIdGenerator.d.ts +1 -1
  79. package/lib/{utils → impl}/url_parser/DefaultUrlParser.d.ts +4 -4
  80. package/lib/{utils → impl}/url_parser/DefaultUrlParser.js +9 -2
  81. package/lib/logger/HttpLogServiceClient.d.ts +17 -0
  82. package/lib/logger/HttpLogServiceClient.js +52 -0
  83. package/lib/logger/ILogServiceClient.d.ts +6 -0
  84. package/lib/logger/ILogServiceClient.js +1 -0
  85. package/lib/logger/ILogger.d.ts +6 -0
  86. package/lib/logger/LoggerBase.d.ts +6 -2
  87. package/lib/logger/LoggerBase.js +14 -1
  88. package/lib/logger/constants.d.ts +2 -0
  89. package/lib/logger/constants.js +2 -0
  90. package/lib/logger/index.d.ts +4 -0
  91. package/lib/logger/index.js +3 -0
  92. package/lib/logger/model/EnrichedLogRecord.d.ts +3 -0
  93. package/lib/logger/model/EnrichedLogRecord.js +1 -0
  94. package/lib/logger/model/LogMetadata.d.ts +9 -0
  95. package/lib/logger/model/LogMetadata.js +1 -0
  96. package/lib/logger/model/LogRecord.d.ts +6 -0
  97. package/lib/logger/model/LogRecord.js +1 -0
  98. package/lib/logger/model/index.d.ts +3 -0
  99. package/lib/logger/model/index.js +3 -0
  100. package/lib/phase/flow/EndEnforcerFlow.d.ts +6 -0
  101. package/lib/phase/flow/EndEnforcerFlow.js +10 -0
  102. package/lib/phase/flow/index.d.ts +1 -0
  103. package/lib/phase/flow/index.js +1 -0
  104. package/lib/phase/impl/AdditionalActivityHandlerPhase.js +4 -15
  105. package/lib/phase/impl/CompositePhase.js +9 -19
  106. package/lib/phase/impl/CreateBlockResponsePhase.js +24 -35
  107. package/lib/phase/impl/DecideActionPhase.js +11 -21
  108. package/lib/phase/impl/EnrichContextFromRequestPhase.js +28 -45
  109. package/lib/phase/impl/EnrichContextFromResponsePhase.js +12 -23
  110. package/lib/phase/impl/FilterPhase.js +3 -13
  111. package/lib/phase/impl/FirstPartyPhase.js +21 -32
  112. package/lib/phase/impl/ModifyIncomingRequestPhase.js +4 -14
  113. package/lib/phase/impl/ModifyOutgoingResponsePhase.js +7 -18
  114. package/lib/phase/impl/ParseTokenPhase.js +5 -15
  115. package/lib/phase/impl/PreflightPhase.js +12 -20
  116. package/lib/phase/impl/RiskApiPhase.js +24 -36
  117. package/lib/phase/impl/SendAsyncActivitiesOnRequestPhase.js +8 -20
  118. package/lib/phase/impl/SendAsyncActivitiesOnResponsePhase.js +4 -14
  119. package/lib/phase/impl/SendLogsPhase.d.ts +11 -0
  120. package/lib/phase/impl/SendLogsPhase.js +16 -0
  121. package/lib/phase/impl/TelemetryPhase.js +9 -21
  122. package/lib/phase/impl/index.d.ts +1 -0
  123. package/lib/phase/impl/index.js +1 -0
  124. package/lib/products/account_defender/AccountDefender.js +16 -35
  125. package/lib/products/bot_defender/BotDefender.js +51 -72
  126. package/lib/products/bot_defender/BotDefenderActionData.js +2 -0
  127. package/lib/products/bot_defender/block/DefaultBotDefenderBlocker.d.ts +4 -4
  128. package/lib/products/bot_defender/block/DefaultBotDefenderBlocker.js +5 -3
  129. package/lib/products/bot_defender/block/captcha/CaptchaBlocker.d.ts +7 -4
  130. package/lib/products/bot_defender/block/captcha/CaptchaBlocker.js +12 -8
  131. package/lib/products/bot_defender/block/captcha/HtmlCaptchaBlocker.d.ts +1 -1
  132. package/lib/products/bot_defender/block/captcha/HtmlCaptchaBlocker.js +1 -0
  133. package/lib/products/bot_defender/block/captcha/JsonCaptchaBlocker.d.ts +1 -1
  134. package/lib/products/bot_defender/block/captcha/JsonCaptchaBlocker.js +5 -4
  135. package/lib/products/bot_defender/block/captcha/MobileCaptchaBlocker.d.ts +2 -2
  136. package/lib/products/bot_defender/block/captcha/MobileCaptchaBlocker.js +2 -0
  137. package/lib/products/bot_defender/block/utils.js +1 -2
  138. package/lib/products/bot_defender/filter/DefaultBotDefenderFilter.js +7 -1
  139. package/lib/products/bot_defender/first_party/DefaultBotDefenderFirstParty.js +51 -68
  140. package/lib/products/bot_defender/first_party/constants.d.ts +0 -4
  141. package/lib/products/bot_defender/first_party/constants.js +0 -7
  142. package/lib/products/credential_intelligence/CredentialIntelligence.js +42 -63
  143. package/lib/products/credential_intelligence/endpoint/CredentialEndpoint.js +15 -23
  144. package/lib/products/credential_intelligence/endpoint/CredentialEndpointManager.js +9 -22
  145. package/lib/products/credential_intelligence/endpoint/extractor/BodyCredentialExtractor.d.ts +5 -5
  146. package/lib/products/credential_intelligence/endpoint/extractor/BodyCredentialExtractor.js +22 -33
  147. package/lib/products/credential_intelligence/endpoint/extractor/CustomCredentialExtractor.js +8 -18
  148. package/lib/products/credential_intelligence/endpoint/extractor/HeaderCredentialExtractor.js +2 -0
  149. package/lib/products/credential_intelligence/endpoint/extractor/QueryParamCredentialExtractor.d.ts +1 -1
  150. package/lib/products/credential_intelligence/endpoint/extractor/QueryParamCredentialExtractor.js +11 -16
  151. package/lib/products/credential_intelligence/endpoint/hash_protocol/MultistepHashProtocol.js +11 -21
  152. package/lib/products/credential_intelligence/endpoint/hash_protocol/SingleStepAndMultistepHashProtocol.js +9 -18
  153. package/lib/products/credential_intelligence/endpoint/hash_protocol/SingleStepHashProtocol.js +13 -25
  154. package/lib/products/credential_intelligence/endpoint/login_successful/BodyLoginSuccessfulParser.js +4 -14
  155. package/lib/products/credential_intelligence/endpoint/login_successful/CustomLoginSuccessfulParser.js +10 -20
  156. package/lib/products/credential_intelligence/endpoint/login_successful/HeaderLoginSuccessfulParser.js +7 -16
  157. package/lib/products/credential_intelligence/endpoint/login_successful/LoginSuccessfulParserFactory.js +7 -6
  158. package/lib/products/credential_intelligence/endpoint/login_successful/StatusLoginSuccessfulParser.js +3 -13
  159. package/lib/products/credential_intelligence/endpoint/matcher/ExactPathEndpointMatcher.js +2 -0
  160. package/lib/products/credential_intelligence/endpoint/matcher/RegexPathEndpointMatcher.js +2 -0
  161. package/lib/pxde/DefaultDataEnrichment.js +47 -61
  162. package/lib/pxhd/PXHDUtils.js +2 -2
  163. package/lib/risk_api/client/PostRiskApiClientBase.d.ts +7 -12
  164. package/lib/risk_api/client/PostRiskApiClientBase.js +70 -171
  165. package/lib/risk_api/model/RiskActivity.d.ts +5 -45
  166. package/lib/risk_api/risk_response/IRiskResponse.d.ts +1 -0
  167. package/lib/risk_api/risk_response/RiskResponseBase.d.ts +1 -0
  168. package/lib/risk_api/risk_response/RiskResponseBase.js +20 -33
  169. package/lib/risk_api/risk_response/v2/DefaultRiskResponseV2.d.ts +1 -1
  170. package/lib/risk_api/risk_response/v2/DefaultRiskResponseV2.js +3 -5
  171. package/lib/risk_api/risk_response/v2/RiskResponseV2Payload.d.ts +1 -0
  172. package/lib/risk_api/risk_response/v3/DefaultRiskResponseV3.js +2 -4
  173. package/lib/risk_api/risk_response/v3/RiskResponseV3Payload.d.ts +1 -0
  174. package/lib/risk_token/parser/TokenParserBase.js +25 -36
  175. package/lib/risk_token/token/TokenBase.js +24 -29
  176. package/lib/risk_token/token/v2/DefaultTokenV2.js +34 -49
  177. package/lib/risk_token/token/v3/DefaultTokenV3.js +63 -77
  178. package/lib/telemetry/DefaultTelemetry.js +46 -58
  179. package/lib/utils/base64/index.d.ts +0 -3
  180. package/lib/utils/base64/index.js +0 -3
  181. package/lib/utils/cipher/index.d.ts +1 -3
  182. package/lib/utils/cipher/index.js +1 -2
  183. package/lib/utils/constants.d.ts +2 -1
  184. package/lib/utils/constants.js +2 -1
  185. package/lib/utils/hash/index.d.ts +0 -3
  186. package/lib/utils/hash/index.js +0 -3
  187. package/lib/utils/hmac/index.d.ts +0 -2
  188. package/lib/utils/hmac/index.js +0 -2
  189. package/lib/utils/ip_range_checker/index.d.ts +1 -2
  190. package/lib/utils/ip_range_checker/index.js +1 -1
  191. package/lib/utils/request_id_generator/index.d.ts +1 -2
  192. package/lib/utils/request_id_generator/index.js +1 -1
  193. package/lib/utils/url_parser/index.d.ts +0 -1
  194. package/lib/utils/url_parser/index.js +0 -1
  195. package/lib/utils/utils.d.ts +1 -7
  196. package/lib/utils/utils.js +3 -25
  197. package/package.json +12 -6
  198. package/lib/activities/model/Activity.d.ts +0 -13
  199. package/lib/http/impl/index.d.ts +0 -4
  200. package/lib/http/impl/index.js +0 -4
  201. package/lib/http/impl/phin/PhinHttpClient.js +0 -41
  202. package/lib/http/impl/phin/PhinIncomingResponse.js +0 -38
  203. package/lib/utils/cipher/CryptoCipherUtils.js +0 -28
  204. package/lib/utils/cipher/SubtleCryptoCipherUtils.js +0 -47
  205. package/lib/utils/hash/CryptoHashUtils.js +0 -20
  206. package/lib/utils/hash/SubtleCryptoHashUtils.js +0 -31
  207. /package/lib/activities/model/{Activity.js → AsyncActivity.js} +0 -0
  208. /package/lib/activities/model/{ActivityDetails.js → AsyncActivityDetails.js} +0 -0
  209. /package/lib/http/{impl → utils}/FormDataImpl.d.ts +0 -0
  210. /package/lib/http/{impl → utils}/MinimalResponseImpl.d.ts +0 -0
  211. /package/lib/{utils → impl}/base64/AtobBase64Utils.js +0 -0
  212. /package/lib/{utils → impl}/base64/JSBase64Base64Utils.js +0 -0
  213. /package/lib/{http/impl → impl/http}/phin/index.d.ts +0 -0
  214. /package/lib/{http/impl → impl/http}/phin/index.js +0 -0
  215. /package/lib/{utils → impl}/ip_range_checker/DefaultIpRangeChecker.js +0 -0
  216. /package/lib/{utils → impl}/request_id_generator/UuidRequestIdGenerator.js +0 -0
@@ -0,0 +1,116 @@
1
+ // This file is based on the implementation found here:
2
+ // https://github.com/pinglu85/BFEdevSolutions/blob/main/Coding-Problems/80.implement-your-own-URLSearchParams.md
3
+ import { URLUtils } from './URLUtils';
4
+ export class UrlSearchParamsImpl {
5
+ _searchParamsArray;
6
+ _searchParamsMap;
7
+ constructor(init) {
8
+ this._searchParamsArray = [];
9
+ this._searchParamsMap = new Map();
10
+ if (init) {
11
+ if (typeof init !== 'object') {
12
+ this._constructSearchParamsFromString(init);
13
+ }
14
+ else if (Array.isArray(init)) {
15
+ this._constructSearchParamsFromArray(init);
16
+ }
17
+ else {
18
+ this._constructSearchParamsFromObject(init);
19
+ }
20
+ }
21
+ }
22
+ append(name, value) {
23
+ name = String(name);
24
+ value = String(value);
25
+ this._saveParam(name, value);
26
+ }
27
+ delete(name) {
28
+ name = String(name);
29
+ this._searchParamsMap.delete(name);
30
+ this._searchParamsArray = this._searchParamsArray.filter((param) => param[0] !== name);
31
+ }
32
+ forEach(callback) {
33
+ this._searchParamsArray.forEach((param) => {
34
+ callback(param[1], param[0], this);
35
+ });
36
+ }
37
+ get(name) {
38
+ name = String(name);
39
+ const value = this._searchParamsMap.get(name);
40
+ return value ? value[0] : null;
41
+ }
42
+ getAll(name) {
43
+ name = String(name);
44
+ const value = this._searchParamsMap.get(name);
45
+ return value ? value : [];
46
+ }
47
+ has(name) {
48
+ name = String(name);
49
+ return this._searchParamsMap.has(name);
50
+ }
51
+ set(name, value) {
52
+ name = String(name);
53
+ value = String(value);
54
+ if (!this.has(name)) {
55
+ this.append(name, value);
56
+ return;
57
+ }
58
+ name = URLUtils.decodeUriComponent(name);
59
+ value = URLUtils.decodeUriComponent(value);
60
+ this._searchParamsMap.set(name, [value]);
61
+ const searchParamIdx = this._searchParamsArray.findIndex((param) => param[0] === name);
62
+ this._searchParamsArray[searchParamIdx][1] = value;
63
+ this._searchParamsArray = this._searchParamsArray.filter((param, idx) => param[0] !== name || idx === searchParamIdx);
64
+ }
65
+ toString() {
66
+ return this._searchParamsArray
67
+ .map(([key, value]) => `${URLUtils.encodeUriComponent(key)}=${URLUtils.encodeUriComponent(value)}`)
68
+ .join('&');
69
+ }
70
+ _constructSearchParamsFromString(init) {
71
+ let searchParams = String(init);
72
+ if (searchParams.startsWith('?')) {
73
+ searchParams = searchParams.slice(1);
74
+ }
75
+ searchParams.split('&').forEach((param) => {
76
+ let [key, value] = param.split('=');
77
+ if (!value) {
78
+ value = '';
79
+ }
80
+ this._saveParam(key, value);
81
+ });
82
+ }
83
+ _constructSearchParamsFromArray(init) {
84
+ for (const param of init) {
85
+ if (!Array.isArray(param || param.length !== 2)) {
86
+ throw new Error("Failed to construct 'UrlSearchParamsImpl'");
87
+ }
88
+ const key = String(param[0]);
89
+ const value = String(param[1]);
90
+ this._saveParam(key, value);
91
+ }
92
+ }
93
+ _constructSearchParamsFromObject(init) {
94
+ if (init instanceof Set) {
95
+ throw new Error("Failed to construct 'UrlSearchParamsImpl'");
96
+ }
97
+ for (const key of Object.keys(init)) {
98
+ const value = String(init[key]);
99
+ this._saveParam(key, value);
100
+ }
101
+ }
102
+ _saveParam(key, value) {
103
+ key = URLUtils.decodeUriComponent(key);
104
+ value = URLUtils.decodeUriComponent(value);
105
+ this._searchParamsArray.push([key, value]);
106
+ this._storeParamInSearchParamsMap(key, value);
107
+ }
108
+ _storeParamInSearchParamsMap(key, value) {
109
+ let values = this._searchParamsMap.get(key);
110
+ if (!values) {
111
+ values = [];
112
+ this._searchParamsMap.set(key, values);
113
+ }
114
+ values.push(value);
115
+ }
116
+ }
@@ -3,3 +3,9 @@ export * from './constants';
3
3
  export * from './HttpMethod';
4
4
  export * from './MinimalResponseUtils';
5
5
  export * from './MultipartFormDataUtils';
6
+ export * from './FormDataImpl';
7
+ export * from './MinimalResponseImpl';
8
+ export * from './OutgoingRequestImpl';
9
+ export * from './UrlImpl';
10
+ export * from './UrlSearchParamsImpl';
11
+ export * from './URLUtils';
@@ -3,3 +3,9 @@ export * from './constants';
3
3
  export * from './HttpMethod';
4
4
  export * from './MinimalResponseUtils';
5
5
  export * from './MultipartFormDataUtils';
6
+ export * from './FormDataImpl';
7
+ export * from './MinimalResponseImpl';
8
+ export * from './OutgoingRequestImpl';
9
+ export * from './UrlImpl';
10
+ export * from './UrlSearchParamsImpl';
11
+ export * from './URLUtils';
@@ -1,4 +1,4 @@
1
- import { IBase64Utils } from './IBase64Utils';
1
+ import { IBase64Utils } from '../../utils';
2
2
  export declare class AtobBase64Utils implements IBase64Utils {
3
3
  base64Decode(stringToDecode: string): string;
4
4
  base64Encode(stringToEncode: string): string;
@@ -1,4 +1,4 @@
1
- import { IBase64Utils } from './IBase64Utils';
1
+ import { IBase64Utils } from '../../utils';
2
2
  export declare class BufferBase64Utils implements IBase64Utils {
3
3
  static BASE_64_ENCODING: 'base64';
4
4
  base64Decode(stringToDecode: string): string;
@@ -1,4 +1,5 @@
1
1
  export class BufferBase64Utils {
2
+ static BASE_64_ENCODING = 'base64';
2
3
  base64Decode(stringToDecode) {
3
4
  const buffer = Buffer.from(stringToDecode, BufferBase64Utils.BASE_64_ENCODING);
4
5
  return buffer.toString('utf8');
@@ -8,4 +9,3 @@ export class BufferBase64Utils {
8
9
  return buffer.toString(BufferBase64Utils.BASE_64_ENCODING);
9
10
  }
10
11
  }
11
- BufferBase64Utils.BASE_64_ENCODING = 'base64';
@@ -1,4 +1,4 @@
1
- import { IBase64Utils } from './IBase64Utils';
1
+ import { IBase64Utils } from '../../utils';
2
2
  export declare class JSBase64Base64Utils implements IBase64Utils {
3
3
  base64Encode(stringToEncode: string): string;
4
4
  base64Decode(stringToDecode: string): string;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import * as crypto from 'crypto';
3
- import { ICipherUtils, Pbkdf2DecryptOptions } from './ICipherUtils';
3
+ import { ICipherUtils, Pbkdf2DecryptOptions } from '../../utils';
4
4
  declare type CryptoModule = typeof crypto;
5
5
  export declare class CryptoCipherUtils implements ICipherUtils {
6
6
  private crypto;
@@ -0,0 +1,18 @@
1
+ import * as crypto from 'crypto';
2
+ export class CryptoCipherUtils {
3
+ crypto;
4
+ constructor(cryptoModule = crypto) {
5
+ this.crypto = cryptoModule;
6
+ }
7
+ async pbkdf2Decrypt(secret, encryptedString, iterations, salt, options) {
8
+ const keylen = options?.keylen || 32;
9
+ const ivlen = options?.ivlen || 16;
10
+ const derivation = this.crypto.pbkdf2Sync(secret, Buffer.from(salt, 'base64'), iterations, keylen + ivlen, 'sha256');
11
+ const key = derivation.subarray(0, keylen);
12
+ const iv = derivation.subarray(keylen);
13
+ const cipher = this.crypto.createDecipheriv('aes-256-cbc', key, iv);
14
+ let decrypted = cipher.update(encryptedString, 'base64', 'utf8');
15
+ decrypted += cipher.final('utf8');
16
+ return decrypted;
17
+ }
18
+ }
@@ -1,5 +1,4 @@
1
- import { IBase64Utils } from '../base64';
2
- import { ICipherUtils, Pbkdf2DecryptOptions } from './ICipherUtils';
1
+ import { ICipherUtils, IBase64Utils, Pbkdf2DecryptOptions } from '../../utils';
3
2
  export declare class SubtleCryptoCipherUtils implements ICipherUtils {
4
3
  private base64Utils;
5
4
  private subtleCrypto;
@@ -0,0 +1,38 @@
1
+ export class SubtleCryptoCipherUtils {
2
+ base64Utils;
3
+ subtleCrypto;
4
+ constructor(base64Utils, subtleCrypto = crypto.subtle) {
5
+ this.subtleCrypto = subtleCrypto;
6
+ this.base64Utils = base64Utils;
7
+ }
8
+ async pbkdf2Decrypt(secret, encryptedString, iterations, salt, options) {
9
+ const ivlen = options?.ivlen || 16;
10
+ const keylen = options?.keylen || 32;
11
+ const bitsLength = (ivlen + keylen) * 8;
12
+ const encodedPassword = new TextEncoder().encode(secret);
13
+ const encodedSalt = this.base64ToArrayBuffer(salt);
14
+ const importedKey = await this.subtleCrypto.importKey('raw', encodedPassword, 'PBKDF2', false, ['deriveBits']);
15
+ const params = { name: 'PBKDF2', hash: 'SHA-256', salt: encodedSalt, iterations: iterations };
16
+ const derivation = await this.subtleCrypto.deriveBits(params, importedKey, bitsLength);
17
+ const derivedKey = derivation.slice(0, keylen);
18
+ const iv = derivation.slice(keylen);
19
+ const cookieBuffer = this.base64ToArrayBuffer(encryptedString);
20
+ const importedDecryptionKey = await this.subtleCrypto.importKey('raw', derivedKey, { name: 'AES-CBC' }, false, [
21
+ 'decrypt',
22
+ ]);
23
+ const decrypted = await this.subtleCrypto.decrypt({
24
+ name: 'AES-CBC',
25
+ iv: iv,
26
+ }, importedDecryptionKey, cookieBuffer);
27
+ return new TextDecoder('utf-8').decode(decrypted);
28
+ }
29
+ base64ToArrayBuffer(base64String) {
30
+ const binaryString = this.base64Utils.base64Decode(base64String);
31
+ const length = binaryString.length;
32
+ const bytes = new Uint8Array(length);
33
+ binaryString.split('').forEach((char, index) => {
34
+ bytes[index] = char.charCodeAt(0);
35
+ });
36
+ return bytes.buffer;
37
+ }
38
+ }
@@ -1,7 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import * as crypto from 'crypto';
3
- import { IHashUtils } from './IHashUtils';
4
- import { Algorithm } from '../Algorithm';
3
+ import { Algorithm, IHashUtils } from '../../utils';
5
4
  declare type CryptoModule = typeof crypto;
6
5
  export declare class CryptoHashUtils implements IHashUtils {
7
6
  private readonly crypto;
@@ -0,0 +1,10 @@
1
+ import * as crypto from 'crypto';
2
+ export class CryptoHashUtils {
3
+ crypto;
4
+ constructor(cryptoModule = crypto) {
5
+ this.crypto = cryptoModule;
6
+ }
7
+ async hashString(text, algo) {
8
+ return this.crypto.createHash(algo).update(text).digest('hex');
9
+ }
10
+ }
@@ -1,5 +1,4 @@
1
- import { IHashUtils } from './IHashUtils';
2
- import { Algorithm } from '../Algorithm';
1
+ import { Algorithm, IHashUtils } from '../../utils';
3
2
  export declare class CryptoJSHashUtils implements IHashUtils {
4
3
  hashString(text: string, algo: Algorithm): string;
5
4
  }
@@ -1,5 +1,5 @@
1
1
  import cryptoJs from 'crypto-js';
2
- import { Algorithm } from '../Algorithm';
2
+ import { Algorithm } from '../../utils';
3
3
  export class CryptoJSHashUtils {
4
4
  hashString(text, algo) {
5
5
  switch (algo) {
@@ -1,5 +1,4 @@
1
- import { Algorithm } from '../Algorithm';
2
- import { IHashUtils } from './IHashUtils';
1
+ import { Algorithm, IHashUtils } from '../../utils';
3
2
  export declare class SubtleCryptoHashUtils implements IHashUtils {
4
3
  private readonly subtle;
5
4
  constructor(subtleCrypto?: SubtleCrypto);
@@ -0,0 +1,21 @@
1
+ import * as crypto from 'crypto';
2
+ import { Algorithm } from '../../utils';
3
+ export class SubtleCryptoHashUtils {
4
+ subtle;
5
+ constructor(subtleCrypto = crypto.subtle) {
6
+ this.subtle = subtleCrypto;
7
+ }
8
+ async hashString(text, algo) {
9
+ const textUint8 = new TextEncoder().encode(text);
10
+ const hashBuffer = await this.subtle.digest(this.convertAlgo(algo), textUint8);
11
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
12
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
13
+ }
14
+ convertAlgo(algo) {
15
+ switch (algo) {
16
+ case Algorithm.SHA256:
17
+ default:
18
+ return 'SHA-256';
19
+ }
20
+ }
21
+ }
@@ -1,7 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import * as crypto from 'crypto';
3
- import { IHmacUtils } from './IHmacUtils';
4
- import { Algorithm } from '../Algorithm';
3
+ import { Algorithm, IHmacUtils } from '../../utils';
5
4
  declare type CryptoModule = typeof crypto;
6
5
  export declare class CryptoHmacUtils implements IHmacUtils {
7
6
  private readonly crypto;
@@ -1,6 +1,7 @@
1
1
  import * as crypto from 'crypto';
2
- import { Algorithm } from '../Algorithm';
2
+ import { Algorithm } from '../../utils';
3
3
  export class CryptoHmacUtils {
4
+ crypto;
4
5
  constructor(cryptoModule = crypto) {
5
6
  this.crypto = cryptoModule;
6
7
  }
@@ -1,5 +1,4 @@
1
- import { IHmacUtils } from './IHmacUtils';
2
- import { Algorithm } from '../Algorithm';
1
+ import { Algorithm, IHmacUtils } from '../../utils';
3
2
  export declare class CryptoJSHmacUtils implements IHmacUtils {
4
3
  createHmac(algo: Algorithm, payload: string, secret: string): string;
5
4
  }
@@ -1,5 +1,5 @@
1
1
  import cryptoJs from 'crypto-js';
2
- import { Algorithm } from '../Algorithm';
2
+ import { Algorithm } from '../../utils';
3
3
  export class CryptoJSHmacUtils {
4
4
  createHmac(algo, payload, secret) {
5
5
  switch (algo) {
@@ -1,4 +1,4 @@
1
- import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '../../interfaces';
1
+ import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '../../../http/interfaces';
2
2
  export declare class PhinHttpClient implements IHttpClient {
3
3
  private readonly httpsKeepAliveAgent;
4
4
  constructor();
@@ -0,0 +1,31 @@
1
+ import { Agent as HttpAgent } from 'http';
2
+ import { Agent as HttpsAgent } from 'https';
3
+ import phin from 'phin';
4
+ import { EnforcerTimeoutError } from '../../../utils';
5
+ import { joinHeaderValues, } from '../../../http/interfaces';
6
+ import { PhinIncomingResponse } from './PhinIncomingResponse';
7
+ export class PhinHttpClient {
8
+ httpsKeepAliveAgent;
9
+ constructor() {
10
+ this.httpsKeepAliveAgent = new HttpsAgent({ keepAlive: true });
11
+ }
12
+ async send(request, options) {
13
+ try {
14
+ const res = await phin.promisified({
15
+ url: request.url,
16
+ method: request.method,
17
+ headers: joinHeaderValues(request.headers),
18
+ data: request.body,
19
+ timeout: options?.timeoutMs || null,
20
+ core: {
21
+ agent: request.url.startsWith('https://') ? this.httpsKeepAliveAgent : new HttpAgent(),
22
+ },
23
+ });
24
+ return new PhinIncomingResponse(res);
25
+ }
26
+ catch (e) {
27
+ const isTimeout = e.toString().toLowerCase().includes('timeout');
28
+ throw isTimeout ? new EnforcerTimeoutError(options.timeoutMs) : e;
29
+ }
30
+ }
31
+ }
@@ -1,13 +1,13 @@
1
1
  /// <reference types="node" />
2
2
  import { IResponse } from 'phin';
3
- import { IFormData, IIncomingResponse, ReadonlyHeaders } from '../../interfaces';
3
+ import { IFormData, IIncomingResponse, IURLSearchParams, ReadonlyHeaders } from '../../../http';
4
4
  export declare class PhinIncomingResponse implements IIncomingResponse {
5
5
  readonly status: number;
6
6
  readonly headers: ReadonlyHeaders;
7
7
  readonly body: Buffer;
8
8
  constructor(response: IResponse);
9
9
  formData(): Promise<IFormData>;
10
- formUrlEncoded(): Promise<URLSearchParams>;
10
+ formUrlEncoded(): Promise<IURLSearchParams>;
11
11
  json(): Promise<any>;
12
12
  text(): Promise<string>;
13
13
  }
@@ -0,0 +1,23 @@
1
+ import { CONTENT_TYPE_HEADER_NAME, MultipartFormDataUtils, URLUtils, } from '../../../http';
2
+ export class PhinIncomingResponse {
3
+ status;
4
+ headers;
5
+ body;
6
+ constructor(response) {
7
+ this.status = response.statusCode;
8
+ this.body = response.body;
9
+ this.headers = Object.fromEntries(Object.entries(response.headers).map(([key, val]) => [key, typeof val === 'string' ? [val] : val]));
10
+ }
11
+ async formData() {
12
+ return MultipartFormDataUtils.createFormDataWithoutFiles(await this.text(), this.headers[CONTENT_TYPE_HEADER_NAME]?.[0]);
13
+ }
14
+ async formUrlEncoded() {
15
+ return URLUtils.parseSearchParams(await this.text());
16
+ }
17
+ async json() {
18
+ return JSON.parse(await this.text());
19
+ }
20
+ async text() {
21
+ return this.body.toString();
22
+ }
23
+ }
@@ -1,4 +1,4 @@
1
- import { IIpRangeChecker } from './IIpRangeChecker';
1
+ import { IIpRangeChecker } from '../../utils';
2
2
  export declare class DefaultIpRangeChecker implements IIpRangeChecker {
3
3
  isIpInRange(ip: string, range: string | string[]): boolean;
4
4
  }
@@ -1,4 +1,4 @@
1
- import { IRequestIdGenerator } from './IRequestIdGenerator';
1
+ import { IRequestIdGenerator } from '../../utils';
2
2
  export declare class UuidRequestIdGenerator implements IRequestIdGenerator {
3
3
  generateRequestId(): string;
4
4
  }
@@ -1,13 +1,13 @@
1
- import { IURLParser } from './IURLParser';
2
1
  import { IURL } from '../../http';
2
+ import { IURLParser } from '../../utils';
3
3
  export type UrlParserOptions = {
4
4
  normalize?: boolean;
5
5
  reverseCharactersEncoding?: boolean;
6
6
  };
7
7
  export declare class DefaultUrlParser implements IURLParser {
8
- private options;
8
+ protected options: UrlParserOptions;
9
9
  constructor(options?: UrlParserOptions);
10
10
  parse(rawUrl: string): IURL;
11
- private reverseCharactersEncoding;
12
- private normalize;
11
+ protected reverseCharactersEncoding(path: string): string;
12
+ protected normalize(path: string): string;
13
13
  }
@@ -1,9 +1,15 @@
1
+ import { URLUtils } from '../../http';
1
2
  export class DefaultUrlParser {
3
+ options;
2
4
  constructor(options) {
3
- this.options = Object.assign({ normalize: true, reverseCharactersEncoding: false }, options);
5
+ this.options = {
6
+ normalize: true,
7
+ reverseCharactersEncoding: false,
8
+ ...options,
9
+ };
4
10
  }
5
11
  parse(rawUrl) {
6
- const url = new URL(rawUrl);
12
+ const url = URLUtils.parseURL(rawUrl);
7
13
  if (this.options.reverseCharactersEncoding) {
8
14
  url.pathname = this.reverseCharactersEncoding(url.pathname);
9
15
  }
@@ -13,6 +19,7 @@ export class DefaultUrlParser {
13
19
  return url;
14
20
  }
15
21
  reverseCharactersEncoding(path) {
22
+ // NOTICE: Find a suitable polyfill in case decodeURI doesn't exist in the global scope
16
23
  return decodeURI(path);
17
24
  }
18
25
  normalize(path) {
@@ -0,0 +1,17 @@
1
+ import { EnrichedLogRecord, LogRecord } from './model';
2
+ import { ReadonlyContext } from '../context';
3
+ import { IConfiguration } from '../config';
4
+ import { IHttpClient } from '../http';
5
+ import { ILogger } from '../logger';
6
+ import { ILogServiceClient } from './ILogServiceClient';
7
+ export declare class HttpLogServiceClient<Req, Res> implements ILogServiceClient<Req, Res> {
8
+ protected readonly appId: string;
9
+ protected readonly backendUrl: string;
10
+ protected readonly loggerAuthToken: string;
11
+ protected readonly logger: ILogger;
12
+ protected readonly httpClient: IHttpClient;
13
+ constructor(config: IConfiguration<Req, Res>, httpClient: IHttpClient);
14
+ sendLogs(context: ReadonlyContext<Req, Res>, logs: LogRecord[]): Promise<void>;
15
+ protected enrichLogRecord(context: ReadonlyContext<Req, Res>, log: LogRecord): EnrichedLogRecord;
16
+ protected postLogs(logRecords: EnrichedLogRecord[]): Promise<boolean>;
17
+ }
@@ -0,0 +1,52 @@
1
+ import { EXTERNAL_LOGGER_SERVICE_PATH } from './constants';
2
+ import { AUTHORIZATION_HEADER_NAME, CONTENT_TYPE_HEADER_NAME, ContentType, HttpMethod, OutgoingRequestImpl, URLUtils, } from '../http';
3
+ import { getAuthorizationHeader } from '../utils';
4
+ export class HttpLogServiceClient {
5
+ appId;
6
+ backendUrl;
7
+ loggerAuthToken;
8
+ logger;
9
+ httpClient;
10
+ constructor(config, httpClient) {
11
+ this.appId = config.appId;
12
+ this.backendUrl = config.backendScoreApiUrl;
13
+ this.loggerAuthToken = config.loggerAuthToken;
14
+ this.logger = config.logger;
15
+ this.httpClient = httpClient;
16
+ }
17
+ async sendLogs(context, logs) {
18
+ try {
19
+ const enrichedLogs = logs.map((log) => this.enrichLogRecord(context, log));
20
+ await this.postLogs(enrichedLogs);
21
+ }
22
+ catch (e) {
23
+ this.logger.error(`unable to send logs: ${e}`);
24
+ }
25
+ }
26
+ enrichLogRecord(context, log) {
27
+ const requestData = context.requestData;
28
+ const url = URLUtils.parseURL(requestData.rawUrl);
29
+ const logMeta = {
30
+ container: 'enforcer',
31
+ appID: this.appId,
32
+ method: requestData.method,
33
+ host: url.host,
34
+ url: requestData.rawUrl,
35
+ path: url.pathname + requestData.url.search,
36
+ requestId: context.requestId,
37
+ };
38
+ return { ...logMeta, ...log };
39
+ }
40
+ async postLogs(logRecords) {
41
+ const url = `${this.backendUrl}${EXTERNAL_LOGGER_SERVICE_PATH}`;
42
+ const method = HttpMethod.POST;
43
+ const headers = {
44
+ [CONTENT_TYPE_HEADER_NAME]: [ContentType.APPLICATION_JSON],
45
+ [AUTHORIZATION_HEADER_NAME]: [getAuthorizationHeader(this.loggerAuthToken)],
46
+ };
47
+ const body = JSON.stringify(logRecords);
48
+ const req = new OutgoingRequestImpl({ url, method, headers, body });
49
+ const res = await this.httpClient.send(req);
50
+ return res?.status === 200;
51
+ }
52
+ }
@@ -0,0 +1,6 @@
1
+ import { ReadonlyContext } from '../context';
2
+ import { LogRecord } from './model';
3
+ import { AsyncOrSync } from 'ts-essentials';
4
+ export interface ILogServiceClient<Req, Res> {
5
+ sendLogs(context: ReadonlyContext<Req, Res>, logs: LogRecord[]): AsyncOrSync<void>;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { LoggerSeverity } from './LoggerSeverity';
2
+ import { LogRecord } from './model';
2
3
  export interface ILogger {
3
4
  /**
4
5
  * @returns LoggerSeverity - The current logger severity.
@@ -21,4 +22,9 @@ export interface ILogger {
21
22
  * @returns void
22
23
  */
23
24
  error(message: string): void;
25
+ /**
26
+ * Get all the saved logs for that request
27
+ * @returns LogRecord[]
28
+ */
29
+ getLogs(): LogRecord[];
24
30
  }
@@ -1,8 +1,10 @@
1
1
  import { ILogger } from './ILogger';
2
2
  import { LoggerSeverity } from './LoggerSeverity';
3
+ import { LogRecord } from './model';
3
4
  export declare abstract class LoggerBase implements ILogger {
4
- private loggerSeverity;
5
- protected constructor(loggerSeverity?: LoggerSeverity);
5
+ protected loggerSeverity: LoggerSeverity;
6
+ protected logs: LogRecord[];
7
+ protected constructor(loggerSeverity?: LoggerSeverity, logs?: LogRecord[]);
6
8
  protected abstract log(message: string): void;
7
9
  debug(message: string): void;
8
10
  error(message: string): void;
@@ -10,4 +12,6 @@ export declare abstract class LoggerBase implements ILogger {
10
12
  setLoggerSeverity(loggerSeverity: LoggerSeverity): void;
11
13
  protected logError(message: string): void;
12
14
  protected logDebug(message: string): void;
15
+ getLogs(): LogRecord[];
16
+ protected recordLog(message: string, loggerSeverity: LoggerSeverity): void;
13
17
  }
@@ -1,14 +1,19 @@
1
1
  import { LoggerSeverity } from './LoggerSeverity';
2
2
  export class LoggerBase {
3
- constructor(loggerSeverity = LoggerSeverity.ERROR) {
3
+ loggerSeverity;
4
+ logs;
5
+ constructor(loggerSeverity = LoggerSeverity.ERROR, logs = []) {
4
6
  this.loggerSeverity = loggerSeverity;
7
+ this.logs = logs;
5
8
  }
6
9
  debug(message) {
10
+ this.recordLog(message, LoggerSeverity.DEBUG);
7
11
  if (this.loggerSeverity == LoggerSeverity.DEBUG) {
8
12
  this.logDebug(message);
9
13
  }
10
14
  }
11
15
  error(message) {
16
+ this.recordLog(message, LoggerSeverity.ERROR);
12
17
  if (this.loggerSeverity != LoggerSeverity.NONE) {
13
18
  this.logError(message);
14
19
  }
@@ -27,4 +32,12 @@ export class LoggerBase {
27
32
  logDebug(message) {
28
33
  this.log(message);
29
34
  }
35
+ // default implementation, can be overridden
36
+ getLogs() {
37
+ return this.logs;
38
+ }
39
+ recordLog(message, loggerSeverity) {
40
+ const logRecord = { message: message, severity: loggerSeverity, messageTimestamp: Date.now() };
41
+ this.logs.push(logRecord);
42
+ }
30
43
  }
@@ -0,0 +1,2 @@
1
+ export declare const X_PX_ENFORCER_LOG_HEADER = "x-px-enforcer-log";
2
+ export declare const EXTERNAL_LOGGER_SERVICE_PATH = "/enforcer-logs/";