homebridge-adt-pulse 3.3.0 → 3.3.5
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/README.md +2 -6
- package/build/config-ui/public/assets/complete-logo-C1QwzyYf.png +0 -0
- package/build/config-ui/public/assets/index-BX0lTpP2.js +66 -0
- package/build/config-ui/public/assets/setup-logo-4wW8y1cj.png +0 -0
- package/build/config-ui/public/favicon.ico +0 -0
- package/build/config-ui/public/index.html +14 -0
- package/build/config-ui/public/style.css +4 -0
- package/build/config-ui/server.js +255 -0
- package/build/config-ui/server.js.map +1 -0
- package/build/lib/api.js +178 -174
- package/build/lib/api.js.map +1 -1
- package/build/lib/auth.js +1130 -0
- package/build/lib/auth.js.map +1 -0
- package/build/lib/detect.js +99 -97
- package/build/lib/detect.js.map +1 -1
- package/build/lib/fake.js +563 -0
- package/build/lib/fake.js.map +1 -0
- package/build/lib/items.js +15 -58
- package/build/lib/items.js.map +1 -1
- package/build/lib/platform.js +6 -3
- package/build/lib/platform.js.map +1 -1
- package/build/lib/regex.js +12 -1
- package/build/lib/regex.js.map +1 -1
- package/build/lib/schema.js +99 -1
- package/build/lib/schema.js.map +1 -1
- package/build/lib/utility.js +72 -121
- package/build/lib/utility.js.map +1 -1
- package/build/scripts/repl.js +59 -29
- package/build/scripts/repl.js.map +1 -1
- package/build/scripts/test-api.js +7 -7
- package/build/scripts/test-api.js.map +1 -1
- package/config.schema.json +14 -8
- package/package.json +40 -22
|
@@ -0,0 +1,1130 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { wrapper } from 'axios-cookiejar-support';
|
|
3
|
+
import { JSDOM } from 'jsdom';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import { serializeError } from 'serialize-error';
|
|
6
|
+
import { CookieJar } from 'tough-cookie';
|
|
7
|
+
import { detectGlobalDebugParser, detectGlobalPortalVersion } from './detect.js';
|
|
8
|
+
import { generateFakeDynatracePCHeaderValue, generateFakeLoginFingerprint } from './fake.js';
|
|
9
|
+
import { objectKeyClientType, objectKeyLocale, objectKeyLogin, objectKeyPreAuthToken, objectKeySat, requestPathAccessSignIn, requestPathAccessSignInEXxPartnerAdt, requestPathMfaMfaSignInWorkflowChallenge, requestPathNgaServRunRraProxyHrefRestAdtUiClientMultiFactorAuthAddTrustedDeviceSatXx, requestPathNgaServRunRraProxyHrefRestAdtUiClientMultiFactorAuthRequestOtpForRegisteredPropertySatXx, requestPathNgaServRunRraProxyHrefRestAdtUiClientMultiFactorAuthValidateOtpSatXx, requestPathNgaServRunRraProxyHrefRestIcontrolUiClientMultiFactorAuthSatXx, requestPathNgaServRunRraProxyOnlyClientMultiFactorAuthExcludeSatXxHrefRestAdtUiUpdatesSatXx, requestPathSummarySummary, requestPathSystemSystem, textOneTimePasscode, } from './regex.js';
|
|
10
|
+
import { multiFactorAuth, otpResponse } from './schema.js';
|
|
11
|
+
import { debugLog, fetchErrorMessage, findNullKeys, generateHash, parseMultiFactorMethods, parseMultiFactorTrustedDevices, parseSensorsTable, stackTracer, } from './utility.js';
|
|
12
|
+
export class ADTPulseAuth {
|
|
13
|
+
#connection;
|
|
14
|
+
#credentials;
|
|
15
|
+
#internal;
|
|
16
|
+
#session;
|
|
17
|
+
constructor(config, internalConfig) {
|
|
18
|
+
this.#connection = {
|
|
19
|
+
subdomain: config.subdomain,
|
|
20
|
+
};
|
|
21
|
+
this.#credentials = {
|
|
22
|
+
fingerprint: generateFakeLoginFingerprint(),
|
|
23
|
+
password: config.password,
|
|
24
|
+
username: config.username,
|
|
25
|
+
};
|
|
26
|
+
this.#internal = {
|
|
27
|
+
baseUrl: internalConfig.baseUrl ?? `https://${this.#connection.subdomain}.adtpulse.com`,
|
|
28
|
+
debug: internalConfig.debug ?? false,
|
|
29
|
+
logger: internalConfig.logger ?? null,
|
|
30
|
+
reportedHashes: [],
|
|
31
|
+
};
|
|
32
|
+
this.#session = {
|
|
33
|
+
httpClient: wrapper(axios.create({
|
|
34
|
+
jar: new CookieJar(),
|
|
35
|
+
validateStatus: () => true,
|
|
36
|
+
})),
|
|
37
|
+
mfa: {
|
|
38
|
+
clientType: null,
|
|
39
|
+
locale: null,
|
|
40
|
+
login: null,
|
|
41
|
+
preAuthToken: null,
|
|
42
|
+
satCode: null,
|
|
43
|
+
token: null,
|
|
44
|
+
trustedDevices: [],
|
|
45
|
+
verificationMethods: [],
|
|
46
|
+
},
|
|
47
|
+
portalVersion: null,
|
|
48
|
+
status: 'logged-out',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async getVerificationMethods() {
|
|
52
|
+
let errorObject;
|
|
53
|
+
if (this.#internal.debug) {
|
|
54
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Attempting to retrieve verification methods from "${this.#internal.baseUrl}"`);
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const sessions = {};
|
|
58
|
+
if (this.#session.status === 'complete'
|
|
59
|
+
|| this.#session.status === 'not-required') {
|
|
60
|
+
if (this.#internal.debug) {
|
|
61
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', 'Already retrieved verification methods');
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
65
|
+
success: true,
|
|
66
|
+
info: {
|
|
67
|
+
methods: this.#session.mfa.verificationMethods,
|
|
68
|
+
status: this.#session.status,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
sessions.axiosIndex = await this.#session.httpClient.get(`${this.#internal.baseUrl}/`, this.getRequestConfig());
|
|
73
|
+
if (sessions.axiosIndex.status >= 400) {
|
|
74
|
+
if (this.#internal.debug) {
|
|
75
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', `The remote server responded with a HTTP ${sessions.axiosIndex.status} status code`);
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
79
|
+
success: false,
|
|
80
|
+
info: {
|
|
81
|
+
message: `The remote server responded with a HTTP ${sessions.axiosIndex.status} status code`,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (typeof sessions.axiosIndex?.request === 'undefined') {
|
|
86
|
+
if (this.#internal.debug) {
|
|
87
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'The HTTP client responded without the "request" object');
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
91
|
+
success: false,
|
|
92
|
+
info: {
|
|
93
|
+
message: 'The HTTP client responded without the "request" object',
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const axiosIndexRequestPath = sessions.axiosIndex.request.path;
|
|
98
|
+
const axiosIndexRequestPathValid = requestPathAccessSignIn.test(axiosIndexRequestPath);
|
|
99
|
+
if (this.#internal.debug) {
|
|
100
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Request path ➜ ${axiosIndexRequestPath}`);
|
|
101
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Request path valid ➜ ${axiosIndexRequestPathValid}`);
|
|
102
|
+
}
|
|
103
|
+
if (!axiosIndexRequestPathValid) {
|
|
104
|
+
if (this.#internal.debug) {
|
|
105
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', `"${axiosIndexRequestPath} is not the sign-in page`);
|
|
106
|
+
}
|
|
107
|
+
this.handleLoginFailure(axiosIndexRequestPath, sessions.axiosIndex);
|
|
108
|
+
return {
|
|
109
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
110
|
+
success: false,
|
|
111
|
+
info: {
|
|
112
|
+
message: `"${axiosIndexRequestPath} is not the sign-in page`,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const loginForm = new URLSearchParams();
|
|
117
|
+
loginForm.append('usernameForm', this.#credentials.username);
|
|
118
|
+
loginForm.append('passwordForm', this.#credentials.password);
|
|
119
|
+
loginForm.append('sun', 'yes');
|
|
120
|
+
loginForm.append('networkid', '');
|
|
121
|
+
loginForm.append('fingerprint', this.#credentials.fingerprint);
|
|
122
|
+
this.#session.portalVersion = axiosIndexRequestPath.replace(requestPathAccessSignIn, '$2');
|
|
123
|
+
await this.newInformationDispatcher('portal-version', { version: this.#session.portalVersion });
|
|
124
|
+
sessions.axiosSignIn = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/access/signin.jsp?e=ns&partner=adt`, loginForm, this.getRequestConfig({
|
|
125
|
+
headers: {
|
|
126
|
+
'Cache-Control': 'max-age=0',
|
|
127
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
128
|
+
Origin: this.#internal.baseUrl,
|
|
129
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/access/signin.jsp?e=ns&partner=adt`,
|
|
130
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
131
|
+
},
|
|
132
|
+
}));
|
|
133
|
+
if (sessions.axiosSignIn.status >= 400) {
|
|
134
|
+
if (this.#internal.debug) {
|
|
135
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', `The remote server responded with a HTTP ${sessions.axiosSignIn.status} status code`);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
139
|
+
success: false,
|
|
140
|
+
info: {
|
|
141
|
+
message: `The remote server responded with a HTTP ${sessions.axiosSignIn.status} status code`,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (typeof sessions.axiosSignIn?.request === 'undefined') {
|
|
146
|
+
if (this.#internal.debug) {
|
|
147
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'The HTTP client responded without the "request" object');
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
151
|
+
success: false,
|
|
152
|
+
info: {
|
|
153
|
+
message: 'The HTTP client responded without the "request" object',
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const axiosSignInRequestPath = sessions.axiosSignIn.request.path;
|
|
158
|
+
const axiosSignInRequestPathValid = requestPathMfaMfaSignInWorkflowChallenge.test(axiosSignInRequestPath) || requestPathSummarySummary.test(axiosSignInRequestPath);
|
|
159
|
+
if (this.#internal.debug) {
|
|
160
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Request path ➜ ${axiosSignInRequestPath}`);
|
|
161
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Request path valid ➜ ${axiosSignInRequestPathValid}`);
|
|
162
|
+
}
|
|
163
|
+
if (requestPathSummarySummary.test(axiosSignInRequestPath)) {
|
|
164
|
+
if (this.#internal.debug) {
|
|
165
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Verification methods not required from "${this.#internal.baseUrl}"`);
|
|
166
|
+
}
|
|
167
|
+
this.#session.status = 'not-required';
|
|
168
|
+
return {
|
|
169
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
170
|
+
success: true,
|
|
171
|
+
info: {
|
|
172
|
+
methods: this.#session.mfa.verificationMethods,
|
|
173
|
+
status: this.#session.status,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (requestPathAccessSignInEXxPartnerAdt.test(axiosSignInRequestPath)) {
|
|
178
|
+
if (this.#internal.debug) {
|
|
179
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'Invalid username and/or password');
|
|
180
|
+
}
|
|
181
|
+
this.handleLoginFailure(axiosSignInRequestPath, sessions.axiosSignIn);
|
|
182
|
+
return {
|
|
183
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
184
|
+
success: false,
|
|
185
|
+
info: {
|
|
186
|
+
message: 'Invalid username and/or password',
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (!axiosSignInRequestPathValid) {
|
|
191
|
+
if (this.#internal.debug) {
|
|
192
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', `"${axiosSignInRequestPath}" is not the workflow challenge page`);
|
|
193
|
+
}
|
|
194
|
+
this.handleLoginFailure(axiosSignInRequestPath, sessions.axiosSignIn);
|
|
195
|
+
return {
|
|
196
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
197
|
+
success: false,
|
|
198
|
+
info: {
|
|
199
|
+
message: `"${axiosSignInRequestPath}" is not the workflow challenge page`,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
if (typeof sessions.axiosSignIn.data !== 'string') {
|
|
204
|
+
if (this.#internal.debug) {
|
|
205
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'The response body of the workflow challenge page is not of type "string"');
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
209
|
+
success: false,
|
|
210
|
+
info: {
|
|
211
|
+
message: 'The response body of the workflow challenge page is not of type "string"',
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const matchClientType = sessions.axiosSignIn.data.match(objectKeyClientType);
|
|
216
|
+
const matchLocale = sessions.axiosSignIn.data.match(objectKeyLocale);
|
|
217
|
+
const matchLogin = sessions.axiosSignIn.data.match(objectKeyLogin);
|
|
218
|
+
const matchPreAuthToken = sessions.axiosSignIn.data.match(objectKeyPreAuthToken);
|
|
219
|
+
const matchSatCode = sessions.axiosSignIn.data.match(objectKeySat);
|
|
220
|
+
this.#session.mfa.clientType = (matchClientType !== null && matchClientType.length >= 2) ? matchClientType[1] : null;
|
|
221
|
+
this.#session.mfa.locale = (matchLocale !== null && matchLocale.length >= 2) ? matchLocale[1] : null;
|
|
222
|
+
this.#session.mfa.login = (matchLogin !== null && matchLogin.length >= 2) ? matchLogin[1] : null;
|
|
223
|
+
this.#session.mfa.preAuthToken = (matchPreAuthToken !== null && matchPreAuthToken.length >= 2) ? matchPreAuthToken[1] : null;
|
|
224
|
+
this.#session.mfa.satCode = (matchSatCode !== null && matchSatCode.length >= 2) ? matchSatCode[1] : null;
|
|
225
|
+
if (this.#session.mfa.clientType === null
|
|
226
|
+
|| this.#session.mfa.locale === null
|
|
227
|
+
|| this.#session.mfa.login === null
|
|
228
|
+
|| this.#session.mfa.preAuthToken === null
|
|
229
|
+
|| this.#session.mfa.satCode === null) {
|
|
230
|
+
if (this.#internal.debug) {
|
|
231
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'Failed to retrieve required MFA details from the workflow challenge page');
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
235
|
+
success: false,
|
|
236
|
+
info: {
|
|
237
|
+
message: 'Failed to retrieve required MFA details from the workflow challenge page',
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
sessions.axiosMethods = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/nga/serv/RunRRAProxy?href=rest/icontrol/ui/client/multiFactorAuth&sat=${this.#session.mfa.satCode}`, this.getRequestConfig({
|
|
242
|
+
headers: {
|
|
243
|
+
Accept: 'application/json',
|
|
244
|
+
'Content-Type': undefined,
|
|
245
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/mfa/mfaSignIn.jsp?workflow=challenge`,
|
|
246
|
+
'Sec-Fetch-Dest': 'empty',
|
|
247
|
+
'Sec-Fetch-Mode': 'cors',
|
|
248
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
249
|
+
'Sec-Fetch-User': undefined,
|
|
250
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
251
|
+
'X-clientType': this.#session.mfa.clientType,
|
|
252
|
+
'X-format': 'json',
|
|
253
|
+
'X-locale': this.#session.mfa.locale,
|
|
254
|
+
'X-login': this.#session.mfa.login,
|
|
255
|
+
'X-preAuthToken': this.#session.mfa.preAuthToken,
|
|
256
|
+
'X-version': '7.0',
|
|
257
|
+
'x-dtpc': generateFakeDynatracePCHeaderValue('multi-factor'),
|
|
258
|
+
},
|
|
259
|
+
}));
|
|
260
|
+
if (sessions.axiosMethods.status >= 400) {
|
|
261
|
+
if (this.#internal.debug) {
|
|
262
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', `The remote server responded with a HTTP ${sessions.axiosMethods.status} status code`);
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
266
|
+
success: false,
|
|
267
|
+
info: {
|
|
268
|
+
message: `The remote server responded with a HTTP ${sessions.axiosMethods.status} status code`,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (typeof sessions.axiosMethods?.request === 'undefined') {
|
|
273
|
+
if (this.#internal.debug) {
|
|
274
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'The HTTP client responded without the "request" object');
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
278
|
+
success: false,
|
|
279
|
+
info: {
|
|
280
|
+
message: 'The HTTP client responded without the "request" object',
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
const axiosMethodsRequestPath = sessions.axiosMethods.request.path;
|
|
285
|
+
const axiosMethodsRequestPathValid = requestPathNgaServRunRraProxyHrefRestIcontrolUiClientMultiFactorAuthSatXx.test(axiosMethodsRequestPath);
|
|
286
|
+
if (this.#internal.debug) {
|
|
287
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Request path ➜ ${axiosMethodsRequestPath}`);
|
|
288
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'info', `Request path valid ➜ ${axiosMethodsRequestPathValid}`);
|
|
289
|
+
}
|
|
290
|
+
if (!axiosMethodsRequestPathValid) {
|
|
291
|
+
if (this.#internal.debug) {
|
|
292
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', `"${axiosMethodsRequestPath}" is not the MFA auth page`);
|
|
293
|
+
}
|
|
294
|
+
this.handleLoginFailure(axiosMethodsRequestPath, sessions.axiosMethods);
|
|
295
|
+
return {
|
|
296
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
297
|
+
success: false,
|
|
298
|
+
info: {
|
|
299
|
+
message: `"${axiosMethodsRequestPath}" is not the MFA auth page`,
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
const parsedMethods = multiFactorAuth.safeParse(sessions.axiosMethods.data);
|
|
304
|
+
if (!parsedMethods.success) {
|
|
305
|
+
if (this.#internal.debug) {
|
|
306
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'The response body of the MFA auth page is invalid');
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
310
|
+
success: false,
|
|
311
|
+
info: {
|
|
312
|
+
message: 'The response body of the MFA auth page is invalid',
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
const parsedMultiFactorMethods = parseMultiFactorMethods(parsedMethods.data);
|
|
317
|
+
if (parsedMultiFactorMethods.length === 0) {
|
|
318
|
+
if (this.#internal.debug) {
|
|
319
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'Failed to retrieve verification methods');
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
323
|
+
success: false,
|
|
324
|
+
info: {
|
|
325
|
+
message: 'Failed to retrieve verification methods',
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
this.#session.mfa.verificationMethods = parsedMultiFactorMethods;
|
|
330
|
+
this.#session.status = 'complete';
|
|
331
|
+
if (this.#internal.debug) {
|
|
332
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'success', `Successfully retrieved verification methods from "${this.#internal.baseUrl}"`);
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
336
|
+
success: true,
|
|
337
|
+
info: {
|
|
338
|
+
methods: parsedMultiFactorMethods,
|
|
339
|
+
status: this.#session.status,
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
errorObject = serializeError(error);
|
|
345
|
+
}
|
|
346
|
+
if (this.#internal.debug) {
|
|
347
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getVerificationMethods()', 'error', 'Method encountered an error during execution');
|
|
348
|
+
stackTracer('serialize-error', errorObject);
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
action: 'GET_VERIFICATION_METHODS',
|
|
352
|
+
success: false,
|
|
353
|
+
info: {
|
|
354
|
+
error: errorObject,
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
async requestCode(methodId) {
|
|
359
|
+
let errorObject;
|
|
360
|
+
if (this.#internal.debug) {
|
|
361
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'info', `Attempting to request a code using the "${methodId}" method at "${this.#internal.baseUrl}"`);
|
|
362
|
+
}
|
|
363
|
+
if (this.#session.mfa.verificationMethods.find((device) => device.id === methodId) === undefined) {
|
|
364
|
+
if (this.#internal.debug) {
|
|
365
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'error', `The "${methodId}" verification method does not exist. Did you run the "getVerificationMethods()" yet?`);
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
action: 'REQUEST_CODE',
|
|
369
|
+
success: false,
|
|
370
|
+
info: {
|
|
371
|
+
message: `The "${methodId}" verification method does not exist. Did you run the "getVerificationMethods()" yet?`,
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
const sessions = {};
|
|
377
|
+
const requestCodeForm = new URLSearchParams();
|
|
378
|
+
requestCodeForm.append('id', methodId);
|
|
379
|
+
sessions.axiosRequestCode = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/nga/serv/RunRRAProxy?href=rest/adt/ui/client/multiFactorAuth/requestOtpForRegisteredProperty&sat=${this.#session.mfa.satCode}`, requestCodeForm, this.getRequestConfig({
|
|
380
|
+
headers: {
|
|
381
|
+
Accept: 'application/json',
|
|
382
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
383
|
+
Origin: this.#internal.baseUrl,
|
|
384
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/mfa/mfaSignIn.jsp?workflow=challenge`,
|
|
385
|
+
'Sec-Fetch-Dest': 'empty',
|
|
386
|
+
'Sec-Fetch-Mode': 'cors',
|
|
387
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
388
|
+
'Sec-Fetch-User': undefined,
|
|
389
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
390
|
+
'X-clientType': this.#session.mfa.clientType,
|
|
391
|
+
'X-format': 'json',
|
|
392
|
+
'X-locale': this.#session.mfa.locale,
|
|
393
|
+
'X-login': this.#session.mfa.login,
|
|
394
|
+
'X-preAuthToken': this.#session.mfa.preAuthToken,
|
|
395
|
+
'X-version': '7.0',
|
|
396
|
+
'x-dtpc': generateFakeDynatracePCHeaderValue('multi-factor'),
|
|
397
|
+
},
|
|
398
|
+
}));
|
|
399
|
+
if (typeof sessions.axiosRequestCode?.request === 'undefined') {
|
|
400
|
+
if (this.#internal.debug) {
|
|
401
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'error', 'The HTTP client responded without the "request" object');
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
action: 'REQUEST_CODE',
|
|
405
|
+
success: false,
|
|
406
|
+
info: {
|
|
407
|
+
message: 'The HTTP client responded without the "request" object',
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
const axiosRequestCodeRequestPath = sessions.axiosRequestCode.request.path;
|
|
412
|
+
const axiosRequestCodeRequestPathValid = requestPathNgaServRunRraProxyHrefRestAdtUiClientMultiFactorAuthRequestOtpForRegisteredPropertySatXx.test(axiosRequestCodeRequestPath);
|
|
413
|
+
if (this.#internal.debug) {
|
|
414
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'info', `Request path ➜ ${axiosRequestCodeRequestPath}`);
|
|
415
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'info', `Request path valid ➜ ${axiosRequestCodeRequestPathValid}`);
|
|
416
|
+
}
|
|
417
|
+
if (!axiosRequestCodeRequestPathValid) {
|
|
418
|
+
if (this.#internal.debug) {
|
|
419
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'error', `"${axiosRequestCodeRequestPath}" is not the request code page`);
|
|
420
|
+
}
|
|
421
|
+
this.handleLoginFailure(axiosRequestCodeRequestPath, sessions.axiosRequestCode);
|
|
422
|
+
return {
|
|
423
|
+
action: 'REQUEST_CODE',
|
|
424
|
+
success: false,
|
|
425
|
+
info: {
|
|
426
|
+
message: `"${axiosRequestCodeRequestPath}" is not the request code page`,
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
const parsedRequestCode = otpResponse.safeParse(sessions.axiosRequestCode.data);
|
|
431
|
+
if (!parsedRequestCode.success) {
|
|
432
|
+
if (this.#internal.debug) {
|
|
433
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'error', 'The response body of the request code page is invalid');
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
action: 'REQUEST_CODE',
|
|
437
|
+
success: false,
|
|
438
|
+
info: {
|
|
439
|
+
message: 'The response body of the request code page is invalid',
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
if (!parsedRequestCode.data.detail.includes('OK')) {
|
|
444
|
+
if (this.#internal.debug) {
|
|
445
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'error', `Unable to get a verification code ➜ "${parsedRequestCode.data.detail}"`);
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
action: 'REQUEST_CODE',
|
|
449
|
+
success: false,
|
|
450
|
+
info: {
|
|
451
|
+
message: `Unable to get a verification code ➜ "${parsedRequestCode.data.detail}"`,
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
if (this.#internal.debug) {
|
|
456
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'success', `Successfully requested a code for "${methodId}" at "${this.#internal.baseUrl}"`);
|
|
457
|
+
}
|
|
458
|
+
return {
|
|
459
|
+
action: 'REQUEST_CODE',
|
|
460
|
+
success: true,
|
|
461
|
+
info: null,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
catch (error) {
|
|
465
|
+
errorObject = serializeError(error);
|
|
466
|
+
}
|
|
467
|
+
if (this.#internal.debug) {
|
|
468
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.requestCode()', 'error', 'Method encountered an error during execution');
|
|
469
|
+
stackTracer('serialize-error', errorObject);
|
|
470
|
+
}
|
|
471
|
+
return {
|
|
472
|
+
action: 'REQUEST_CODE',
|
|
473
|
+
success: false,
|
|
474
|
+
info: {
|
|
475
|
+
error: errorObject,
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
async validateCode(otpCode) {
|
|
480
|
+
let errorObject;
|
|
481
|
+
if (this.#internal.debug) {
|
|
482
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'info', `Attempting to validate verification code at "${this.#internal.baseUrl}"`);
|
|
483
|
+
}
|
|
484
|
+
if (!textOneTimePasscode.test(otpCode)) {
|
|
485
|
+
if (this.#internal.debug) {
|
|
486
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', `"${otpCode}" is an invalid verification code format`);
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
action: 'VALIDATE_CODE',
|
|
490
|
+
success: false,
|
|
491
|
+
info: {
|
|
492
|
+
message: `"${otpCode}" is an invalid verification code format`,
|
|
493
|
+
},
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const sessions = {};
|
|
498
|
+
const validateCodeForm = new URLSearchParams();
|
|
499
|
+
validateCodeForm.append('otp', otpCode);
|
|
500
|
+
sessions.axiosValidateCode = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/nga/serv/RunRRAProxy?href=rest/adt/ui/client/multiFactorAuth/validateOtp&sat=${this.#session.mfa.satCode}`, validateCodeForm, this.getRequestConfig({
|
|
501
|
+
headers: {
|
|
502
|
+
Accept: 'application/json',
|
|
503
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
504
|
+
Origin: this.#internal.baseUrl,
|
|
505
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/mfa/mfaSignIn.jsp?workflow=challenge`,
|
|
506
|
+
'Sec-Fetch-Dest': 'empty',
|
|
507
|
+
'Sec-Fetch-Mode': 'cors',
|
|
508
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
509
|
+
'Sec-Fetch-User': undefined,
|
|
510
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
511
|
+
'X-clientType': this.#session.mfa.clientType,
|
|
512
|
+
'X-format': 'json',
|
|
513
|
+
'X-locale': this.#session.mfa.locale,
|
|
514
|
+
'X-login': this.#session.mfa.login,
|
|
515
|
+
'X-preAuthToken': this.#session.mfa.preAuthToken,
|
|
516
|
+
'X-version': '7.0',
|
|
517
|
+
'x-dtpc': generateFakeDynatracePCHeaderValue('multi-factor'),
|
|
518
|
+
},
|
|
519
|
+
}));
|
|
520
|
+
if (typeof sessions.axiosValidateCode?.request === 'undefined') {
|
|
521
|
+
if (this.#internal.debug) {
|
|
522
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', 'The HTTP client responded without the "request" object');
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
action: 'VALIDATE_CODE',
|
|
526
|
+
success: false,
|
|
527
|
+
info: {
|
|
528
|
+
message: 'The HTTP client responded without the "request" object',
|
|
529
|
+
},
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
const axiosValidateCodeRequestPath = sessions.axiosValidateCode.request.path;
|
|
533
|
+
const axiosValidateCodeRequestPathValid = requestPathNgaServRunRraProxyHrefRestAdtUiClientMultiFactorAuthValidateOtpSatXx.test(axiosValidateCodeRequestPath);
|
|
534
|
+
if (this.#internal.debug) {
|
|
535
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'info', `Request path ➜ ${axiosValidateCodeRequestPath}`);
|
|
536
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'info', `Request path valid ➜ ${axiosValidateCodeRequestPathValid}`);
|
|
537
|
+
}
|
|
538
|
+
if (!axiosValidateCodeRequestPathValid) {
|
|
539
|
+
if (this.#internal.debug) {
|
|
540
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', `"${axiosValidateCodeRequestPath}" is not the validate code page`);
|
|
541
|
+
}
|
|
542
|
+
this.handleLoginFailure(axiosValidateCodeRequestPath, sessions.axiosValidateCode);
|
|
543
|
+
return {
|
|
544
|
+
action: 'VALIDATE_CODE',
|
|
545
|
+
success: false,
|
|
546
|
+
info: {
|
|
547
|
+
message: `"${axiosValidateCodeRequestPath}" is not the validate code page`,
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
if (typeof sessions.axiosValidateCode.data === 'string'
|
|
552
|
+
&& sessions.axiosValidateCode.data === '') {
|
|
553
|
+
if (this.#internal.debug) {
|
|
554
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', 'Already passed verification');
|
|
555
|
+
}
|
|
556
|
+
return {
|
|
557
|
+
action: 'VALIDATE_CODE',
|
|
558
|
+
success: true,
|
|
559
|
+
info: null,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
const parsedValidateCode = otpResponse.safeParse(sessions.axiosValidateCode.data);
|
|
563
|
+
if (!parsedValidateCode.success) {
|
|
564
|
+
if (this.#internal.debug) {
|
|
565
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', 'The response body of the validate code page is invalid');
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
action: 'VALIDATE_CODE',
|
|
569
|
+
success: false,
|
|
570
|
+
info: {
|
|
571
|
+
message: 'The response body of the validate code page is invalid',
|
|
572
|
+
},
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
if (!parsedValidateCode.data.detail.startsWith('u=')) {
|
|
576
|
+
if (this.#internal.debug) {
|
|
577
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', 'The verification code submitted is either invalidated or expired');
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
action: 'VALIDATE_CODE',
|
|
581
|
+
success: false,
|
|
582
|
+
info: {
|
|
583
|
+
message: 'The verification code submitted is either invalidated or expired',
|
|
584
|
+
},
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
this.#session.mfa.token = parsedValidateCode.data.detail;
|
|
588
|
+
if (this.#internal.debug) {
|
|
589
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'success', `Successfully validated verification code at "${this.#internal.baseUrl}"`);
|
|
590
|
+
}
|
|
591
|
+
return {
|
|
592
|
+
action: 'VALIDATE_CODE',
|
|
593
|
+
success: true,
|
|
594
|
+
info: null,
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
errorObject = serializeError(error);
|
|
599
|
+
}
|
|
600
|
+
if (this.#internal.debug) {
|
|
601
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.validateCode()', 'error', 'Method encountered an error during execution');
|
|
602
|
+
stackTracer('serialize-error', errorObject);
|
|
603
|
+
}
|
|
604
|
+
return {
|
|
605
|
+
action: 'VALIDATE_CODE',
|
|
606
|
+
success: false,
|
|
607
|
+
info: {
|
|
608
|
+
error: errorObject,
|
|
609
|
+
},
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
async getTrustedDevices() {
|
|
613
|
+
let errorObject;
|
|
614
|
+
if (this.#internal.debug) {
|
|
615
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'info', `Attempting to retrieve trusted devices at "${this.#internal.baseUrl}"`);
|
|
616
|
+
}
|
|
617
|
+
try {
|
|
618
|
+
const sessions = {};
|
|
619
|
+
sessions.axiosDevicePoll = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/nga/serv/RunRRAProxy?only=client.multiFactorAuth&exclude=&sat=${this.#session.mfa.satCode}&href=rest/adt/ui/updates&sat=${this.#session.mfa.satCode}&`, this.getRequestConfig({
|
|
620
|
+
headers: {
|
|
621
|
+
Accept: 'application/json',
|
|
622
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/mfa/mfaSignIn.jsp?workflow=challenge`,
|
|
623
|
+
'Sec-Fetch-Dest': 'empty',
|
|
624
|
+
'Sec-Fetch-Mode': 'cors',
|
|
625
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
626
|
+
'Sec-Fetch-User': undefined,
|
|
627
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
628
|
+
'X-clientType': this.#session.mfa.clientType,
|
|
629
|
+
'X-format': 'json',
|
|
630
|
+
'X-locale': this.#session.mfa.locale,
|
|
631
|
+
'X-login': this.#session.mfa.login,
|
|
632
|
+
'X-token': this.#session.mfa.token,
|
|
633
|
+
'X-version': '7.0',
|
|
634
|
+
'x-dtpc': generateFakeDynatracePCHeaderValue('multi-factor'),
|
|
635
|
+
},
|
|
636
|
+
}));
|
|
637
|
+
if (typeof sessions.axiosDevicePoll?.request === 'undefined') {
|
|
638
|
+
if (this.#internal.debug) {
|
|
639
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'error', 'The HTTP client responded without the "request" object');
|
|
640
|
+
}
|
|
641
|
+
return {
|
|
642
|
+
action: 'GET_TRUSTED_DEVICES',
|
|
643
|
+
success: false,
|
|
644
|
+
info: {
|
|
645
|
+
message: 'The HTTP client responded without the "request" object',
|
|
646
|
+
},
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
const axiosDevicePollRequestPath = sessions.axiosDevicePoll.request.path;
|
|
650
|
+
const axiosDevicePollRequestPathValid = requestPathNgaServRunRraProxyOnlyClientMultiFactorAuthExcludeSatXxHrefRestAdtUiUpdatesSatXx.test(axiosDevicePollRequestPath);
|
|
651
|
+
if (this.#internal.debug) {
|
|
652
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'info', `Request path ➜ ${axiosDevicePollRequestPath}`);
|
|
653
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'info', `Request path valid ➜ ${axiosDevicePollRequestPathValid}`);
|
|
654
|
+
}
|
|
655
|
+
if (!axiosDevicePollRequestPathValid) {
|
|
656
|
+
if (this.#internal.debug) {
|
|
657
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'error', `"${axiosDevicePollRequestPath}" is not the device polling page`);
|
|
658
|
+
}
|
|
659
|
+
this.handleLoginFailure(axiosDevicePollRequestPath, sessions.axiosDevicePoll);
|
|
660
|
+
return {
|
|
661
|
+
action: 'GET_TRUSTED_DEVICES',
|
|
662
|
+
success: false,
|
|
663
|
+
info: {
|
|
664
|
+
message: `"${axiosDevicePollRequestPath}" is not the device polling page`,
|
|
665
|
+
},
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
const parsedDevicePoll = multiFactorAuth.safeParse(_.get(sessions.axiosDevicePoll.data, ['update', 0, 'data', 'client', 'multiFactorAuth']));
|
|
669
|
+
if (!parsedDevicePoll.success) {
|
|
670
|
+
if (this.#internal.debug) {
|
|
671
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'error', 'The response body of the device polling page is invalid');
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
action: 'GET_TRUSTED_DEVICES',
|
|
675
|
+
success: false,
|
|
676
|
+
info: {
|
|
677
|
+
message: 'The response body of the device polling page is invalid',
|
|
678
|
+
},
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
const parsedTrustedDevices = parseMultiFactorTrustedDevices(parsedDevicePoll.data);
|
|
682
|
+
this.#session.mfa.trustedDevices = parsedTrustedDevices;
|
|
683
|
+
if (this.#internal.debug) {
|
|
684
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'success', `Successfully retrieved trusted devices at "${this.#internal.baseUrl}"`);
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
action: 'GET_TRUSTED_DEVICES',
|
|
688
|
+
success: true,
|
|
689
|
+
info: {
|
|
690
|
+
trustedDevices: parsedTrustedDevices,
|
|
691
|
+
},
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
catch (error) {
|
|
695
|
+
errorObject = serializeError(error);
|
|
696
|
+
}
|
|
697
|
+
if (this.#internal.debug) {
|
|
698
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getTrustedDevices()', 'error', 'Method encountered an error during execution');
|
|
699
|
+
stackTracer('serialize-error', errorObject);
|
|
700
|
+
}
|
|
701
|
+
return {
|
|
702
|
+
action: 'GET_TRUSTED_DEVICES',
|
|
703
|
+
success: false,
|
|
704
|
+
info: {
|
|
705
|
+
error: errorObject,
|
|
706
|
+
},
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
async addTrustedDevice(deviceName) {
|
|
710
|
+
let errorObject;
|
|
711
|
+
if (this.#internal.debug) {
|
|
712
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'info', `Attempting to add trusted device at "${this.#internal.baseUrl}"`);
|
|
713
|
+
}
|
|
714
|
+
if (this.#session.mfa.trustedDevices.find((trustedDevice) => trustedDevice.name === encodeURIComponent(deviceName)) !== undefined) {
|
|
715
|
+
if (this.#internal.debug) {
|
|
716
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', 'The name for the trusted device already exists');
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
720
|
+
success: false,
|
|
721
|
+
info: {
|
|
722
|
+
message: 'The name for the trusted device already exists',
|
|
723
|
+
},
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
if (deviceName.length < 1 || deviceName.length > 100) {
|
|
727
|
+
if (this.#internal.debug) {
|
|
728
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', 'The name for the trusted device must be between 1 to 100 characters');
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
732
|
+
success: false,
|
|
733
|
+
info: {
|
|
734
|
+
message: 'The name for the trusted device must be between 1 to 100 characters',
|
|
735
|
+
},
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
const sessions = {};
|
|
740
|
+
const trustedDeviceForm = new URLSearchParams();
|
|
741
|
+
trustedDeviceForm.append('name', encodeURIComponent(deviceName));
|
|
742
|
+
sessions.axiosAddDevice = await this.#session.httpClient.post(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/nga/serv/RunRRAProxy?href=rest/adt/ui/client/multiFactorAuth/addTrustedDevice&sat=${this.#session.mfa.satCode}`, trustedDeviceForm, this.getRequestConfig({
|
|
743
|
+
headers: {
|
|
744
|
+
Accept: 'application/json',
|
|
745
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
746
|
+
Origin: this.#internal.baseUrl,
|
|
747
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/mfa/mfaSignIn.jsp?workflow=challenge`,
|
|
748
|
+
'Sec-Fetch-Dest': 'empty',
|
|
749
|
+
'Sec-Fetch-Mode': 'cors',
|
|
750
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
751
|
+
'Sec-Fetch-User': undefined,
|
|
752
|
+
'Upgrade-Insecure-Requests': undefined,
|
|
753
|
+
'X-clientType': this.#session.mfa.clientType,
|
|
754
|
+
'X-format': 'json',
|
|
755
|
+
'X-locale': this.#session.mfa.locale,
|
|
756
|
+
'X-login': this.#session.mfa.login,
|
|
757
|
+
'X-token': this.#session.mfa.token,
|
|
758
|
+
'X-version': '7.0',
|
|
759
|
+
'x-dtpc': generateFakeDynatracePCHeaderValue('multi-factor'),
|
|
760
|
+
},
|
|
761
|
+
}));
|
|
762
|
+
if (typeof sessions.axiosAddDevice?.request === 'undefined') {
|
|
763
|
+
if (this.#internal.debug) {
|
|
764
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', 'The HTTP client responded without the "request" object');
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
768
|
+
success: false,
|
|
769
|
+
info: {
|
|
770
|
+
message: 'The HTTP client responded without the "request" object',
|
|
771
|
+
},
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
const axiosAddDeviceRequestPath = sessions.axiosAddDevice.request.path;
|
|
775
|
+
const axiosAddDeviceRequestPathValid = requestPathNgaServRunRraProxyHrefRestAdtUiClientMultiFactorAuthAddTrustedDeviceSatXx.test(axiosAddDeviceRequestPath);
|
|
776
|
+
if (this.#internal.debug) {
|
|
777
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'info', `Request path ➜ ${axiosAddDeviceRequestPath}`);
|
|
778
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'info', `Request path valid ➜ ${axiosAddDeviceRequestPathValid}`);
|
|
779
|
+
}
|
|
780
|
+
if (!axiosAddDeviceRequestPathValid) {
|
|
781
|
+
if (this.#internal.debug) {
|
|
782
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', `"${axiosAddDeviceRequestPath}" is not the add trusted device page`);
|
|
783
|
+
}
|
|
784
|
+
this.handleLoginFailure(axiosAddDeviceRequestPath, sessions.axiosAddDevice);
|
|
785
|
+
return {
|
|
786
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
787
|
+
success: false,
|
|
788
|
+
info: {
|
|
789
|
+
message: `"${axiosAddDeviceRequestPath}" is not the add trusted device page`,
|
|
790
|
+
},
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
const parsedValidateCode = otpResponse.safeParse(sessions.axiosAddDevice.data);
|
|
794
|
+
if (!parsedValidateCode.success) {
|
|
795
|
+
if (this.#internal.debug) {
|
|
796
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', 'The response body of the add trusted device page is invalid');
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
800
|
+
success: false,
|
|
801
|
+
info: {
|
|
802
|
+
message: 'The response body of the add trusted device page is invalid',
|
|
803
|
+
},
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
if (!parsedValidateCode.data.detail.includes('OK')) {
|
|
807
|
+
if (this.#internal.debug) {
|
|
808
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', `The trusted device could not be added ➜ "${parsedValidateCode.data.detail}"`);
|
|
809
|
+
}
|
|
810
|
+
return {
|
|
811
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
812
|
+
success: false,
|
|
813
|
+
info: {
|
|
814
|
+
message: `The trusted device could not be added ➜ "${parsedValidateCode.data.detail}"`,
|
|
815
|
+
},
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
if (this.#internal.debug) {
|
|
819
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'success', `Successfully added trusted device at "${this.#internal.baseUrl}"`);
|
|
820
|
+
}
|
|
821
|
+
return {
|
|
822
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
823
|
+
success: true,
|
|
824
|
+
info: null,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
catch (error) {
|
|
828
|
+
errorObject = serializeError(error);
|
|
829
|
+
}
|
|
830
|
+
if (this.#internal.debug) {
|
|
831
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.addTrustedDevice()', 'error', 'Method encountered an error during execution');
|
|
832
|
+
stackTracer('serialize-error', errorObject);
|
|
833
|
+
}
|
|
834
|
+
return {
|
|
835
|
+
action: 'ADD_TRUSTED_DEVICE',
|
|
836
|
+
success: false,
|
|
837
|
+
info: {
|
|
838
|
+
error: errorObject,
|
|
839
|
+
},
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
async completeSignIn() {
|
|
843
|
+
let errorObject;
|
|
844
|
+
if (this.#internal.debug) {
|
|
845
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'info', `Attempting to complete sign in at "${this.#internal.baseUrl}"`);
|
|
846
|
+
}
|
|
847
|
+
try {
|
|
848
|
+
const sessions = {};
|
|
849
|
+
sessions.axiosPostSignIn = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/access/PostSigninProcessServ`, this.getRequestConfig({
|
|
850
|
+
headers: {
|
|
851
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/mfa/mfaSignIn.jsp?workflow=challenge`,
|
|
852
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
853
|
+
},
|
|
854
|
+
}));
|
|
855
|
+
if (sessions.axiosPostSignIn.status >= 400) {
|
|
856
|
+
if (this.#internal.debug) {
|
|
857
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'error', `The remote server responded with a HTTP ${sessions.axiosPostSignIn.status} status code`);
|
|
858
|
+
}
|
|
859
|
+
return {
|
|
860
|
+
action: 'COMPLETE_SIGN_IN',
|
|
861
|
+
success: false,
|
|
862
|
+
info: {
|
|
863
|
+
message: `The remote server responded with a HTTP ${sessions.axiosPostSignIn.status} status code`,
|
|
864
|
+
},
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
if (typeof sessions.axiosPostSignIn?.request === 'undefined') {
|
|
868
|
+
if (this.#internal.debug) {
|
|
869
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'error', 'The HTTP client responded without the "request" object');
|
|
870
|
+
}
|
|
871
|
+
return {
|
|
872
|
+
action: 'COMPLETE_SIGN_IN',
|
|
873
|
+
success: false,
|
|
874
|
+
info: {
|
|
875
|
+
message: 'The HTTP client responded without the "request" object',
|
|
876
|
+
},
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
const axiosPostSignInRequestPath = sessions.axiosPostSignIn.request.path;
|
|
880
|
+
const axiosPostSignInRequestPathValid = requestPathSummarySummary.test(axiosPostSignInRequestPath);
|
|
881
|
+
if (this.#internal.debug) {
|
|
882
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'info', `Request path ➜ ${axiosPostSignInRequestPath}`);
|
|
883
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'info', `Request path valid ➜ ${axiosPostSignInRequestPathValid}`);
|
|
884
|
+
}
|
|
885
|
+
if (!axiosPostSignInRequestPathValid) {
|
|
886
|
+
if (this.#internal.debug) {
|
|
887
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'error', `"${axiosPostSignInRequestPath}" is not the summary page`);
|
|
888
|
+
}
|
|
889
|
+
this.handleLoginFailure(axiosPostSignInRequestPath, sessions.axiosPostSignIn);
|
|
890
|
+
return {
|
|
891
|
+
action: 'COMPLETE_SIGN_IN',
|
|
892
|
+
success: false,
|
|
893
|
+
info: {
|
|
894
|
+
message: `"${axiosPostSignInRequestPath}" is not the summary page`,
|
|
895
|
+
},
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
this.#session.mfa = {
|
|
899
|
+
clientType: null,
|
|
900
|
+
locale: null,
|
|
901
|
+
login: null,
|
|
902
|
+
preAuthToken: null,
|
|
903
|
+
satCode: null,
|
|
904
|
+
token: null,
|
|
905
|
+
trustedDevices: [],
|
|
906
|
+
verificationMethods: [],
|
|
907
|
+
};
|
|
908
|
+
if (this.#internal.debug) {
|
|
909
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'success', `Successfully completed sign in at "${this.#internal.baseUrl}"`);
|
|
910
|
+
}
|
|
911
|
+
return {
|
|
912
|
+
action: 'COMPLETE_SIGN_IN',
|
|
913
|
+
success: true,
|
|
914
|
+
info: null,
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
catch (error) {
|
|
918
|
+
errorObject = serializeError(error);
|
|
919
|
+
}
|
|
920
|
+
if (this.#internal.debug) {
|
|
921
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.completeSignIn()', 'error', 'Method encountered an error during execution');
|
|
922
|
+
stackTracer('serialize-error', errorObject);
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
action: 'COMPLETE_SIGN_IN',
|
|
926
|
+
success: false,
|
|
927
|
+
info: {
|
|
928
|
+
error: errorObject,
|
|
929
|
+
},
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
async getSensors() {
|
|
933
|
+
let errorObject;
|
|
934
|
+
if (this.#internal.debug) {
|
|
935
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'info', `Attempting to retrieve sensors from "${this.#internal.baseUrl}"`);
|
|
936
|
+
}
|
|
937
|
+
try {
|
|
938
|
+
const sessions = {};
|
|
939
|
+
sessions.axiosSystem = await this.#session.httpClient.get(`${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/system/system.jsp`, this.getRequestConfig({
|
|
940
|
+
headers: {
|
|
941
|
+
Referer: `${this.#internal.baseUrl}/myhome/${this.#session.portalVersion}/summary/summary.jsp`,
|
|
942
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
943
|
+
},
|
|
944
|
+
}));
|
|
945
|
+
if (sessions.axiosSystem.status >= 400) {
|
|
946
|
+
if (this.#internal.debug) {
|
|
947
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'error', `The remote server responded with a HTTP ${sessions.axiosSystem.status} status code`);
|
|
948
|
+
}
|
|
949
|
+
return {
|
|
950
|
+
action: 'GET_SENSORS',
|
|
951
|
+
success: false,
|
|
952
|
+
info: {
|
|
953
|
+
message: `The remote server responded with a HTTP ${sessions.axiosSystem.status} status code`,
|
|
954
|
+
},
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
if (typeof sessions.axiosSystem?.request === 'undefined') {
|
|
958
|
+
if (this.#internal.debug) {
|
|
959
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'error', 'The HTTP client responded without the "request" object');
|
|
960
|
+
}
|
|
961
|
+
return {
|
|
962
|
+
action: 'GET_SENSORS',
|
|
963
|
+
success: false,
|
|
964
|
+
info: {
|
|
965
|
+
message: 'The HTTP client responded without the "request" object',
|
|
966
|
+
},
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
const axiosSystemRequestPath = sessions.axiosSystem.request.path;
|
|
970
|
+
const axiosSystemRequestPathValid = requestPathSystemSystem.test(axiosSystemRequestPath);
|
|
971
|
+
if (this.#internal.debug) {
|
|
972
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'info', `Request path ➜ ${axiosSystemRequestPath}`);
|
|
973
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'info', `Request path valid ➜ ${axiosSystemRequestPathValid}`);
|
|
974
|
+
}
|
|
975
|
+
if (!axiosSystemRequestPathValid) {
|
|
976
|
+
if (this.#internal.debug) {
|
|
977
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'error', `"${axiosSystemRequestPath}" is not the system page`);
|
|
978
|
+
}
|
|
979
|
+
this.handleLoginFailure(axiosSystemRequestPath, sessions.axiosSystem);
|
|
980
|
+
return {
|
|
981
|
+
action: 'GET_SENSORS',
|
|
982
|
+
success: false,
|
|
983
|
+
info: {
|
|
984
|
+
message: `"${axiosSystemRequestPath}" is not the system page`,
|
|
985
|
+
},
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
if (typeof sessions.axiosSystem.data !== 'string') {
|
|
989
|
+
if (this.#internal.debug) {
|
|
990
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'error', 'The response body of the system page is not of type "string"');
|
|
991
|
+
}
|
|
992
|
+
return {
|
|
993
|
+
action: 'GET_SENSORS',
|
|
994
|
+
success: false,
|
|
995
|
+
info: {
|
|
996
|
+
message: 'The response body of the system page is not of type "string"',
|
|
997
|
+
},
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
sessions.jsdomSystem = new JSDOM(sessions.axiosSystem.data, {
|
|
1001
|
+
url: sessions.axiosSystem.config.url,
|
|
1002
|
+
referrer: sessions.axiosSystem.config.headers.Referer,
|
|
1003
|
+
contentType: 'text/html',
|
|
1004
|
+
pretendToBeVisual: true,
|
|
1005
|
+
});
|
|
1006
|
+
const jsdomSystemSensorsTable = sessions.jsdomSystem.window.document.querySelectorAll('#systemContentList tr[class^=\'p_row\'] tr.p_listRow');
|
|
1007
|
+
const parsedSensorsConfigTable = parseSensorsTable('sensors-config', jsdomSystemSensorsTable);
|
|
1008
|
+
await this.newInformationDispatcher('debug-parser', {
|
|
1009
|
+
method: 'generateSensorsConfig',
|
|
1010
|
+
response: parsedSensorsConfigTable,
|
|
1011
|
+
rawHtml: sessions.axiosSystem.data,
|
|
1012
|
+
});
|
|
1013
|
+
if (this.#internal.debug) {
|
|
1014
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'success', `Successfully retrieved sensors from "${this.#internal.baseUrl}"`);
|
|
1015
|
+
}
|
|
1016
|
+
return {
|
|
1017
|
+
action: 'GET_SENSORS',
|
|
1018
|
+
success: true,
|
|
1019
|
+
info: {
|
|
1020
|
+
sensors: parsedSensorsConfigTable,
|
|
1021
|
+
},
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
catch (error) {
|
|
1025
|
+
errorObject = serializeError(error);
|
|
1026
|
+
}
|
|
1027
|
+
if (this.#internal.debug) {
|
|
1028
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.getSensors()', 'error', 'Method encountered an error during execution');
|
|
1029
|
+
stackTracer('serialize-error', errorObject);
|
|
1030
|
+
}
|
|
1031
|
+
return {
|
|
1032
|
+
action: 'GET_SENSORS',
|
|
1033
|
+
success: false,
|
|
1034
|
+
info: {
|
|
1035
|
+
error: errorObject,
|
|
1036
|
+
},
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
getFingerprint() {
|
|
1040
|
+
return this.#credentials.fingerprint;
|
|
1041
|
+
}
|
|
1042
|
+
resetSession() {
|
|
1043
|
+
this.#session = {
|
|
1044
|
+
httpClient: wrapper(axios.create({
|
|
1045
|
+
jar: new CookieJar(),
|
|
1046
|
+
validateStatus: () => true,
|
|
1047
|
+
})),
|
|
1048
|
+
mfa: {
|
|
1049
|
+
clientType: null,
|
|
1050
|
+
locale: null,
|
|
1051
|
+
login: null,
|
|
1052
|
+
preAuthToken: null,
|
|
1053
|
+
satCode: null,
|
|
1054
|
+
token: null,
|
|
1055
|
+
trustedDevices: [],
|
|
1056
|
+
verificationMethods: [],
|
|
1057
|
+
},
|
|
1058
|
+
portalVersion: null,
|
|
1059
|
+
status: 'logged-out',
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
async newInformationDispatcher(type, data) {
|
|
1063
|
+
const dataHash = generateHash(data);
|
|
1064
|
+
if (this.#internal.reportedHashes.find((reportedHash) => dataHash === reportedHash) === undefined) {
|
|
1065
|
+
let detectedNew = false;
|
|
1066
|
+
switch (type) {
|
|
1067
|
+
case 'debug-parser':
|
|
1068
|
+
detectedNew = await detectGlobalDebugParser(data, null, this.#internal.debug);
|
|
1069
|
+
break;
|
|
1070
|
+
case 'portal-version':
|
|
1071
|
+
detectedNew = await detectGlobalPortalVersion(data, null, this.#internal.debug);
|
|
1072
|
+
break;
|
|
1073
|
+
default:
|
|
1074
|
+
break;
|
|
1075
|
+
}
|
|
1076
|
+
if (detectedNew) {
|
|
1077
|
+
this.#internal.reportedHashes.push(dataHash);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
getRequestConfig(extraConfig) {
|
|
1082
|
+
const defaultConfig = {
|
|
1083
|
+
family: 4,
|
|
1084
|
+
headers: {
|
|
1085
|
+
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
1086
|
+
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
|
1087
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
1088
|
+
'Cache-Control': 'no-cache',
|
|
1089
|
+
Connection: 'keep-alive',
|
|
1090
|
+
Host: `${this.#connection.subdomain}.adtpulse.com`,
|
|
1091
|
+
Pragma: 'no-cache',
|
|
1092
|
+
'Sec-Fetch-Dest': 'document',
|
|
1093
|
+
'Sec-Fetch-Mode': 'navigate',
|
|
1094
|
+
'Sec-Fetch-Site': 'none',
|
|
1095
|
+
'Sec-Fetch-User': '?1',
|
|
1096
|
+
'Upgrade-Insecure-Requests': '1',
|
|
1097
|
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
|
|
1098
|
+
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
|
|
1099
|
+
'sec-ch-ua-mobile': '?0',
|
|
1100
|
+
'sec-ch-ua-platform': '"macOS"',
|
|
1101
|
+
},
|
|
1102
|
+
timeout: 15000,
|
|
1103
|
+
};
|
|
1104
|
+
if (extraConfig === undefined) {
|
|
1105
|
+
return defaultConfig;
|
|
1106
|
+
}
|
|
1107
|
+
return _.merge(_.omit(defaultConfig, findNullKeys(extraConfig)), _.omit(extraConfig, findNullKeys(extraConfig)));
|
|
1108
|
+
}
|
|
1109
|
+
handleLoginFailure(requestPath, session) {
|
|
1110
|
+
if (requestPath === null) {
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
if (requestPathAccessSignIn.test(requestPath) || requestPathAccessSignInEXxPartnerAdt.test(requestPath)) {
|
|
1114
|
+
if (this.#internal.debug) {
|
|
1115
|
+
const errorMessage = fetchErrorMessage(session);
|
|
1116
|
+
if (requestPathAccessSignIn.test(requestPath) || requestPathAccessSignInEXxPartnerAdt.test(requestPath)) {
|
|
1117
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.handleLoginFailure()', 'error', 'Either the username or password is incorrect, fingerprint format is invalid, or was signed out due to inactivity');
|
|
1118
|
+
}
|
|
1119
|
+
if (requestPathSummarySummary.test(requestPath)) {
|
|
1120
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.handleLoginFailure()', 'error', 'The generated fingerprint is already validated');
|
|
1121
|
+
}
|
|
1122
|
+
if (errorMessage !== null) {
|
|
1123
|
+
debugLog(this.#internal.logger, 'auth.ts / ADTPulseAuth.handleLoginFailure()', 'warn', `Portal message ➜ "${errorMessage}"`);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
this.resetSession();
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
//# sourceMappingURL=auth.js.map
|