perimeterx-js-core 0.2.0 → 0.3.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.
- package/lib/activities/model/ActivityDetails.d.ts +4 -2
- package/lib/activities/utils.js +2 -1
- package/lib/config/ConfigurationParams.d.ts +4 -0
- package/lib/config/DefaultConfigurations.js +5 -1
- package/lib/config/IConfiguration.d.ts +18 -0
- package/lib/config/StaticConfigurationBase.d.ts +4 -0
- package/lib/config/StaticConfigurationBase.js +28 -0
- package/lib/context/ContextBase.d.ts +3 -2
- package/lib/context/ContextBase.js +13 -77
- package/lib/context/IContext.d.ts +4 -3
- package/lib/custom_parameters/CustomParametersUtils.d.ts +3 -0
- package/lib/custom_parameters/CustomParametersUtils.js +59 -0
- package/lib/enforcer/EnforcerBase.d.ts +6 -1
- package/lib/enforcer/EnforcerBase.js +41 -7
- package/lib/first_party/DefaultFirstParty.js +1 -1
- package/lib/graphql/DefaultGraphQLParser.d.ts +19 -0
- package/lib/graphql/DefaultGraphQLParser.js +183 -0
- package/lib/graphql/IGraphQLParser.d.ts +5 -0
- package/lib/graphql/IGraphQLParser.js +2 -0
- package/lib/graphql/index.d.ts +5 -0
- package/lib/graphql/index.js +7 -0
- package/lib/graphql/model/GraphQLData.d.ts +7 -0
- package/lib/graphql/model/GraphQLData.js +2 -0
- package/lib/graphql/model/GraphQLOperation.d.ts +5 -0
- package/lib/graphql/model/GraphQLOperation.js +2 -0
- package/lib/graphql/model/GraphQLOperationType.d.ts +5 -0
- package/lib/graphql/model/GraphQLOperationType.js +9 -0
- package/lib/http/utils/HttpHeaders.d.ts +3 -1
- package/lib/http/utils/HttpHeaders.js +19 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/risk_api/PostRiskApiClient.js +6 -3
- package/lib/risk_api/model/RiskActivity.d.ts +2 -0
- package/lib/risk_api/model/RiskResponseV2.d.ts +2 -0
- package/lib/risk_api/risk_response_handler/RiskResponseV2Handler.js +1 -0
- package/lib/utils/constants.d.ts +1 -1
- package/lib/utils/constants.js +1 -1
- package/lib/utils/utils.js +1 -1
- package/package.json +1 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { PassReason } from '../../utils
|
|
2
|
-
import { BlockReason } from '../../block_handler
|
|
1
|
+
import { PassReason } from '../../utils';
|
|
2
|
+
import { BlockReason } from '../../block_handler';
|
|
3
|
+
import { GraphQLData } from '../../graphql';
|
|
3
4
|
export declare type ActivityTypeDetails = PageRequestedActivityDetails | BlockActivityDetails | AdditionalS2SActivityDetails;
|
|
4
5
|
export declare type ActivityDetails = ActivityTypeDetails & {
|
|
5
6
|
client_uuid: string;
|
|
@@ -17,6 +18,7 @@ export declare type ActivityDetails = ActivityTypeDetails & {
|
|
|
17
18
|
tls_preferred_ciphers?: string;
|
|
18
19
|
tls_ciphers_sha?: string;
|
|
19
20
|
tls_ja3_fingerprint?: string;
|
|
21
|
+
graphql_operations?: GraphQLData[];
|
|
20
22
|
credentials_compromised?: boolean;
|
|
21
23
|
ci_version?: string;
|
|
22
24
|
sso_step?: string;
|
package/lib/activities/utils.js
CHANGED
|
@@ -8,7 +8,7 @@ var createActivity = function (activityType, config, context) {
|
|
|
8
8
|
type: activityType,
|
|
9
9
|
px_app_id: config.appId,
|
|
10
10
|
url: context.requestData.url.href,
|
|
11
|
-
headers: (0, utils_1.removeSensitiveHeaders)(context.requestData.headers, config.sensitiveHeaders).toObject(),
|
|
11
|
+
headers: (0, utils_1.removeSensitiveHeaders)(context.requestData.headers, config.sensitiveHeaders).toObject(','),
|
|
12
12
|
pxhd: context.pxhd,
|
|
13
13
|
socket_ip: context.requestData.ip,
|
|
14
14
|
timestamp: Date.now(),
|
|
@@ -44,6 +44,7 @@ var createGenericActivityDetails = function (config, context) {
|
|
|
44
44
|
requestId: 'request_id',
|
|
45
45
|
uuid: 'client_uuid',
|
|
46
46
|
tokenOrigin: 'cookie_origin',
|
|
47
|
+
graphqlData: 'graphql_operations',
|
|
47
48
|
});
|
|
48
49
|
(0, utils_1.transferExistingProperties)(context.requestData, genericActivityDetails, {
|
|
49
50
|
httpVersion: 'http_version',
|
|
@@ -58,6 +58,10 @@ export declare type ConfigurationParams = {
|
|
|
58
58
|
px_jwt_header_name?: string;
|
|
59
59
|
px_jwt_header_user_id_field_name?: string;
|
|
60
60
|
px_jwt_header_additional_field_names?: string[];
|
|
61
|
+
px_graphql_enabled?: boolean;
|
|
62
|
+
px_graphql_routes?: string[];
|
|
63
|
+
px_sensitive_graphql_operation_names?: string[];
|
|
64
|
+
px_sensitive_graphql_operation_types?: Array<'query' | 'mutation' | 'subscription'>;
|
|
61
65
|
px_extract_ip?: () => {};
|
|
62
66
|
px_additional_activity_handler?: AdditionalActivityHandler;
|
|
63
67
|
px_enrich_custom_parameters?: CustomParametersFunction;
|
|
@@ -94,8 +94,12 @@ exports.DEFAULT_CONFIGURATIONS = {
|
|
|
94
94
|
px_filter_by_user_agent: [],
|
|
95
95
|
px_css_ref: '',
|
|
96
96
|
px_js_ref: '',
|
|
97
|
-
px_custom_cookie_header: '',
|
|
97
|
+
px_custom_cookie_header: 'x-px-cookies',
|
|
98
98
|
px_custom_logo: '',
|
|
99
|
+
px_graphql_enabled: true,
|
|
100
|
+
px_graphql_routes: ['/graphql'],
|
|
101
|
+
px_sensitive_graphql_operation_names: [],
|
|
102
|
+
px_sensitive_graphql_operation_types: [],
|
|
99
103
|
px_enrich_custom_parameters: null,
|
|
100
104
|
px_proxy_url: '',
|
|
101
105
|
px_jwt_cookie_name: '',
|
|
@@ -165,6 +165,24 @@ export interface IConfiguration<ParamsType extends ConfigurationParams = Configu
|
|
|
165
165
|
* The maximum amount of time to wait before sending asynchronous activities to the collector.
|
|
166
166
|
*/
|
|
167
167
|
readonly activityBatchTimeoutMs: number;
|
|
168
|
+
/**
|
|
169
|
+
* Whether parsing of GraphQL request bodies should be enabled.
|
|
170
|
+
*/
|
|
171
|
+
readonly graphqlEnabled: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Routes that should trigger GraphQL parsing by the enforcer.
|
|
174
|
+
*/
|
|
175
|
+
readonly graphqlRoutes: string[];
|
|
176
|
+
/**
|
|
177
|
+
* An array of GraphQL operation names that should trigger a risk API call
|
|
178
|
+
* even if a valid, unexpired, low-score risk cookie is present.
|
|
179
|
+
*/
|
|
180
|
+
readonly sensitiveGraphqlOperationNames: string[];
|
|
181
|
+
/**
|
|
182
|
+
* An array of GraphQL operation types (e.g., mutation) that should trigger a risk API call
|
|
183
|
+
* even if a valid, unexpired, low-score risk cookie is present.
|
|
184
|
+
*/
|
|
185
|
+
readonly sensitiveGraphqlOperationTypes: string[];
|
|
168
186
|
/**
|
|
169
187
|
* A function returning CustomParameters that will be added to the enforcer activities.
|
|
170
188
|
*/
|
|
@@ -53,6 +53,10 @@ export declare abstract class StaticConfigurationBase<ParamsType extends Configu
|
|
|
53
53
|
get userAgentMaxLength(): number;
|
|
54
54
|
get maxActivityBatchSize(): number;
|
|
55
55
|
get activityBatchTimeoutMs(): number;
|
|
56
|
+
get graphqlEnabled(): boolean;
|
|
57
|
+
get graphqlRoutes(): string[];
|
|
58
|
+
get sensitiveGraphqlOperationNames(): string[];
|
|
59
|
+
get sensitiveGraphqlOperationTypes(): string[];
|
|
56
60
|
get enrichCustomParameters(): CustomParametersFunction;
|
|
57
61
|
get additionalActivityHandler(): AdditionalActivityHandler;
|
|
58
62
|
get altBackendCaptchaUrl(): string;
|
|
@@ -343,6 +343,34 @@ var StaticConfigurationBase = /** @class */ (function () {
|
|
|
343
343
|
enumerable: false,
|
|
344
344
|
configurable: true
|
|
345
345
|
});
|
|
346
|
+
Object.defineProperty(StaticConfigurationBase.prototype, "graphqlEnabled", {
|
|
347
|
+
get: function () {
|
|
348
|
+
return this.configParams.px_graphql_enabled;
|
|
349
|
+
},
|
|
350
|
+
enumerable: false,
|
|
351
|
+
configurable: true
|
|
352
|
+
});
|
|
353
|
+
Object.defineProperty(StaticConfigurationBase.prototype, "graphqlRoutes", {
|
|
354
|
+
get: function () {
|
|
355
|
+
return this.configParams.px_graphql_routes;
|
|
356
|
+
},
|
|
357
|
+
enumerable: false,
|
|
358
|
+
configurable: true
|
|
359
|
+
});
|
|
360
|
+
Object.defineProperty(StaticConfigurationBase.prototype, "sensitiveGraphqlOperationNames", {
|
|
361
|
+
get: function () {
|
|
362
|
+
return this.configParams.px_sensitive_graphql_operation_names;
|
|
363
|
+
},
|
|
364
|
+
enumerable: false,
|
|
365
|
+
configurable: true
|
|
366
|
+
});
|
|
367
|
+
Object.defineProperty(StaticConfigurationBase.prototype, "sensitiveGraphqlOperationTypes", {
|
|
368
|
+
get: function () {
|
|
369
|
+
return this.configParams.px_sensitive_graphql_operation_types;
|
|
370
|
+
},
|
|
371
|
+
enumerable: false,
|
|
372
|
+
configurable: true
|
|
373
|
+
});
|
|
346
374
|
Object.defineProperty(StaticConfigurationBase.prototype, "enrichCustomParameters", {
|
|
347
375
|
get: function () {
|
|
348
376
|
return this.configParams.px_enrich_custom_parameters || null;
|
|
@@ -4,6 +4,7 @@ import { CustomParameters } from '../custom_parameters';
|
|
|
4
4
|
import { FilterReason } from '../filter';
|
|
5
5
|
import { IHttpRequest, HttpHeaders } from '../http';
|
|
6
6
|
import { PXDE } from '../pxde';
|
|
7
|
+
import { GraphQLData } from '../graphql';
|
|
7
8
|
import { IBotDefenderToken, TokenOrigin } from '../risk_token';
|
|
8
9
|
import { VidSource, PassReason, ICookieParser, IUuidGenerator } from '../utils';
|
|
9
10
|
import { IContext, MobileData, RequestData, ResponseData, RiskApiData, ServerData, TlsData } from './IContext';
|
|
@@ -35,21 +36,21 @@ export declare abstract class ContextBase<OptionsType extends ContextBaseOptions
|
|
|
35
36
|
pxde?: PXDE;
|
|
36
37
|
pxdeVerified?: boolean;
|
|
37
38
|
customParameters?: CustomParameters;
|
|
39
|
+
graphqlData?: GraphQLData[];
|
|
38
40
|
protected readonly config: IConfiguration;
|
|
39
41
|
protected constructor(config: IConfiguration, request: IHttpRequest, options?: OptionsType);
|
|
40
42
|
protected abstract createRiskToken(config: IConfiguration, cookies: Record<string, string>, options: OptionsType): IBotDefenderToken;
|
|
41
43
|
protected createRequestData(config: IConfiguration, request: IHttpRequest, cookieParser?: ICookieParser): RequestData;
|
|
44
|
+
protected getCookies(cookieParser: ICookieParser, ...cookieHeaderValues: string[]): Record<string, string>;
|
|
42
45
|
protected extractUserAgentFromHeader(config: IConfiguration, headers: HttpHeaders): string;
|
|
43
46
|
protected extractIpFromHeader(config: IConfiguration, headers: HttpHeaders): string;
|
|
44
47
|
protected isMonitored(config: IConfiguration, requestData: RequestData): boolean;
|
|
45
48
|
protected isSensitive(config: IConfiguration, { url }: RequestData): boolean;
|
|
46
49
|
protected isAllowedToBypassMonitor(config: IConfiguration, requestData: RequestData): boolean;
|
|
47
|
-
completeInitialization(): Promise<void>;
|
|
48
50
|
protected setRiskTokenOnContext(config: IConfiguration, options: OptionsType): void;
|
|
49
51
|
protected setMobileTokenOnContext(config: IConfiguration, mobileToken: string, options: OptionsType): void;
|
|
50
52
|
protected setWebTokenOnContext(config: IConfiguration, options: OptionsType): void;
|
|
51
53
|
protected setCookiesOnContext(): void;
|
|
52
54
|
protected getMobileToken(config: IConfiguration, mobileToken: string, options: OptionsType): IBotDefenderToken;
|
|
53
|
-
protected handleCustomParameters(config: IConfiguration, request: IHttpRequest): Promise<void>;
|
|
54
55
|
get isMobile(): boolean;
|
|
55
56
|
}
|
|
@@ -1,44 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.ContextBase = void 0;
|
|
40
4
|
var block_handler_1 = require("../block_handler");
|
|
41
|
-
var custom_parameters_1 = require("../custom_parameters");
|
|
42
5
|
var http_1 = require("../http");
|
|
43
6
|
var risk_token_1 = require("../risk_token");
|
|
44
7
|
var utils_1 = require("../utils");
|
|
@@ -63,18 +26,28 @@ var ContextBase = /** @class */ (function () {
|
|
|
63
26
|
}
|
|
64
27
|
}
|
|
65
28
|
ContextBase.prototype.createRequestData = function (config, request, cookieParser) {
|
|
66
|
-
var _a;
|
|
29
|
+
var _a, _b;
|
|
67
30
|
if (cookieParser === void 0) { cookieParser = new utils_1.DefaultCookieParser(); }
|
|
68
31
|
var url = (0, utils_1.getDecodedUrl)(request.url);
|
|
69
32
|
var method = request.method;
|
|
70
33
|
var headers = request.headers;
|
|
71
|
-
var
|
|
72
|
-
var cookies = cookieHeaderValue ? cookieParser.parseCookies(cookieHeaderValue) : {};
|
|
34
|
+
var cookies = this.getCookies(cookieParser, (_a = request.headers.get(http_1.COOKIE_HEADER_NAME)) === null || _a === void 0 ? void 0 : _a[0], (_b = request.headers.get(config.customCookieHeader)) === null || _b === void 0 ? void 0 : _b[0]);
|
|
73
35
|
var requestCookieNames = Object.keys(cookies);
|
|
74
36
|
var userAgent = this.extractUserAgentFromHeader(config, headers);
|
|
75
37
|
var ip = this.extractIpFromHeader(config, headers);
|
|
76
38
|
return { url: url, method: method, headers: headers, cookies: cookies, ip: ip, userAgent: userAgent, requestCookieNames: requestCookieNames, request: request };
|
|
77
39
|
};
|
|
40
|
+
ContextBase.prototype.getCookies = function (cookieParser) {
|
|
41
|
+
var cookieHeaderValues = [];
|
|
42
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
43
|
+
cookieHeaderValues[_i - 1] = arguments[_i];
|
|
44
|
+
}
|
|
45
|
+
var cookies = {};
|
|
46
|
+
cookieHeaderValues.forEach(function (value) {
|
|
47
|
+
Object.assign(cookies, value ? cookieParser.parseCookies(value) : null);
|
|
48
|
+
});
|
|
49
|
+
return cookies;
|
|
50
|
+
};
|
|
78
51
|
ContextBase.prototype.extractUserAgentFromHeader = function (config, headers) {
|
|
79
52
|
var _a;
|
|
80
53
|
var userAgent = ((_a = headers === null || headers === void 0 ? void 0 : headers.get(http_1.USER_AGENT_HEADER_NAME)) === null || _a === void 0 ? void 0 : _a[0]) || '';
|
|
@@ -111,18 +84,6 @@ var ContextBase = /** @class */ (function () {
|
|
|
111
84
|
return (config.bypassMonitorHeader &&
|
|
112
85
|
((_a = requestData.headers.get(config.bypassMonitorHeader)) === null || _a === void 0 ? void 0 : _a[0]) === utils_1.BYPASS_MONITOR_HEADER_VALUE);
|
|
113
86
|
};
|
|
114
|
-
ContextBase.prototype.completeInitialization = function () {
|
|
115
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
116
|
-
return __generator(this, function (_a) {
|
|
117
|
-
switch (_a.label) {
|
|
118
|
-
case 0: return [4 /*yield*/, this.handleCustomParameters(this.config, this.requestData.request)];
|
|
119
|
-
case 1:
|
|
120
|
-
_a.sent();
|
|
121
|
-
return [2 /*return*/];
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
87
|
ContextBase.prototype.setRiskTokenOnContext = function (config, options) {
|
|
127
88
|
var _a;
|
|
128
89
|
var mobileToken = (_a = this.requestData.headers.get(utils_1.X_PX_AUTHORIZATION_HEADER_NAME)) === null || _a === void 0 ? void 0 : _a[0];
|
|
@@ -169,31 +130,6 @@ var ContextBase = /** @class */ (function () {
|
|
|
169
130
|
return null;
|
|
170
131
|
}
|
|
171
132
|
};
|
|
172
|
-
ContextBase.prototype.handleCustomParameters = function (config, request) {
|
|
173
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
174
|
-
var _a, _b, _c, e_1;
|
|
175
|
-
return __generator(this, function (_d) {
|
|
176
|
-
switch (_d.label) {
|
|
177
|
-
case 0:
|
|
178
|
-
if (!(config.enrichCustomParameters && typeof config.enrichCustomParameters === 'function')) return [3 /*break*/, 4];
|
|
179
|
-
_d.label = 1;
|
|
180
|
-
case 1:
|
|
181
|
-
_d.trys.push([1, 3, , 4]);
|
|
182
|
-
_a = this;
|
|
183
|
-
_c = (_b = custom_parameters_1.CustomParametersUtils).normalizeCustomParams;
|
|
184
|
-
return [4 /*yield*/, config.enrichCustomParameters(config.toParams(), request)];
|
|
185
|
-
case 2:
|
|
186
|
-
_a.customParameters = _c.apply(_b, [_d.sent()]);
|
|
187
|
-
return [3 /*break*/, 4];
|
|
188
|
-
case 3:
|
|
189
|
-
e_1 = _d.sent();
|
|
190
|
-
config.logger.error("unable to enrich custom params: ".concat(e_1));
|
|
191
|
-
return [3 /*break*/, 4];
|
|
192
|
-
case 4: return [2 /*return*/];
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
};
|
|
197
133
|
Object.defineProperty(ContextBase.prototype, "isMobile", {
|
|
198
134
|
get: function () {
|
|
199
135
|
return this.tokenOrigin === risk_token_1.TokenOrigin.HEADER;
|
|
@@ -6,6 +6,7 @@ import { BlockAction, BlockReason } from '../block_handler';
|
|
|
6
6
|
import { HttpHeaders, HttpMethod, IHttpRequest } from '../http';
|
|
7
7
|
import { CustomParameters } from '../custom_parameters';
|
|
8
8
|
import { PXDE } from '../pxde';
|
|
9
|
+
import { GraphQLData } from '../graphql/model/GraphQLData';
|
|
9
10
|
export declare type RequestData = {
|
|
10
11
|
/**
|
|
11
12
|
* The request URL.
|
|
@@ -253,8 +254,8 @@ export interface IContext {
|
|
|
253
254
|
*/
|
|
254
255
|
customParameters?: CustomParameters;
|
|
255
256
|
/**
|
|
256
|
-
*
|
|
257
|
-
* the request
|
|
257
|
+
* An array of objects with information about the different GraphQL operations
|
|
258
|
+
* parsed from the request.
|
|
258
259
|
*/
|
|
259
|
-
|
|
260
|
+
graphqlData?: GraphQLData[];
|
|
260
261
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { IConfiguration } from '../config';
|
|
2
|
+
import { IContext } from '../context';
|
|
1
3
|
import { CustomParameters } from './CustomParameters';
|
|
2
4
|
export declare namespace CustomParametersUtils {
|
|
5
|
+
const handleCustomParameters: (config: IConfiguration, context: IContext) => Promise<void>;
|
|
3
6
|
const normalizeCustomParams: (customParameters: Record<string, any>) => CustomParameters;
|
|
4
7
|
}
|
|
@@ -1,8 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (_) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.CustomParametersUtils = void 0;
|
|
4
40
|
var CustomParametersUtils;
|
|
5
41
|
(function (CustomParametersUtils) {
|
|
42
|
+
var _this = this;
|
|
43
|
+
CustomParametersUtils.handleCustomParameters = function (config, context) { return __awaiter(_this, void 0, void 0, function () {
|
|
44
|
+
var parameters, e_1;
|
|
45
|
+
return __generator(this, function (_a) {
|
|
46
|
+
switch (_a.label) {
|
|
47
|
+
case 0:
|
|
48
|
+
if (!(config.enrichCustomParameters && typeof config.enrichCustomParameters === 'function')) return [3 /*break*/, 4];
|
|
49
|
+
_a.label = 1;
|
|
50
|
+
case 1:
|
|
51
|
+
_a.trys.push([1, 3, , 4]);
|
|
52
|
+
return [4 /*yield*/, config.enrichCustomParameters(config.toParams(), context.requestData.request)];
|
|
53
|
+
case 2:
|
|
54
|
+
parameters = _a.sent();
|
|
55
|
+
context.customParameters = CustomParametersUtils.normalizeCustomParams(parameters);
|
|
56
|
+
return [3 /*break*/, 4];
|
|
57
|
+
case 3:
|
|
58
|
+
e_1 = _a.sent();
|
|
59
|
+
config.logger.error("unable to enrich custom params: ".concat(e_1));
|
|
60
|
+
return [3 /*break*/, 4];
|
|
61
|
+
case 4: return [2 /*return*/];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}); };
|
|
6
65
|
CustomParametersUtils.normalizeCustomParams = function (customParameters) {
|
|
7
66
|
var normalizedParams = {};
|
|
8
67
|
if (customParameters && typeof customParameters === 'object') {
|
|
@@ -10,6 +10,7 @@ import { ITelemetry } from '../telemetry';
|
|
|
10
10
|
import { IBlockResponseGenerator } from '../block_handler';
|
|
11
11
|
import { TokenVersion } from '../risk_token';
|
|
12
12
|
import { IActivityClient } from '../activities';
|
|
13
|
+
import { IGraphQLParser } from '../graphql';
|
|
13
14
|
export declare type EnforcerBaseOptions = {
|
|
14
15
|
tokenVersion?: TokenVersion;
|
|
15
16
|
dataEnrichment?: IDataEnrichment;
|
|
@@ -20,6 +21,7 @@ export declare type EnforcerBaseOptions = {
|
|
|
20
21
|
hashUtils?: IHashUtils;
|
|
21
22
|
cipherUtils?: ICipherUtils;
|
|
22
23
|
blockGenerator?: IBlockResponseGenerator;
|
|
24
|
+
graphqlParser?: IGraphQLParser;
|
|
23
25
|
} & ({
|
|
24
26
|
httpClient: IHttpClient;
|
|
25
27
|
firstParty?: IFirstParty;
|
|
@@ -43,6 +45,7 @@ export declare abstract class EnforcerBase<EnforceArgs extends any[], Req, Res>
|
|
|
43
45
|
protected riskApiScoreRetriever: IScoreRetriever;
|
|
44
46
|
protected blockGenerator: IBlockResponseGenerator;
|
|
45
47
|
protected activityClient: IActivityClient;
|
|
48
|
+
protected graphQLParser?: IGraphQLParser;
|
|
46
49
|
/**
|
|
47
50
|
* Returns the original Req object in case the module is disabled or an error is thrown.
|
|
48
51
|
* @param args - The EnforceArgs required to enforce the incoming request.
|
|
@@ -65,7 +68,7 @@ export declare abstract class EnforcerBase<EnforceArgs extends any[], Req, Res>
|
|
|
65
68
|
* @returns IContext - The context for the request.
|
|
66
69
|
* @protected
|
|
67
70
|
*/
|
|
68
|
-
protected abstract retrieveContext(req: Req, res: Res, ...args: EnforceArgs): IContext;
|
|
71
|
+
protected abstract retrieveContext(req: Req, res: Res, ...args: EnforceArgs): IContext | null;
|
|
69
72
|
/**
|
|
70
73
|
* Converts the IHttpRequest object into the Req object.
|
|
71
74
|
* @param httpRequest - The IHttpRequest object.
|
|
@@ -118,6 +121,8 @@ export declare abstract class EnforcerBase<EnforceArgs extends any[], Req, Res>
|
|
|
118
121
|
protected handleFirstParty(context: IContext): Promise<IHttpResponse>;
|
|
119
122
|
protected handleFilter(context: IContext): boolean;
|
|
120
123
|
protected handleCompleteContextInitialization(context: IContext): Promise<void>;
|
|
124
|
+
protected handleGraphQL(context: IContext): Promise<void>;
|
|
125
|
+
protected handleEnrichCustomParameters(context: IContext): Promise<void>;
|
|
121
126
|
protected handleTelemetryIfNeeded(context: IContext): Promise<void>;
|
|
122
127
|
protected handlePxde(context: IContext): Promise<void>;
|
|
123
128
|
protected handleCookieRetrieverIfNeeded(context: IContext): Promise<void>;
|
|
@@ -57,6 +57,8 @@ var block_handler_1 = require("../block_handler");
|
|
|
57
57
|
var risk_token_1 = require("../risk_token");
|
|
58
58
|
var risk_api_1 = require("../risk_api");
|
|
59
59
|
var activities_1 = require("../activities");
|
|
60
|
+
var graphql_1 = require("../graphql");
|
|
61
|
+
var custom_parameters_1 = require("../custom_parameters");
|
|
60
62
|
var EnforcerBase = /** @class */ (function () {
|
|
61
63
|
/**
|
|
62
64
|
* The EnforcerBase constructor.
|
|
@@ -72,6 +74,9 @@ var EnforcerBase = /** @class */ (function () {
|
|
|
72
74
|
this.cookieScoreRetriever = options.cookieScoreRetriever || new risk_token_1.RiskTokenScoreRetriever(this.config);
|
|
73
75
|
this.blockGenerator = options.blockGenerator || new block_handler_1.DefaultBlockResponseGenerator(this.config, base64Utils);
|
|
74
76
|
this.dataEnrichment = options.dataEnrichment || new pxde_1.DefaultDataEnrichment(this.config, base64Utils, hashUtils);
|
|
77
|
+
this.graphQLParser = this.config.graphqlEnabled
|
|
78
|
+
? options.graphqlParser || new graphql_1.DefaultGraphQLParser(this.config)
|
|
79
|
+
: null;
|
|
75
80
|
var httpClient = options.httpClient;
|
|
76
81
|
this.firstParty = options.firstParty || new first_party_1.DefaultFirstParty(this.config, httpClient);
|
|
77
82
|
this.telemetry = options.telemetry || new telemetry_1.DefaultTelemetry(this.config, httpClient, base64Utils, hashUtils);
|
|
@@ -151,23 +156,29 @@ var EnforcerBase = /** @class */ (function () {
|
|
|
151
156
|
case 3:
|
|
152
157
|
_a.sent();
|
|
153
158
|
this.config.logger.debug('context initialization complete');
|
|
154
|
-
return [4 /*yield*/, this.
|
|
159
|
+
return [4 /*yield*/, this.handleGraphQL(context)];
|
|
155
160
|
case 4:
|
|
156
161
|
_a.sent();
|
|
157
|
-
return [4 /*yield*/, this.
|
|
162
|
+
return [4 /*yield*/, this.handleEnrichCustomParameters(context)];
|
|
158
163
|
case 5:
|
|
159
164
|
_a.sent();
|
|
160
|
-
return [4 /*yield*/, this.
|
|
165
|
+
return [4 /*yield*/, this.handleTelemetryIfNeeded(context)];
|
|
161
166
|
case 6:
|
|
162
167
|
_a.sent();
|
|
163
|
-
return [4 /*yield*/, this.
|
|
168
|
+
return [4 /*yield*/, this.handlePxde(context)];
|
|
164
169
|
case 7:
|
|
165
170
|
_a.sent();
|
|
166
|
-
return [4 /*yield*/, this.
|
|
171
|
+
return [4 /*yield*/, this.handleCookieRetrieverIfNeeded(context)];
|
|
167
172
|
case 8:
|
|
168
173
|
_a.sent();
|
|
169
|
-
return [4 /*yield*/, this.
|
|
174
|
+
return [4 /*yield*/, this.handleRiskApiIfNeeded(context)];
|
|
170
175
|
case 9:
|
|
176
|
+
_a.sent();
|
|
177
|
+
return [4 /*yield*/, this.handleAdditionalActivityHandler(context)];
|
|
178
|
+
case 10:
|
|
179
|
+
_a.sent();
|
|
180
|
+
return [4 /*yield*/, this.handleBlockResponse(context)];
|
|
181
|
+
case 11:
|
|
171
182
|
httpResponse = _a.sent();
|
|
172
183
|
if (httpResponse) {
|
|
173
184
|
this.config.logger.debug("blocking request due to ".concat(context.blockReason));
|
|
@@ -204,10 +215,33 @@ var EnforcerBase = /** @class */ (function () {
|
|
|
204
215
|
return this.filter.shouldFilter(context);
|
|
205
216
|
};
|
|
206
217
|
EnforcerBase.prototype.handleCompleteContextInitialization = function (context) {
|
|
218
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
219
|
+
return __generator(this, function (_a) {
|
|
220
|
+
return [2 /*return*/];
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
EnforcerBase.prototype.handleGraphQL = function (context) {
|
|
225
|
+
var _a;
|
|
226
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
227
|
+
return __generator(this, function (_b) {
|
|
228
|
+
switch (_b.label) {
|
|
229
|
+
case 0:
|
|
230
|
+
if (!((_a = this.graphQLParser) === null || _a === void 0 ? void 0 : _a.isGraphQLRequest(context))) return [3 /*break*/, 2];
|
|
231
|
+
return [4 /*yield*/, this.graphQLParser.parseGraphQLRequest(context)];
|
|
232
|
+
case 1:
|
|
233
|
+
_b.sent();
|
|
234
|
+
_b.label = 2;
|
|
235
|
+
case 2: return [2 /*return*/];
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
EnforcerBase.prototype.handleEnrichCustomParameters = function (context) {
|
|
207
241
|
return __awaiter(this, void 0, void 0, function () {
|
|
208
242
|
return __generator(this, function (_a) {
|
|
209
243
|
switch (_a.label) {
|
|
210
|
-
case 0: return [4 /*yield*/,
|
|
244
|
+
case 0: return [4 /*yield*/, custom_parameters_1.CustomParametersUtils.handleCustomParameters(this.config, context)];
|
|
211
245
|
case 1:
|
|
212
246
|
_a.sent();
|
|
213
247
|
return [2 /*return*/];
|
|
@@ -153,7 +153,7 @@ var DefaultFirstParty = /** @class */ (function () {
|
|
|
153
153
|
case 1: return [2 /*return*/, _b.sent()];
|
|
154
154
|
case 2:
|
|
155
155
|
e_1 = _b.sent();
|
|
156
|
-
this.config.logger.debug("failed sending first party request to ".concat(url));
|
|
156
|
+
this.config.logger.debug("failed sending first party request to ".concat(url, ": ").concat(e_1));
|
|
157
157
|
return [2 /*return*/, null];
|
|
158
158
|
case 3: return [2 /*return*/];
|
|
159
159
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IContext } from '../context/IContext';
|
|
2
|
+
import { IConfiguration } from '../config';
|
|
3
|
+
import { IGraphQLParser } from './IGraphQLParser';
|
|
4
|
+
export declare class DefaultGraphQLParser implements IGraphQLParser {
|
|
5
|
+
private readonly logger;
|
|
6
|
+
private readonly graphqlRoutes;
|
|
7
|
+
private readonly sensitiveOperationTypes;
|
|
8
|
+
private readonly sensitiveOperationNames;
|
|
9
|
+
constructor(config: IConfiguration);
|
|
10
|
+
isGraphQLRequest({ requestData }: IContext): boolean;
|
|
11
|
+
parseGraphQLRequest(context: IContext): Promise<boolean>;
|
|
12
|
+
private getGraphQLOperationsFromBody;
|
|
13
|
+
private parseGraphQLOperations;
|
|
14
|
+
private parseGraphQlOperation;
|
|
15
|
+
private getOperationNameToTypeMap;
|
|
16
|
+
private getGraphQLData;
|
|
17
|
+
private isSensitiveOperation;
|
|
18
|
+
private extractGraphQLVariableNames;
|
|
19
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (_) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.DefaultGraphQLParser = void 0;
|
|
40
|
+
var http_1 = require("../http");
|
|
41
|
+
var GraphQLOperationType_1 = require("./model/GraphQLOperationType");
|
|
42
|
+
var utils_1 = require("../utils");
|
|
43
|
+
var DefaultGraphQLParser = /** @class */ (function () {
|
|
44
|
+
function DefaultGraphQLParser(config) {
|
|
45
|
+
this.logger = config.logger;
|
|
46
|
+
this.graphqlRoutes = config.graphqlRoutes;
|
|
47
|
+
this.sensitiveOperationNames = config.sensitiveGraphqlOperationNames;
|
|
48
|
+
this.sensitiveOperationTypes = config.sensitiveGraphqlOperationTypes;
|
|
49
|
+
}
|
|
50
|
+
DefaultGraphQLParser.prototype.isGraphQLRequest = function (_a) {
|
|
51
|
+
var requestData = _a.requestData;
|
|
52
|
+
return (requestData.method === http_1.HttpMethod.POST && (0, utils_1.isRouteInPatterns)(requestData.url.pathname, this.graphqlRoutes));
|
|
53
|
+
};
|
|
54
|
+
DefaultGraphQLParser.prototype.parseGraphQLRequest = function (context) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
56
|
+
var graphQLOperations, data, e_1;
|
|
57
|
+
return __generator(this, function (_a) {
|
|
58
|
+
switch (_a.label) {
|
|
59
|
+
case 0:
|
|
60
|
+
_a.trys.push([0, 2, , 3]);
|
|
61
|
+
return [4 /*yield*/, this.getGraphQLOperationsFromBody(context.requestData)];
|
|
62
|
+
case 1:
|
|
63
|
+
graphQLOperations = _a.sent();
|
|
64
|
+
if (!graphQLOperations) {
|
|
65
|
+
this.logger.debug('unable to get graphql operations from request body');
|
|
66
|
+
return [2 /*return*/, false];
|
|
67
|
+
}
|
|
68
|
+
data = this.parseGraphQLOperations(graphQLOperations);
|
|
69
|
+
if (!data || data.length === 0) {
|
|
70
|
+
this.logger.debug('unable to parse graphql operations');
|
|
71
|
+
return [2 /*return*/, false];
|
|
72
|
+
}
|
|
73
|
+
this.logger.debug("".concat(data.length, " graphql operation").concat(data.length === 1 ? '' : 's', " parsed successfully"));
|
|
74
|
+
context.graphqlData = data;
|
|
75
|
+
context.isSensitiveRequest = context.isSensitiveRequest || data.some(function (operation) { return operation.sensitive; });
|
|
76
|
+
return [2 /*return*/, true];
|
|
77
|
+
case 2:
|
|
78
|
+
e_1 = _a.sent();
|
|
79
|
+
this.logger.debug("error parsing graphql request: ".concat(e_1));
|
|
80
|
+
return [2 /*return*/, false];
|
|
81
|
+
case 3: return [2 /*return*/];
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
DefaultGraphQLParser.prototype.getGraphQLOperationsFromBody = function (_a) {
|
|
87
|
+
var request = _a.request;
|
|
88
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
89
|
+
var body;
|
|
90
|
+
return __generator(this, function (_b) {
|
|
91
|
+
switch (_b.label) {
|
|
92
|
+
case 0: return [4 /*yield*/, request.readBody()];
|
|
93
|
+
case 1:
|
|
94
|
+
body = _b.sent();
|
|
95
|
+
if (typeof body === 'string') {
|
|
96
|
+
try {
|
|
97
|
+
body = JSON.parse(body);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
this.logger.debug("unable to parse string body: ".concat(e));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!body || typeof body !== 'object') {
|
|
104
|
+
return [2 /*return*/, null];
|
|
105
|
+
}
|
|
106
|
+
return [2 /*return*/, Array.isArray(body) ? body : [body]];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
DefaultGraphQLParser.prototype.parseGraphQLOperations = function (operations) {
|
|
112
|
+
var _this = this;
|
|
113
|
+
return operations.map(function (operation) { return _this.parseGraphQlOperation(operation); }).filter(function (x) { return x; });
|
|
114
|
+
};
|
|
115
|
+
DefaultGraphQLParser.prototype.parseGraphQlOperation = function (operation) {
|
|
116
|
+
if (!operation.query || typeof operation.query !== 'string') {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
var operationNameToTypeMap = this.getOperationNameToTypeMap(operation.query);
|
|
120
|
+
if (!operationNameToTypeMap) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
return this.getGraphQLData(operationNameToTypeMap, operation);
|
|
124
|
+
};
|
|
125
|
+
DefaultGraphQLParser.prototype.getOperationNameToTypeMap = function (query) {
|
|
126
|
+
var operationTypesString = Object.values(GraphQLOperationType_1.GraphQLOperationType).join('|');
|
|
127
|
+
var pattern = new RegExp("\\s*(".concat(operationTypesString, ")\\s+(\\w+)"), 'gm');
|
|
128
|
+
var match;
|
|
129
|
+
var map = {};
|
|
130
|
+
while ((match = pattern.exec(query)) !== null) {
|
|
131
|
+
var operationType = match[1];
|
|
132
|
+
var operationName = match[2];
|
|
133
|
+
if (map[operationName]) {
|
|
134
|
+
// query contains two operations with the same name which is illegal
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
map[operationName] = operationType;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return map;
|
|
142
|
+
};
|
|
143
|
+
DefaultGraphQLParser.prototype.getGraphQLData = function (operationNameToTypeMap, operation) {
|
|
144
|
+
var name = operation.operationName ||
|
|
145
|
+
(Object.keys(operationNameToTypeMap).length === 1 ? Object.keys(operationNameToTypeMap)[0] : undefined);
|
|
146
|
+
var type = operationNameToTypeMap[name];
|
|
147
|
+
if (!type && /^\s*{/.test(operation.query)) {
|
|
148
|
+
type = GraphQLOperationType_1.GraphQLOperationType.QUERY;
|
|
149
|
+
}
|
|
150
|
+
if (!type) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
var data = { name: name, type: type };
|
|
154
|
+
if (this.isSensitiveOperation(name, type)) {
|
|
155
|
+
data.sensitive = true;
|
|
156
|
+
}
|
|
157
|
+
if (operation.variables && typeof operation.variables === 'object') {
|
|
158
|
+
data.variables = this.extractGraphQLVariableNames(operation.variables);
|
|
159
|
+
}
|
|
160
|
+
return data;
|
|
161
|
+
};
|
|
162
|
+
DefaultGraphQLParser.prototype.isSensitiveOperation = function (operationName, operationType) {
|
|
163
|
+
return (this.sensitiveOperationTypes.some(function (type) { return type === operationType; }) ||
|
|
164
|
+
this.sensitiveOperationNames.some(function (name) { return name === operationName; }));
|
|
165
|
+
};
|
|
166
|
+
DefaultGraphQLParser.prototype.extractGraphQLVariableNames = function (variables) {
|
|
167
|
+
var processVariables = function (variablesObj, prefix) {
|
|
168
|
+
return Object.entries(variablesObj).reduce(function (total, _a) {
|
|
169
|
+
var key = _a[0], value = _a[1];
|
|
170
|
+
if (!value || typeof value !== 'object' || Object.keys(value).length === 0) {
|
|
171
|
+
total.push(prefix + key);
|
|
172
|
+
return total;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
return total.concat(processVariables(value, "".concat(prefix).concat(key, ".")));
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
};
|
|
179
|
+
return processVariables(variables, '');
|
|
180
|
+
};
|
|
181
|
+
return DefaultGraphQLParser;
|
|
182
|
+
}());
|
|
183
|
+
exports.DefaultGraphQLParser = DefaultGraphQLParser;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { GraphQLOperationType } from './model/GraphQLOperationType';
|
|
2
|
+
export { GraphQLOperation } from './model/GraphQLOperation';
|
|
3
|
+
export { GraphQLData } from './model/GraphQLData';
|
|
4
|
+
export { IGraphQLParser } from './IGraphQLParser';
|
|
5
|
+
export { DefaultGraphQLParser } from './DefaultGraphQLParser';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultGraphQLParser = exports.GraphQLOperationType = void 0;
|
|
4
|
+
var GraphQLOperationType_1 = require("./model/GraphQLOperationType");
|
|
5
|
+
Object.defineProperty(exports, "GraphQLOperationType", { enumerable: true, get: function () { return GraphQLOperationType_1.GraphQLOperationType; } });
|
|
6
|
+
var DefaultGraphQLParser_1 = require("./DefaultGraphQLParser");
|
|
7
|
+
Object.defineProperty(exports, "DefaultGraphQLParser", { enumerable: true, get: function () { return DefaultGraphQLParser_1.DefaultGraphQLParser; } });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GraphQLOperationType = void 0;
|
|
4
|
+
var GraphQLOperationType;
|
|
5
|
+
(function (GraphQLOperationType) {
|
|
6
|
+
GraphQLOperationType["QUERY"] = "query";
|
|
7
|
+
GraphQLOperationType["MUTATION"] = "mutation";
|
|
8
|
+
GraphQLOperationType["SUBSCRIPTION"] = "subscription";
|
|
9
|
+
})(GraphQLOperationType = exports.GraphQLOperationType || (exports.GraphQLOperationType = {}));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare type HttpHeadersInit = Record<string, string[]>;
|
|
2
2
|
export declare class HttpHeaders {
|
|
3
3
|
private readonly headers;
|
|
4
|
+
static from(headers: Headers): HttpHeaders;
|
|
4
5
|
/**
|
|
5
6
|
* Constructs a new instance of the HttpHeaders class.
|
|
6
7
|
* @param init - Optional header names and values with which to initialize the HttpHeaders instance.
|
|
@@ -41,11 +42,12 @@ export declare class HttpHeaders {
|
|
|
41
42
|
* @returns object - An object representing the current state of the HttpHeaders instance. The keys are the header
|
|
42
43
|
* names (all lowercase), and the values are arrays of all the associated header values.
|
|
43
44
|
*/
|
|
44
|
-
toObject(): Record<string, string[]>;
|
|
45
|
+
toObject(joinDelimiter?: string): Record<string, string | string[]>;
|
|
45
46
|
/**
|
|
46
47
|
* Iterates through all headers and applies a callback function to each one.
|
|
47
48
|
* @param callbackFn - The callback function to be applied on every header.
|
|
48
49
|
*/
|
|
49
50
|
forEach(callbackFn: (values: readonly string[], name: string) => void): void;
|
|
50
51
|
private toKey;
|
|
52
|
+
entries(delimiter?: string): [string, string][];
|
|
51
53
|
}
|
|
@@ -19,6 +19,13 @@ var HttpHeaders = /** @class */ (function () {
|
|
|
19
19
|
var _this = this;
|
|
20
20
|
this.headers = init ? new Map(Object.keys(init).map(function (name) { return [_this.toKey(name), init[name]]; })) : new Map();
|
|
21
21
|
}
|
|
22
|
+
HttpHeaders.from = function (headers) {
|
|
23
|
+
var ret = new HttpHeaders();
|
|
24
|
+
headers.forEach(function (value, key) {
|
|
25
|
+
ret.append(key, value);
|
|
26
|
+
});
|
|
27
|
+
return ret;
|
|
28
|
+
};
|
|
22
29
|
/**
|
|
23
30
|
* Retrieves the values associated with the provided header name. If no header exists, it returns undefined.
|
|
24
31
|
* @param name - The case-insensitive header name.
|
|
@@ -84,10 +91,10 @@ var HttpHeaders = /** @class */ (function () {
|
|
|
84
91
|
* @returns object - An object representing the current state of the HttpHeaders instance. The keys are the header
|
|
85
92
|
* names (all lowercase), and the values are arrays of all the associated header values.
|
|
86
93
|
*/
|
|
87
|
-
HttpHeaders.prototype.toObject = function () {
|
|
94
|
+
HttpHeaders.prototype.toObject = function (joinDelimiter) {
|
|
88
95
|
var obj = {};
|
|
89
96
|
this.forEach(function (values, name) {
|
|
90
|
-
obj[name] = __spreadArray([], values, true);
|
|
97
|
+
obj[name] = joinDelimiter ? values.join(joinDelimiter) : __spreadArray([], values, true);
|
|
91
98
|
});
|
|
92
99
|
return obj;
|
|
93
100
|
};
|
|
@@ -101,6 +108,16 @@ var HttpHeaders = /** @class */ (function () {
|
|
|
101
108
|
HttpHeaders.prototype.toKey = function (name) {
|
|
102
109
|
return name.toLowerCase();
|
|
103
110
|
};
|
|
111
|
+
HttpHeaders.prototype.entries = function (delimiter) {
|
|
112
|
+
if (delimiter === void 0) { delimiter = ','; }
|
|
113
|
+
var ret = [];
|
|
114
|
+
this.headers.forEach(function (values, headerName) {
|
|
115
|
+
if (values === null || values === void 0 ? void 0 : values.length) {
|
|
116
|
+
ret.push([headerName, values.join(delimiter)]);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return ret;
|
|
120
|
+
};
|
|
104
121
|
return HttpHeaders;
|
|
105
122
|
}());
|
|
106
123
|
exports.HttpHeaders = HttpHeaders;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __exportStar(require("./custom_parameters"), exports);
|
|
|
23
23
|
__exportStar(require("./enforcer"), exports);
|
|
24
24
|
__exportStar(require("./filter"), exports);
|
|
25
25
|
__exportStar(require("./first_party"), exports);
|
|
26
|
+
__exportStar(require("./graphql"), exports);
|
|
26
27
|
__exportStar(require("./http"), exports);
|
|
27
28
|
__exportStar(require("./logger"), exports);
|
|
28
29
|
__exportStar(require("./pxde"), exports);
|
|
@@ -37,7 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.PostRiskApiClient = void 0;
|
|
40
|
-
var
|
|
40
|
+
var risk_token_1 = require("../risk_token");
|
|
41
41
|
var http_1 = require("../http");
|
|
42
42
|
var utils_1 = require("../utils");
|
|
43
43
|
var S2SCallReason_1 = require("./S2SCallReason");
|
|
@@ -136,7 +136,7 @@ var PostRiskApiClient = /** @class */ (function () {
|
|
|
136
136
|
http_method: context.requestData.method,
|
|
137
137
|
http_version: context.requestData.httpVersion,
|
|
138
138
|
risk_mode: context.isMonitoredRequest ? utils_1.ModuleMode.MONITOR : utils_1.ModuleMode.ACTIVE_BLOCKING,
|
|
139
|
-
cookie_origin: context.tokenOrigin ||
|
|
139
|
+
cookie_origin: context.tokenOrigin || risk_token_1.TokenOrigin.COOKIE,
|
|
140
140
|
request_cookie_names: context.requestData.requestCookieNames,
|
|
141
141
|
request_id: context.requestId,
|
|
142
142
|
},
|
|
@@ -169,6 +169,7 @@ var PostRiskApiClient = /** @class */ (function () {
|
|
|
169
169
|
PostRiskApiClient.prototype.addOptionalRiskFieldsToAdditional = function (riskActivity, context) {
|
|
170
170
|
(0, utils_1.transferExistingProperties)(context, riskActivity.additional, {
|
|
171
171
|
vidSource: 'enforcer_vid_source',
|
|
172
|
+
graphqlData: 'graphql_operations',
|
|
172
173
|
});
|
|
173
174
|
(0, utils_1.transferExistingProperties)(context.serverData, riskActivity.additional, {
|
|
174
175
|
region: 'server_info_region',
|
|
@@ -197,11 +198,13 @@ var PostRiskApiClient = /** @class */ (function () {
|
|
|
197
198
|
PostRiskApiClient.prototype.addCookieRiskFieldsToAdditional = function (riskActivity, _a) {
|
|
198
199
|
var riskToken = _a.riskToken;
|
|
199
200
|
if (riskToken) {
|
|
200
|
-
riskActivity.additional.px_orig_cookie = riskToken.getCookieString();
|
|
201
201
|
if (riskToken.isValid()) {
|
|
202
202
|
riskActivity.additional.px_cookie = riskToken.getPayloadString();
|
|
203
203
|
riskActivity.additional.px_cookie_hmac = riskToken.hmac;
|
|
204
204
|
}
|
|
205
|
+
else {
|
|
206
|
+
riskActivity.additional.px_orig_cookie = riskToken.getCookieString();
|
|
207
|
+
}
|
|
205
208
|
}
|
|
206
209
|
};
|
|
207
210
|
PostRiskApiClient.prototype.formatRiskHeadersField = function (headers) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ModuleMode, VidSource } from '../../utils';
|
|
2
2
|
import { TokenOrigin } from '../../risk_token';
|
|
3
3
|
import { CustomParameters } from '../../custom_parameters';
|
|
4
|
+
import { GraphQLData } from '../../graphql/';
|
|
4
5
|
import { S2SCallReason } from '../S2SCallReason';
|
|
5
6
|
export declare type HeaderEntry = {
|
|
6
7
|
name: string;
|
|
@@ -40,6 +41,7 @@ export declare type RiskAdditionalData = {
|
|
|
40
41
|
cross_tab_session?: string;
|
|
41
42
|
app_user_id?: string;
|
|
42
43
|
jwt_additional_fields?: string[];
|
|
44
|
+
graphql_operations?: GraphQLData[];
|
|
43
45
|
} & CustomParameters;
|
|
44
46
|
export declare type RiskActivity = {
|
|
45
47
|
vid?: string;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { RiskStatus } from './RiskStatus';
|
|
2
2
|
import { PXDE } from '../../pxde';
|
|
3
|
+
import { BlockAction } from '../../block_handler';
|
|
3
4
|
export declare type RiskResponseV2 = {
|
|
4
5
|
status: RiskStatus;
|
|
5
6
|
cookie_cfg_block_result?: '0' | '1';
|
|
7
|
+
action?: BlockAction;
|
|
6
8
|
uuid?: string;
|
|
7
9
|
pxhd?: string;
|
|
8
10
|
message?: string;
|
|
@@ -35,6 +35,7 @@ var RiskResponseV2Handler = /** @class */ (function (_super) {
|
|
|
35
35
|
(0, utils_1.transferExistingProperties)(riskResponse, context, {
|
|
36
36
|
uuid: 'uuid',
|
|
37
37
|
pxhd: 'pxhd',
|
|
38
|
+
action: 'blockAction',
|
|
38
39
|
data_enrichment: 'pxde',
|
|
39
40
|
});
|
|
40
41
|
if (riskResponse.data_enrichment) {
|
package/lib/utils/constants.d.ts
CHANGED
|
@@ -7,4 +7,4 @@ export declare const BYPASS_MONITOR_HEADER_VALUE = "1";
|
|
|
7
7
|
export declare const X_PX_AUTHORIZATION_HEADER_NAME = "x-px-authorization";
|
|
8
8
|
export declare const X_PX_ORIGINAL_TOKEN_HEADER_NAME = "x-px-original-token";
|
|
9
9
|
export declare const X_PX_BYPASS_REASON_HEADER_NAME = "x-px-bypass-reason";
|
|
10
|
-
export declare const CORE_MODULE_VERSION = "JS Core 0.
|
|
10
|
+
export declare const CORE_MODULE_VERSION = "JS Core 0.3.0";
|
package/lib/utils/constants.js
CHANGED
|
@@ -10,4 +10,4 @@ exports.BYPASS_MONITOR_HEADER_VALUE = '1';
|
|
|
10
10
|
exports.X_PX_AUTHORIZATION_HEADER_NAME = 'x-px-authorization';
|
|
11
11
|
exports.X_PX_ORIGINAL_TOKEN_HEADER_NAME = 'x-px-original-token';
|
|
12
12
|
exports.X_PX_BYPASS_REASON_HEADER_NAME = 'x-px-bypass-reason';
|
|
13
|
-
exports.CORE_MODULE_VERSION = 'JS Core 0.
|
|
13
|
+
exports.CORE_MODULE_VERSION = 'JS Core 0.3.0';
|
package/lib/utils/utils.js
CHANGED
|
@@ -104,7 +104,7 @@ var isRouteMatch = function (route, pattern) {
|
|
|
104
104
|
if (!route || !pattern) {
|
|
105
105
|
return false;
|
|
106
106
|
}
|
|
107
|
-
if (pattern instanceof RegExp &&
|
|
107
|
+
if (pattern instanceof RegExp && pattern.test(route)) {
|
|
108
108
|
return true;
|
|
109
109
|
}
|
|
110
110
|
if (typeof pattern === 'string' && route.startsWith(pattern)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "perimeterx-js-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"core-js": "^3.19.1",
|
|
40
40
|
"eslint": "^8.25.0",
|
|
41
41
|
"eslint-config-prettier": "^8.5.0",
|
|
42
|
-
"eslint-plugin-no-loops": "^0.3.0",
|
|
43
42
|
"eslint-plugin-prettier": "^4.2.1",
|
|
44
43
|
"husky": "^8.0.3",
|
|
45
44
|
"lint-staged": "^13.1.0",
|