ag-awsauth 0.0.292 → 0.0.293
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/dist/helpers/browser.d.ts +3 -1
- package/dist/helpers/browser.js +153 -18
- package/package.json +1 -1
|
@@ -2,7 +2,9 @@ import type { Page } from 'puppeteer';
|
|
|
2
2
|
export declare const closeBrowser: () => Promise<void>;
|
|
3
3
|
export declare const launchBrowser: () => Promise<void>;
|
|
4
4
|
export declare const goToPage: (url: string) => Promise<Page>;
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const allowAccessSelectors: string[];
|
|
6
|
+
export declare const dismissAllowAccessPrompt: (page: Page, perSelectorTimeout?: number) => Promise<boolean>;
|
|
7
|
+
export declare const allowAccessIfRequested: (page: Page, timeout?: number) => Promise<boolean>;
|
|
6
8
|
export declare function getMFA(p: {
|
|
7
9
|
verificationUriComplete: string;
|
|
8
10
|
creds: {
|
package/dist/helpers/browser.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.allowAccessIfRequested = exports.goToPage = exports.launchBrowser = exports.closeBrowser = void 0;
|
|
12
|
+
exports.allowAccessIfRequested = exports.dismissAllowAccessPrompt = exports.allowAccessSelectors = exports.goToPage = exports.launchBrowser = exports.closeBrowser = void 0;
|
|
13
13
|
exports.getMFA = getMFA;
|
|
14
14
|
const log_1 = require("ag-common/dist/common/helpers/log");
|
|
15
15
|
const puppeteer_1 = require("puppeteer");
|
|
@@ -83,15 +83,154 @@ const goToPage = (url) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
85
|
exports.goToPage = goToPage;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
exports.allowAccessSelectors = [
|
|
87
|
+
'[data-testid="allow-access-button"]',
|
|
88
|
+
'[data-analytics="allow-access-button"]',
|
|
89
|
+
'button[data-testid="allow-access-button"]',
|
|
90
|
+
];
|
|
91
|
+
const clickSelectorIfPresent = (page_1, selector_1, ...args_1) => __awaiter(void 0, [page_1, selector_1, ...args_1], void 0, function* (page, selector, timeout = config_1.timeoutShortMs) {
|
|
92
|
+
try {
|
|
93
|
+
const el = yield page.waitForSelector(selector, {
|
|
94
|
+
timeout,
|
|
95
|
+
visible: true,
|
|
96
|
+
});
|
|
97
|
+
if (!el) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
yield el.click();
|
|
102
|
+
}
|
|
103
|
+
catch (_a) {
|
|
104
|
+
// Element may detach between query and click (SPA re-render).
|
|
105
|
+
// Fall back to an in-page click which re-queries the selector.
|
|
106
|
+
yield page
|
|
107
|
+
.$eval(selector, (bn) => bn.click())
|
|
108
|
+
.catch(() => undefined);
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
catch (_b) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
const clickAllowAccessByText = (page) => __awaiter(void 0, void 0, void 0, function* () {
|
|
117
|
+
try {
|
|
118
|
+
return yield page.evaluate(() => {
|
|
119
|
+
const isVisible = (el) => {
|
|
120
|
+
const rect = el.getBoundingClientRect();
|
|
121
|
+
return (rect.width > 0 &&
|
|
122
|
+
rect.height > 0 &&
|
|
123
|
+
getComputedStyle(el).visibility !== 'hidden');
|
|
124
|
+
};
|
|
125
|
+
// Match button, link, or ARIA-button variants: AWS renders the
|
|
126
|
+
// "Allow access" consent action differently across releases
|
|
127
|
+
// (orange button vs link), so don't assume a <button>.
|
|
128
|
+
const candidates = Array.from(document.querySelectorAll('button, a, [role="button"], input[type="submit"], input[type="button"]')).filter((el) => isVisible(el));
|
|
129
|
+
const label = (el) => {
|
|
130
|
+
var _a, _b;
|
|
131
|
+
return ((_b = (_a = el.value) !== null && _a !== void 0 ? _a : el.textContent) !== null && _b !== void 0 ? _b : '')
|
|
132
|
+
.trim()
|
|
133
|
+
.toLowerCase();
|
|
134
|
+
};
|
|
135
|
+
const exact = candidates.find((el) => label(el) === 'allow access');
|
|
136
|
+
const target = exact !== null && exact !== void 0 ? exact : candidates.find((el) => label(el).includes('allow access'));
|
|
137
|
+
if (target) {
|
|
138
|
+
target.click();
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (_a) {
|
|
145
|
+
return false;
|
|
90
146
|
}
|
|
91
|
-
|
|
92
|
-
|
|
147
|
+
});
|
|
148
|
+
const dismissAllowAccessPrompt = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, perSelectorTimeout = 1000) {
|
|
149
|
+
for (const selector of exports.allowAccessSelectors) {
|
|
150
|
+
if (yield clickSelectorIfPresent(page, selector, perSelectorTimeout)) {
|
|
151
|
+
(0, log_1.info)(`click allow-access-button (${selector})`);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (yield clickAllowAccessByText(page)) {
|
|
156
|
+
(0, log_1.info)('click allow-access-button (text match "Allow access")');
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
});
|
|
161
|
+
exports.dismissAllowAccessPrompt = dismissAllowAccessPrompt;
|
|
162
|
+
const allowAccessIfRequested = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, timeout = config_1.timeoutMs) {
|
|
163
|
+
const deadline = Date.now() + timeout;
|
|
164
|
+
// Poll so a slow-rendering consent dialog is not missed, while still
|
|
165
|
+
// returning quickly when the prompt appears (or never appears).
|
|
166
|
+
while (Date.now() < deadline) {
|
|
167
|
+
if (yield (0, exports.dismissAllowAccessPrompt)(page)) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
if (Date.now() + 500 >= deadline) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
yield new Promise((resolve) => setTimeout(resolve, 500));
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
93
176
|
});
|
|
94
177
|
exports.allowAccessIfRequested = allowAccessIfRequested;
|
|
178
|
+
const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, timeout = config_1.timeoutMs) {
|
|
179
|
+
var _a;
|
|
180
|
+
const deadline = Date.now() + timeout;
|
|
181
|
+
let lastError;
|
|
182
|
+
while (Date.now() < deadline) {
|
|
183
|
+
// Success already visible?
|
|
184
|
+
try {
|
|
185
|
+
const success = yield page.waitForSelector('[data-analytics-alert="success"]', { timeout: 2000 });
|
|
186
|
+
if (success) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
lastError = e;
|
|
192
|
+
}
|
|
193
|
+
// Defensively dismiss the consent prompt if it is (still) showing.
|
|
194
|
+
// This covers the "Allow <user> to access your data? / Allow access"
|
|
195
|
+
// dialog which otherwise blocks success indefinitely.
|
|
196
|
+
try {
|
|
197
|
+
if (yield (0, exports.dismissAllowAccessPrompt)(page)) {
|
|
198
|
+
(0, log_1.info)('dismissed allow-access prompt while waiting for success');
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
(0, log_1.debug)('error dismissing allow-access prompt:', e);
|
|
204
|
+
}
|
|
205
|
+
// Also re-check the other intermediate confirmations while polling.
|
|
206
|
+
try {
|
|
207
|
+
if (yield clickSelectorIfPresent(page, '[data-analytics="accept-user-code"]', 1000)) {
|
|
208
|
+
(0, log_1.info)('click accept-user-code (while waiting for success)');
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (e) {
|
|
213
|
+
(0, log_1.debug)('error clicking accept-user-code while waiting:', e);
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
if (yield clickSelectorIfPresent(page, '#cli_verification_btn', 1000)) {
|
|
217
|
+
(0, log_1.info)('clicking auth request button (while waiting for success)');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch (e) {
|
|
221
|
+
(0, log_1.debug)('error clicking auth request button while waiting:', e);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Final wait to surface a clear TimeoutError if success never arrived.
|
|
225
|
+
try {
|
|
226
|
+
yield page.waitForSelector('[data-analytics-alert="success"]', {
|
|
227
|
+
timeout: config_1.timeoutShortMs,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (_b) {
|
|
231
|
+
throw ((_a = lastError) !== null && _a !== void 0 ? _a : new Error('Timed out waiting for success'));
|
|
232
|
+
}
|
|
233
|
+
});
|
|
95
234
|
function getMFA(p) {
|
|
96
235
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
236
|
var _a;
|
|
@@ -203,15 +342,11 @@ function getMFA(p) {
|
|
|
203
342
|
}
|
|
204
343
|
try {
|
|
205
344
|
(0, log_1.info)('accept-user-code');
|
|
206
|
-
|
|
207
|
-
timeout: config_1.timeoutMs,
|
|
208
|
-
});
|
|
209
|
-
if (messageDiv) {
|
|
345
|
+
if (yield clickSelectorIfPresent(page, '[data-analytics="accept-user-code"]', config_1.timeoutMs)) {
|
|
210
346
|
(0, log_1.info)('click accept-user-code');
|
|
211
|
-
yield messageDiv.click();
|
|
212
347
|
}
|
|
213
348
|
else {
|
|
214
|
-
|
|
349
|
+
(0, log_1.debug)('accept-user-code prompt not present, continuing');
|
|
215
350
|
}
|
|
216
351
|
}
|
|
217
352
|
catch (e) {
|
|
@@ -220,8 +355,10 @@ function getMFA(p) {
|
|
|
220
355
|
let accessStateFound = false;
|
|
221
356
|
try {
|
|
222
357
|
(0, log_1.info)('allow-access-button');
|
|
223
|
-
yield (0, exports.allowAccessIfRequested)(page);
|
|
224
|
-
accessStateFound
|
|
358
|
+
accessStateFound = yield (0, exports.allowAccessIfRequested)(page, config_1.timeoutMedMs);
|
|
359
|
+
if (!accessStateFound) {
|
|
360
|
+
(0, log_1.debug)('allow-access prompt not present, continuing');
|
|
361
|
+
}
|
|
225
362
|
}
|
|
226
363
|
catch (e) {
|
|
227
364
|
(0, log_1.debug)('error clicking allow-access-button:', e);
|
|
@@ -242,9 +379,7 @@ function getMFA(p) {
|
|
|
242
379
|
}
|
|
243
380
|
//
|
|
244
381
|
(0, log_1.info)('waiting for success');
|
|
245
|
-
yield page
|
|
246
|
-
timeout: config_1.timeoutMs,
|
|
247
|
-
});
|
|
382
|
+
yield waitForSuccessDefensively(page, config_1.timeoutMs);
|
|
248
383
|
(0, log_1.warn)('mfa success');
|
|
249
384
|
const cookies = yield page.cookies();
|
|
250
385
|
const ssoAuthn = (_a = cookies.find((c) => c.name === 'x-amz-sso_authn')) === null || _a === void 0 ? void 0 : _a.value;
|