@uipath/auth 1.195.0 → 1.197.0-preview.59
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/authContext.d.ts +22 -0
- package/dist/authProfile.d.ts +11 -0
- package/dist/clientCredentials.d.ts +4 -0
- package/dist/envAuth.d.ts +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +18735 -252
- package/dist/index.d.ts +14 -2
- package/dist/index.js +701 -259
- package/dist/interactive.d.ts +20 -0
- package/dist/loginStatus.d.ts +21 -5
- package/dist/logout.d.ts +4 -0
- package/dist/refreshCircuitBreaker.d.ts +42 -0
- package/dist/robotClientFallback.d.ts +4 -3
- package/dist/selectTenant.d.ts +35 -0
- package/dist/strategies/auth-strategy.d.ts +16 -1
- package/dist/strategies/browser-strategy.d.ts +3 -1
- package/dist/strategies/node-strategy.d.ts +2 -2
- package/dist/utils/envFile.d.ts +7 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19153,16 +19153,33 @@ var require_dist = __commonJS((exports) => {
|
|
|
19153
19153
|
});
|
|
19154
19154
|
|
|
19155
19155
|
// src/getBaseHtml.ts
|
|
19156
|
-
var
|
|
19156
|
+
var escapeHtml = (value) => value.replace(/[&<>"']/g, (char) => {
|
|
19157
|
+
switch (char) {
|
|
19158
|
+
case "&":
|
|
19159
|
+
return "&";
|
|
19160
|
+
case "<":
|
|
19161
|
+
return "<";
|
|
19162
|
+
case ">":
|
|
19163
|
+
return ">";
|
|
19164
|
+
case '"':
|
|
19165
|
+
return """;
|
|
19166
|
+
case "'":
|
|
19167
|
+
return "'";
|
|
19168
|
+
default:
|
|
19169
|
+
return char;
|
|
19170
|
+
}
|
|
19171
|
+
}), getBaseHtml = ({ title, message, type }) => {
|
|
19157
19172
|
const icon = type === "success" ? "✓" : "✕";
|
|
19158
19173
|
const iconClass = type === "success" ? "icon-success" : "icon-error";
|
|
19174
|
+
const safeTitle = escapeHtml(title);
|
|
19175
|
+
const safeMessage = escapeHtml(message);
|
|
19159
19176
|
return `
|
|
19160
19177
|
<!DOCTYPE html>
|
|
19161
19178
|
<html lang="en">
|
|
19162
19179
|
<head>
|
|
19163
19180
|
<meta charset="UTF-8">
|
|
19164
19181
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19165
|
-
<title>${
|
|
19182
|
+
<title>${safeTitle} - UiPath CLI</title>
|
|
19166
19183
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
19167
19184
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
19168
19185
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400&family=Poppins:wght@600&display=swap" rel="stylesheet">
|
|
@@ -19288,8 +19305,8 @@ var getBaseHtml = ({ title, message, type }) => {
|
|
|
19288
19305
|
</div>
|
|
19289
19306
|
</div>
|
|
19290
19307
|
<div class="icon ${iconClass}">${icon}</div>
|
|
19291
|
-
<h1>${
|
|
19292
|
-
<p>${
|
|
19308
|
+
<h1>${safeTitle}</h1>
|
|
19309
|
+
<p>${safeMessage}</p>
|
|
19293
19310
|
<div class="footer">You can close this window</div>
|
|
19294
19311
|
</div>
|
|
19295
19312
|
</div>
|
|
@@ -19405,7 +19422,7 @@ __export(exports_browser_strategy, {
|
|
|
19405
19422
|
});
|
|
19406
19423
|
|
|
19407
19424
|
class BrowserAuthStrategy {
|
|
19408
|
-
async execute(url, _redirectUri, expectedState) {
|
|
19425
|
+
async execute(url, _redirectUri, expectedState, _opts) {
|
|
19409
19426
|
const global2 = getGlobalThis();
|
|
19410
19427
|
if (!global2?.window) {
|
|
19411
19428
|
throw new Error("Browser environment required for authentication");
|
|
@@ -19480,10 +19497,11 @@ __export(exports_node_strategy, {
|
|
|
19480
19497
|
});
|
|
19481
19498
|
|
|
19482
19499
|
class NodeAuthStrategy {
|
|
19483
|
-
async execute(url, redirectUri, expectedState) {
|
|
19500
|
+
async execute(url, redirectUri, expectedState, opts) {
|
|
19484
19501
|
const fs7 = getFileSystem();
|
|
19485
19502
|
const callbackUrl = await startServer({
|
|
19486
19503
|
redirectUri,
|
|
19504
|
+
timeoutMs: opts?.timeoutMs,
|
|
19487
19505
|
onListening: async () => {
|
|
19488
19506
|
let safeUrl = "";
|
|
19489
19507
|
for (const ch of url) {
|
|
@@ -19491,6 +19509,13 @@ class NodeAuthStrategy {
|
|
|
19491
19509
|
if (c > 31 && (c < 128 || c > 159))
|
|
19492
19510
|
safeUrl += ch;
|
|
19493
19511
|
}
|
|
19512
|
+
if (opts?.noBrowser) {
|
|
19513
|
+
if (!opts.onAuthUrl) {
|
|
19514
|
+
throw new Error("Headless login (noBrowser) requires an onAuthUrl handler " + "to surface the authorize URL, but none was provided.");
|
|
19515
|
+
}
|
|
19516
|
+
opts.onAuthUrl(safeUrl);
|
|
19517
|
+
return;
|
|
19518
|
+
}
|
|
19494
19519
|
const [openError] = await catchError(fs7.utils.open(url));
|
|
19495
19520
|
if (!openError)
|
|
19496
19521
|
return;
|
|
@@ -19572,6 +19597,12 @@ var normalizeAndValidateBaseUrl = (rawUrl) => {
|
|
|
19572
19597
|
}
|
|
19573
19598
|
return url.pathname.length > 1 ? url.origin : baseUrl;
|
|
19574
19599
|
};
|
|
19600
|
+
var resolveScopes = (isExternalAppAuth, customScopes, fileScopes) => {
|
|
19601
|
+
const requestedScopes = customScopes?.length ? customScopes : fileScopes ?? [];
|
|
19602
|
+
if (isExternalAppAuth)
|
|
19603
|
+
return requestedScopes;
|
|
19604
|
+
return [...new Set([...DEFAULT_SCOPES, ...requestedScopes])];
|
|
19605
|
+
};
|
|
19575
19606
|
var resolveConfigAsync = async ({
|
|
19576
19607
|
customAuthority,
|
|
19577
19608
|
customClientId,
|
|
@@ -19602,7 +19633,7 @@ var resolveConfigAsync = async ({
|
|
|
19602
19633
|
clientSecret = fileAuth.clientSecret;
|
|
19603
19634
|
}
|
|
19604
19635
|
const isExternalAppAuth = clientId !== DEFAULT_CLIENT_ID && Boolean(clientSecret);
|
|
19605
|
-
const scopes =
|
|
19636
|
+
const scopes = resolveScopes(isExternalAppAuth, customScopes, fileAuth.scopes);
|
|
19606
19637
|
return {
|
|
19607
19638
|
clientId,
|
|
19608
19639
|
clientSecret,
|
|
@@ -20249,6 +20280,105 @@ var exchangeCodeForTokens = async ({
|
|
|
20249
20280
|
};
|
|
20250
20281
|
// src/loginStatus.ts
|
|
20251
20282
|
init_src();
|
|
20283
|
+
|
|
20284
|
+
// src/authProfile.ts
|
|
20285
|
+
init_src();
|
|
20286
|
+
init_constants();
|
|
20287
|
+
var DEFAULT_AUTH_PROFILE = "default";
|
|
20288
|
+
var PROFILE_DIR = "profiles";
|
|
20289
|
+
var PROFILE_NAME_RE = /^[A-Za-z0-9._-]+$/;
|
|
20290
|
+
var ACTIVE_AUTH_PROFILE_KEY = Symbol.for("@uipath/auth/ActiveAuthProfile");
|
|
20291
|
+
var AUTH_PROFILE_STORAGE_KEY = Symbol.for("@uipath/auth/ProfileStorage");
|
|
20292
|
+
var globalSlot2 = globalThis;
|
|
20293
|
+
function isAuthProfileStorage(value) {
|
|
20294
|
+
return value !== null && typeof value === "object" && "getStore" in value && "run" in value;
|
|
20295
|
+
}
|
|
20296
|
+
function createProfileStorage() {
|
|
20297
|
+
const [error, mod] = catchError(() => __require("node:async_hooks"));
|
|
20298
|
+
if (error || typeof mod?.AsyncLocalStorage !== "function") {
|
|
20299
|
+
return {
|
|
20300
|
+
getStore: () => {
|
|
20301
|
+
return;
|
|
20302
|
+
},
|
|
20303
|
+
run: (_store, fn) => fn()
|
|
20304
|
+
};
|
|
20305
|
+
}
|
|
20306
|
+
return new mod.AsyncLocalStorage;
|
|
20307
|
+
}
|
|
20308
|
+
function getProfileStorage() {
|
|
20309
|
+
const existing = globalSlot2[AUTH_PROFILE_STORAGE_KEY];
|
|
20310
|
+
if (isAuthProfileStorage(existing)) {
|
|
20311
|
+
return existing;
|
|
20312
|
+
}
|
|
20313
|
+
const storage = createProfileStorage();
|
|
20314
|
+
globalSlot2[AUTH_PROFILE_STORAGE_KEY] = storage;
|
|
20315
|
+
return storage;
|
|
20316
|
+
}
|
|
20317
|
+
var profileStorage = getProfileStorage();
|
|
20318
|
+
|
|
20319
|
+
class AuthProfileValidationError extends Error {
|
|
20320
|
+
constructor(message) {
|
|
20321
|
+
super(message);
|
|
20322
|
+
this.name = "AuthProfileValidationError";
|
|
20323
|
+
}
|
|
20324
|
+
}
|
|
20325
|
+
function normalizeAuthProfileName(profile) {
|
|
20326
|
+
if (profile === undefined || profile === DEFAULT_AUTH_PROFILE) {
|
|
20327
|
+
return;
|
|
20328
|
+
}
|
|
20329
|
+
if (profile.length === 0 || profile === "." || profile === ".." || !PROFILE_NAME_RE.test(profile)) {
|
|
20330
|
+
throw new AuthProfileValidationError(`Invalid profile name "${profile}". Profile names may contain only letters, numbers, '.', '_', and '-'.`);
|
|
20331
|
+
}
|
|
20332
|
+
return profile;
|
|
20333
|
+
}
|
|
20334
|
+
function setActiveAuthProfile(profile) {
|
|
20335
|
+
const normalized = normalizeAuthProfileName(profile);
|
|
20336
|
+
const scopedState = profileStorage.getStore();
|
|
20337
|
+
if (scopedState !== undefined) {
|
|
20338
|
+
if (normalized === undefined) {
|
|
20339
|
+
delete scopedState.profile;
|
|
20340
|
+
return;
|
|
20341
|
+
}
|
|
20342
|
+
scopedState.profile = normalized;
|
|
20343
|
+
return;
|
|
20344
|
+
}
|
|
20345
|
+
if (normalized === undefined) {
|
|
20346
|
+
delete globalSlot2[ACTIVE_AUTH_PROFILE_KEY];
|
|
20347
|
+
return;
|
|
20348
|
+
}
|
|
20349
|
+
globalSlot2[ACTIVE_AUTH_PROFILE_KEY] = { profile: normalized };
|
|
20350
|
+
}
|
|
20351
|
+
function clearActiveAuthProfile() {
|
|
20352
|
+
const scopedState = profileStorage.getStore();
|
|
20353
|
+
if (scopedState !== undefined) {
|
|
20354
|
+
delete scopedState.profile;
|
|
20355
|
+
return;
|
|
20356
|
+
}
|
|
20357
|
+
delete globalSlot2[ACTIVE_AUTH_PROFILE_KEY];
|
|
20358
|
+
}
|
|
20359
|
+
function getActiveAuthProfile() {
|
|
20360
|
+
const scopedState = profileStorage.getStore();
|
|
20361
|
+
if (scopedState !== undefined) {
|
|
20362
|
+
return scopedState.profile;
|
|
20363
|
+
}
|
|
20364
|
+
return globalSlot2[ACTIVE_AUTH_PROFILE_KEY]?.profile;
|
|
20365
|
+
}
|
|
20366
|
+
function runWithAuthProfile(profile, fn) {
|
|
20367
|
+
const normalized = normalizeAuthProfileName(profile);
|
|
20368
|
+
return profileStorage.run(normalized === undefined ? {} : { profile: normalized }, fn);
|
|
20369
|
+
}
|
|
20370
|
+
function resolveAuthProfileFilePath(profile) {
|
|
20371
|
+
const normalized = normalizeAuthProfileName(profile);
|
|
20372
|
+
if (normalized === undefined) {
|
|
20373
|
+
throw new AuthProfileValidationError(`"${DEFAULT_AUTH_PROFILE}" is the built-in profile and does not have a profile file path.`);
|
|
20374
|
+
}
|
|
20375
|
+
const fs7 = getFileSystem();
|
|
20376
|
+
return fs7.path.join(fs7.env.homedir(), UIPATH_HOME_DIR, PROFILE_DIR, normalized, AUTH_FILENAME);
|
|
20377
|
+
}
|
|
20378
|
+
function getActiveAuthProfileFilePath() {
|
|
20379
|
+
const profile = getActiveAuthProfile();
|
|
20380
|
+
return profile ? resolveAuthProfileFilePath(profile) : undefined;
|
|
20381
|
+
}
|
|
20252
20382
|
// src/utils/jwt.ts
|
|
20253
20383
|
class InvalidIssuerError extends Error {
|
|
20254
20384
|
expected;
|
|
@@ -20377,23 +20507,74 @@ var readAuthFromEnv = () => {
|
|
|
20377
20507
|
organizationId,
|
|
20378
20508
|
tenantName,
|
|
20379
20509
|
tenantId,
|
|
20380
|
-
expiration
|
|
20510
|
+
expiration,
|
|
20511
|
+
source: "env" /* Env */
|
|
20381
20512
|
};
|
|
20382
20513
|
};
|
|
20383
20514
|
|
|
20515
|
+
// src/refreshCircuitBreaker.ts
|
|
20516
|
+
init_src();
|
|
20517
|
+
var BREAKER_SUFFIX = ".refresh-state";
|
|
20518
|
+
var BACKOFF_BASE_MS = 60000;
|
|
20519
|
+
var BACKOFF_CAP_MS = 60 * 60 * 1000;
|
|
20520
|
+
var SURFACE_WINDOW_MS = 60 * 60 * 1000;
|
|
20521
|
+
async function refreshTokenFingerprint(refreshToken) {
|
|
20522
|
+
const bytes = new TextEncoder().encode(refreshToken);
|
|
20523
|
+
if (globalThis.crypto?.subtle) {
|
|
20524
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
|
|
20525
|
+
return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
|
|
20526
|
+
}
|
|
20527
|
+
const { createHash } = await import("node:crypto");
|
|
20528
|
+
return createHash("sha256").update(refreshToken).digest("hex").slice(0, 16);
|
|
20529
|
+
}
|
|
20530
|
+
function breakerPathFor(authPath) {
|
|
20531
|
+
return `${authPath}${BREAKER_SUFFIX}`;
|
|
20532
|
+
}
|
|
20533
|
+
async function loadRefreshBreaker(authPath) {
|
|
20534
|
+
const fs7 = getFileSystem();
|
|
20535
|
+
try {
|
|
20536
|
+
const content = await fs7.readFile(breakerPathFor(authPath), "utf-8");
|
|
20537
|
+
if (!content)
|
|
20538
|
+
return {};
|
|
20539
|
+
const parsed = JSON.parse(content);
|
|
20540
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
20541
|
+
} catch {
|
|
20542
|
+
return {};
|
|
20543
|
+
}
|
|
20544
|
+
}
|
|
20545
|
+
async function saveRefreshBreaker(authPath, state) {
|
|
20546
|
+
try {
|
|
20547
|
+
const fs7 = getFileSystem();
|
|
20548
|
+
const path3 = breakerPathFor(authPath);
|
|
20549
|
+
await fs7.mkdir(fs7.path.dirname(path3));
|
|
20550
|
+
const tempPath = `${path3}.tmp`;
|
|
20551
|
+
await fs7.writeFile(tempPath, JSON.stringify(state));
|
|
20552
|
+
await fs7.rename(tempPath, path3);
|
|
20553
|
+
} catch {}
|
|
20554
|
+
}
|
|
20555
|
+
async function clearRefreshBreaker(authPath) {
|
|
20556
|
+
const fs7 = getFileSystem();
|
|
20557
|
+
const path3 = breakerPathFor(authPath);
|
|
20558
|
+
try {
|
|
20559
|
+
if (await fs7.exists(path3)) {
|
|
20560
|
+
await fs7.rm(path3);
|
|
20561
|
+
}
|
|
20562
|
+
} catch {}
|
|
20563
|
+
}
|
|
20564
|
+
function nextBackoffMs(attempts) {
|
|
20565
|
+
const shift = Math.max(0, attempts - 1);
|
|
20566
|
+
return Math.min(BACKOFF_BASE_MS * 2 ** shift, BACKOFF_CAP_MS);
|
|
20567
|
+
}
|
|
20568
|
+
function shouldSurface(state, nowMs) {
|
|
20569
|
+
if (state.lastSurfacedAtMs === undefined)
|
|
20570
|
+
return true;
|
|
20571
|
+
return nowMs - state.lastSurfacedAtMs >= SURFACE_WINDOW_MS;
|
|
20572
|
+
}
|
|
20573
|
+
|
|
20384
20574
|
// src/robotClientFallback.ts
|
|
20385
20575
|
init_src();
|
|
20386
20576
|
var DEFAULT_TIMEOUT_MS = 1000;
|
|
20387
20577
|
var CLOSE_TIMEOUT_MS = 500;
|
|
20388
|
-
var NOTICE_SENTINEL = Symbol.for("@uipath/auth/robotFallbackNoticePrinted");
|
|
20389
|
-
var printNoticeOnce = () => {
|
|
20390
|
-
const slot = globalThis;
|
|
20391
|
-
if (slot[NOTICE_SENTINEL])
|
|
20392
|
-
return;
|
|
20393
|
-
slot[NOTICE_SENTINEL] = true;
|
|
20394
|
-
catchError(() => process.stderr.write(`Using UiPath Robot credentials. Run 'uip login' for a dedicated session.
|
|
20395
|
-
`));
|
|
20396
|
-
};
|
|
20397
20578
|
var ROBOT_USER_SERVICES_PIPE = "UiPathUserServices";
|
|
20398
20579
|
var ROBOT_USER_SERVICES_ALTERNATE_PIPE = `${ROBOT_USER_SERVICES_PIPE}Alternate`;
|
|
20399
20580
|
var PIPE_NAME_MAX_LENGTH = 103;
|
|
@@ -20438,11 +20619,11 @@ var parseResourceUrl = (url) => {
|
|
|
20438
20619
|
if (error || !parsed)
|
|
20439
20620
|
return;
|
|
20440
20621
|
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
20441
|
-
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
|
|
20445
|
-
|
|
20622
|
+
return {
|
|
20623
|
+
baseUrl: parsed.origin,
|
|
20624
|
+
organizationName: segments[0],
|
|
20625
|
+
tenantName: segments[1]
|
|
20626
|
+
};
|
|
20446
20627
|
};
|
|
20447
20628
|
var defaultLoadModule = async () => {
|
|
20448
20629
|
const [error, mod] = await catchError(() => Promise.resolve().then(() => __toESM(require_dist(), 1)));
|
|
@@ -20493,6 +20674,7 @@ var tryRobotClientFallback = async (options = {}) => {
|
|
|
20493
20674
|
}
|
|
20494
20675
|
let organizationIdFromToken;
|
|
20495
20676
|
let tenantIdFromToken;
|
|
20677
|
+
let issuerFromToken;
|
|
20496
20678
|
const [jwtError, claims] = catchError(() => parseJWT(accessToken));
|
|
20497
20679
|
if (!jwtError && claims) {
|
|
20498
20680
|
const rawOrgId = claims.prtId ?? claims.organizationId ?? claims.prt_id;
|
|
@@ -20503,15 +20685,19 @@ var tryRobotClientFallback = async (options = {}) => {
|
|
|
20503
20685
|
if (typeof tenantClaim === "string" && tenantClaim.length > 0) {
|
|
20504
20686
|
tenantIdFromToken = tenantClaim;
|
|
20505
20687
|
}
|
|
20688
|
+
const issClaim = claims.iss;
|
|
20689
|
+
if (typeof issClaim === "string" && issClaim.length > 0) {
|
|
20690
|
+
issuerFromToken = issClaim;
|
|
20691
|
+
}
|
|
20506
20692
|
}
|
|
20507
|
-
printNoticeOnce();
|
|
20508
20693
|
return {
|
|
20509
20694
|
accessToken,
|
|
20510
20695
|
baseUrl: parsedUrl.baseUrl,
|
|
20511
20696
|
organizationName: parsedUrl.organizationName,
|
|
20512
20697
|
organizationId: organizationIdFromToken ?? parsedUrl.organizationName,
|
|
20513
20698
|
tenantName: parsedUrl.tenantName,
|
|
20514
|
-
tenantId: tenantIdFromToken
|
|
20699
|
+
tenantId: tenantIdFromToken,
|
|
20700
|
+
issuer: issuerFromToken
|
|
20515
20701
|
};
|
|
20516
20702
|
} catch {
|
|
20517
20703
|
return;
|
|
@@ -20614,7 +20800,7 @@ var probeAsync = async (fs7, candidate) => {
|
|
|
20614
20800
|
};
|
|
20615
20801
|
}
|
|
20616
20802
|
};
|
|
20617
|
-
var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME) => {
|
|
20803
|
+
var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) => {
|
|
20618
20804
|
const fs7 = getFileSystem();
|
|
20619
20805
|
if (fs7.path.isAbsolute(envFilePath)) {
|
|
20620
20806
|
const probe2 = await probeAsync(fs7, envFilePath);
|
|
@@ -20625,7 +20811,7 @@ var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME) =>
|
|
|
20625
20811
|
...probe2.unusable ? { unusable: probe2.unusable } : {}
|
|
20626
20812
|
};
|
|
20627
20813
|
}
|
|
20628
|
-
const cwd = fs7.env.cwd();
|
|
20814
|
+
const cwd = opts?.cwd ?? fs7.env.cwd();
|
|
20629
20815
|
let searchDir = cwd;
|
|
20630
20816
|
while (true) {
|
|
20631
20817
|
const candidate = fs7.path.join(searchDir, envFilePath);
|
|
@@ -20655,8 +20841,8 @@ var resolveEnvFileLocationAsync = async (envFilePath = DEFAULT_ENV_FILENAME) =>
|
|
|
20655
20841
|
...probe.unusable ? { unusable: probe.unusable } : {}
|
|
20656
20842
|
};
|
|
20657
20843
|
};
|
|
20658
|
-
var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME) => {
|
|
20659
|
-
const location = await resolveEnvFileLocationAsync(envFilePath);
|
|
20844
|
+
var resolveEnvFilePathAsync = async (envFilePath = DEFAULT_ENV_FILENAME, opts) => {
|
|
20845
|
+
const location = await resolveEnvFileLocationAsync(envFilePath, opts);
|
|
20660
20846
|
if (location.exists) {
|
|
20661
20847
|
return { absolutePath: location.absolutePath };
|
|
20662
20848
|
}
|
|
@@ -20733,19 +20919,329 @@ var LoginStatusSource;
|
|
|
20733
20919
|
((LoginStatusSource2) => {
|
|
20734
20920
|
LoginStatusSource2["File"] = "file";
|
|
20735
20921
|
LoginStatusSource2["Robot"] = "robot";
|
|
20922
|
+
LoginStatusSource2["Env"] = "env";
|
|
20736
20923
|
})(LoginStatusSource ||= {});
|
|
20737
|
-
|
|
20738
|
-
return
|
|
20924
|
+
var getLoginStatusAsync = async (options = {}) => {
|
|
20925
|
+
return getLoginStatusWithDeps(options);
|
|
20926
|
+
};
|
|
20927
|
+
var getLoginStatusWithDeps = async (options = {}, deps = {}) => {
|
|
20928
|
+
const {
|
|
20929
|
+
resolveEnvFilePath = resolveEnvFilePathAsync,
|
|
20930
|
+
loadEnvFile = loadEnvFileAsync,
|
|
20931
|
+
saveEnvFile = saveEnvFileAsync,
|
|
20932
|
+
getFs = getFileSystem,
|
|
20933
|
+
refreshToken: refreshTokenFn = refreshAccessToken,
|
|
20934
|
+
resolveConfig = resolveConfigAsync,
|
|
20935
|
+
robotFallback = tryRobotClientFallback,
|
|
20936
|
+
loadBreaker = loadRefreshBreaker,
|
|
20937
|
+
saveBreaker = saveRefreshBreaker,
|
|
20938
|
+
clearBreaker = clearRefreshBreaker
|
|
20939
|
+
} = deps;
|
|
20940
|
+
if (isRobotAuthEnforced()) {
|
|
20941
|
+
return resolveRobotEnforcedStatus(robotFallback);
|
|
20942
|
+
}
|
|
20943
|
+
if (isEnvAuthEnabled()) {
|
|
20944
|
+
return readAuthFromEnv();
|
|
20945
|
+
}
|
|
20946
|
+
const activeProfile = getActiveAuthProfile();
|
|
20947
|
+
const activeProfileFilePath = getActiveAuthProfileFilePath();
|
|
20948
|
+
const usingActiveProfile = activeProfile !== undefined && (options.envFilePath === undefined || options.envFilePath === activeProfileFilePath);
|
|
20949
|
+
const envFilePath = options.envFilePath ?? activeProfileFilePath ?? DEFAULT_ENV_FILENAME;
|
|
20950
|
+
const { ensureTokenValidityMinutes } = options;
|
|
20951
|
+
const { absolutePath } = await resolveEnvFilePath(envFilePath);
|
|
20952
|
+
if (absolutePath === undefined) {
|
|
20953
|
+
if (usingActiveProfile) {
|
|
20954
|
+
return {
|
|
20955
|
+
loginStatus: "Not logged in",
|
|
20956
|
+
hint: `No credentials found for profile "${activeProfile}". Run 'uip login --profile ${activeProfile}' to authenticate this profile.`
|
|
20957
|
+
};
|
|
20958
|
+
}
|
|
20959
|
+
return resolveBorrowedRobotStatus(robotFallback);
|
|
20960
|
+
}
|
|
20961
|
+
const loaded = await loadFileCredentials(loadEnvFile, absolutePath);
|
|
20962
|
+
if ("status" in loaded) {
|
|
20963
|
+
return loaded.status;
|
|
20964
|
+
}
|
|
20965
|
+
const { credentials } = loaded;
|
|
20966
|
+
const globalHint = () => usingActiveProfile ? Promise.resolve(undefined) : getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath);
|
|
20967
|
+
const expiration = getTokenExpiration(credentials.UIPATH_ACCESS_TOKEN);
|
|
20968
|
+
const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
20969
|
+
let tokens = {
|
|
20970
|
+
accessToken: credentials.UIPATH_ACCESS_TOKEN,
|
|
20971
|
+
refreshToken: credentials.UIPATH_REFRESH_TOKEN,
|
|
20972
|
+
expiration,
|
|
20973
|
+
lockReleaseFailed: false
|
|
20974
|
+
};
|
|
20975
|
+
const refreshToken = credentials.UIPATH_REFRESH_TOKEN;
|
|
20976
|
+
if (expiration && expiration <= outerThreshold && refreshToken) {
|
|
20977
|
+
const refreshed = await attemptRefresh({
|
|
20978
|
+
absolutePath,
|
|
20979
|
+
credentials,
|
|
20980
|
+
accessToken: credentials.UIPATH_ACCESS_TOKEN,
|
|
20981
|
+
refreshToken,
|
|
20982
|
+
expiration,
|
|
20983
|
+
ensureTokenValidityMinutes,
|
|
20984
|
+
getFs,
|
|
20985
|
+
loadEnvFile,
|
|
20986
|
+
saveEnvFile,
|
|
20987
|
+
refreshFn: refreshTokenFn,
|
|
20988
|
+
resolveConfig,
|
|
20989
|
+
loadBreaker,
|
|
20990
|
+
saveBreaker,
|
|
20991
|
+
clearBreaker,
|
|
20992
|
+
globalHint
|
|
20993
|
+
});
|
|
20994
|
+
if (refreshed.kind === "terminal") {
|
|
20995
|
+
return refreshed.status;
|
|
20996
|
+
}
|
|
20997
|
+
tokens = refreshed.tokens;
|
|
20998
|
+
}
|
|
20999
|
+
return buildFileStatus(tokens, credentials, globalHint);
|
|
21000
|
+
};
|
|
21001
|
+
async function resolveRobotEnforcedStatus(robotFallback) {
|
|
21002
|
+
if (isEnvAuthEnabled()) {
|
|
21003
|
+
throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
|
|
21004
|
+
}
|
|
21005
|
+
const robotCreds = await robotFallback({ force: true });
|
|
21006
|
+
if (!robotCreds) {
|
|
21007
|
+
return {
|
|
21008
|
+
loginStatus: "Not logged in",
|
|
21009
|
+
hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
|
|
21010
|
+
};
|
|
21011
|
+
}
|
|
21012
|
+
return buildRobotStatus(robotCreds);
|
|
20739
21013
|
}
|
|
20740
|
-
function
|
|
20741
|
-
|
|
21014
|
+
async function resolveBorrowedRobotStatus(robotFallback) {
|
|
21015
|
+
const robotCreds = await robotFallback();
|
|
21016
|
+
return robotCreds ? buildRobotStatus(robotCreds) : { loginStatus: "Not logged in" };
|
|
20742
21017
|
}
|
|
20743
|
-
function
|
|
20744
|
-
|
|
21018
|
+
async function loadFileCredentials(loadEnvFile, absolutePath) {
|
|
21019
|
+
let credentials;
|
|
21020
|
+
try {
|
|
21021
|
+
credentials = await loadEnvFile({ envPath: absolutePath });
|
|
21022
|
+
} catch (error) {
|
|
21023
|
+
if (isFileNotFoundError(error)) {
|
|
21024
|
+
return { status: { loginStatus: "Not logged in" } };
|
|
21025
|
+
}
|
|
21026
|
+
throw error;
|
|
21027
|
+
}
|
|
21028
|
+
if (!credentials.UIPATH_ACCESS_TOKEN) {
|
|
21029
|
+
return { status: { loginStatus: "Not logged in" } };
|
|
21030
|
+
}
|
|
21031
|
+
return { credentials };
|
|
21032
|
+
}
|
|
21033
|
+
async function getGlobalCredsHint(getFs, loadEnvFile, absolutePath, envFilePath) {
|
|
21034
|
+
const fs7 = getFs();
|
|
21035
|
+
const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
|
|
21036
|
+
if (absolutePath === globalPath)
|
|
21037
|
+
return;
|
|
21038
|
+
if (!await fs7.exists(globalPath))
|
|
21039
|
+
return;
|
|
21040
|
+
try {
|
|
21041
|
+
const globalCreds = await loadEnvFile({ envPath: globalPath });
|
|
21042
|
+
if (!globalCreds.UIPATH_ACCESS_TOKEN)
|
|
21043
|
+
return;
|
|
21044
|
+
const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
|
|
21045
|
+
if (globalExp && globalExp <= new Date)
|
|
21046
|
+
return;
|
|
21047
|
+
return `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
|
|
21048
|
+
} catch {
|
|
21049
|
+
return;
|
|
21050
|
+
}
|
|
20745
21051
|
}
|
|
20746
21052
|
function computeExpirationThreshold(ensureTokenValidityMinutes) {
|
|
20747
21053
|
return new Date(Date.now() + (ensureTokenValidityMinutes ?? 0) * 60 * 1000);
|
|
20748
21054
|
}
|
|
21055
|
+
async function attemptRefresh(ctx) {
|
|
21056
|
+
const shortCircuit = await circuitBreakerShortCircuit(ctx);
|
|
21057
|
+
if (shortCircuit) {
|
|
21058
|
+
return { kind: "terminal", status: shortCircuit };
|
|
21059
|
+
}
|
|
21060
|
+
let release;
|
|
21061
|
+
try {
|
|
21062
|
+
release = await ctx.getFs().acquireLock(ctx.absolutePath);
|
|
21063
|
+
} catch (error) {
|
|
21064
|
+
return {
|
|
21065
|
+
kind: "terminal",
|
|
21066
|
+
status: await lockAcquireFailureStatus(ctx, error)
|
|
21067
|
+
};
|
|
21068
|
+
}
|
|
21069
|
+
let lockedFailure;
|
|
21070
|
+
let lockReleaseFailed = false;
|
|
21071
|
+
let success;
|
|
21072
|
+
try {
|
|
21073
|
+
const outcome = await runRefreshLocked({
|
|
21074
|
+
absolutePath: ctx.absolutePath,
|
|
21075
|
+
refreshToken: ctx.refreshToken,
|
|
21076
|
+
customAuthority: ctx.credentials.UIPATH_URL,
|
|
21077
|
+
ensureTokenValidityMinutes: ctx.ensureTokenValidityMinutes,
|
|
21078
|
+
loadEnvFile: ctx.loadEnvFile,
|
|
21079
|
+
saveEnvFile: ctx.saveEnvFile,
|
|
21080
|
+
refreshFn: ctx.refreshFn,
|
|
21081
|
+
resolveConfig: ctx.resolveConfig,
|
|
21082
|
+
loadBreaker: ctx.loadBreaker,
|
|
21083
|
+
saveBreaker: ctx.saveBreaker,
|
|
21084
|
+
clearBreaker: ctx.clearBreaker
|
|
21085
|
+
});
|
|
21086
|
+
if (outcome.kind === "fail") {
|
|
21087
|
+
lockedFailure = outcome.status;
|
|
21088
|
+
} else {
|
|
21089
|
+
success = outcome;
|
|
21090
|
+
}
|
|
21091
|
+
} finally {
|
|
21092
|
+
try {
|
|
21093
|
+
await release();
|
|
21094
|
+
} catch {
|
|
21095
|
+
lockReleaseFailed = true;
|
|
21096
|
+
}
|
|
21097
|
+
}
|
|
21098
|
+
if (lockedFailure) {
|
|
21099
|
+
const globalHint = await ctx.globalHint();
|
|
21100
|
+
const base = globalHint ? { ...lockedFailure, loginStatus: "Expired", hint: globalHint } : lockedFailure;
|
|
21101
|
+
return {
|
|
21102
|
+
kind: "terminal",
|
|
21103
|
+
status: lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base
|
|
21104
|
+
};
|
|
21105
|
+
}
|
|
21106
|
+
return {
|
|
21107
|
+
kind: "refreshed",
|
|
21108
|
+
tokens: {
|
|
21109
|
+
accessToken: success?.accessToken,
|
|
21110
|
+
refreshToken: success?.refreshToken,
|
|
21111
|
+
expiration: success?.expiration,
|
|
21112
|
+
tokenRefresh: success?.tokenRefresh,
|
|
21113
|
+
persistenceWarning: success?.persistenceWarning,
|
|
21114
|
+
lockReleaseFailed
|
|
21115
|
+
}
|
|
21116
|
+
};
|
|
21117
|
+
}
|
|
21118
|
+
async function buildFileStatus(tokens, credentials, globalHint) {
|
|
21119
|
+
const result = {
|
|
21120
|
+
loginStatus: tokens.expiration && tokens.expiration <= new Date ? "Expired" : "Logged in",
|
|
21121
|
+
accessToken: tokens.accessToken,
|
|
21122
|
+
refreshToken: tokens.refreshToken,
|
|
21123
|
+
baseUrl: credentials.UIPATH_URL,
|
|
21124
|
+
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
21125
|
+
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
21126
|
+
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
21127
|
+
tenantId: credentials.UIPATH_TENANT_ID,
|
|
21128
|
+
expiration: tokens.expiration,
|
|
21129
|
+
source: "file" /* File */,
|
|
21130
|
+
...tokens.persistenceWarning ? { hint: tokens.persistenceWarning, persistenceFailed: true } : {},
|
|
21131
|
+
...tokens.lockReleaseFailed ? { lockReleaseFailed: true } : {},
|
|
21132
|
+
...tokens.tokenRefresh ? { tokenRefresh: tokens.tokenRefresh } : {}
|
|
21133
|
+
};
|
|
21134
|
+
if (result.loginStatus === "Expired") {
|
|
21135
|
+
const hint = await globalHint();
|
|
21136
|
+
if (hint) {
|
|
21137
|
+
result.hint = hint;
|
|
21138
|
+
}
|
|
21139
|
+
}
|
|
21140
|
+
return result;
|
|
21141
|
+
}
|
|
21142
|
+
function buildRobotStatus(robotCreds) {
|
|
21143
|
+
return {
|
|
21144
|
+
loginStatus: "Logged in",
|
|
21145
|
+
accessToken: robotCreds.accessToken,
|
|
21146
|
+
baseUrl: robotCreds.baseUrl,
|
|
21147
|
+
organizationName: robotCreds.organizationName,
|
|
21148
|
+
organizationId: robotCreds.organizationId,
|
|
21149
|
+
tenantName: robotCreds.tenantName,
|
|
21150
|
+
tenantId: robotCreds.tenantId,
|
|
21151
|
+
issuer: robotCreds.issuer,
|
|
21152
|
+
expiration: getTokenExpiration(robotCreds.accessToken),
|
|
21153
|
+
source: "robot" /* Robot */
|
|
21154
|
+
};
|
|
21155
|
+
}
|
|
21156
|
+
var isFileNotFoundError = (error) => {
|
|
21157
|
+
if (!(error instanceof Object))
|
|
21158
|
+
return false;
|
|
21159
|
+
return error.code === "ENOENT";
|
|
21160
|
+
};
|
|
21161
|
+
async function circuitBreakerShortCircuit(ctx) {
|
|
21162
|
+
const {
|
|
21163
|
+
absolutePath,
|
|
21164
|
+
refreshToken,
|
|
21165
|
+
accessToken,
|
|
21166
|
+
credentials,
|
|
21167
|
+
expiration,
|
|
21168
|
+
loadBreaker,
|
|
21169
|
+
saveBreaker,
|
|
21170
|
+
clearBreaker
|
|
21171
|
+
} = ctx;
|
|
21172
|
+
const fingerprint = await refreshTokenFingerprint(refreshToken);
|
|
21173
|
+
const breaker = await loadBreaker(absolutePath).catch(() => ({}));
|
|
21174
|
+
if (breaker.deadTokenFp && breaker.deadTokenFp !== fingerprint) {
|
|
21175
|
+
await clearBreaker(absolutePath);
|
|
21176
|
+
breaker.deadTokenFp = undefined;
|
|
21177
|
+
}
|
|
21178
|
+
const nowMs = Date.now();
|
|
21179
|
+
const tokenIsDead = breaker.deadTokenFp === fingerprint;
|
|
21180
|
+
const inBackoff = breaker.backoffUntilMs !== undefined && nowMs < breaker.backoffUntilMs;
|
|
21181
|
+
if (!tokenIsDead && !inBackoff)
|
|
21182
|
+
return;
|
|
21183
|
+
const globalHint = await ctx.globalHint();
|
|
21184
|
+
const suppressed = !shouldSurface(breaker, nowMs);
|
|
21185
|
+
if (!suppressed) {
|
|
21186
|
+
await saveBreaker(absolutePath, {
|
|
21187
|
+
...breaker,
|
|
21188
|
+
lastSurfacedAtMs: nowMs
|
|
21189
|
+
});
|
|
21190
|
+
}
|
|
21191
|
+
const deadHint = "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired. In a non-interactive context, authenticate with: uip login --client-id <id> --client-secret <secret> -t <tenant>.";
|
|
21192
|
+
const backoffHint = "Token refresh is temporarily backed off after a recent network error and will retry automatically once the backoff window elapses.";
|
|
21193
|
+
return {
|
|
21194
|
+
loginStatus: globalHint ? "Expired" : "Refresh Failed",
|
|
21195
|
+
...globalHint ? {
|
|
21196
|
+
accessToken,
|
|
21197
|
+
refreshToken,
|
|
21198
|
+
baseUrl: credentials.UIPATH_URL,
|
|
21199
|
+
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
21200
|
+
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
21201
|
+
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
21202
|
+
tenantId: credentials.UIPATH_TENANT_ID,
|
|
21203
|
+
expiration,
|
|
21204
|
+
source: "file" /* File */
|
|
21205
|
+
} : {},
|
|
21206
|
+
hint: globalHint ?? (tokenIsDead ? deadHint : backoffHint),
|
|
21207
|
+
refreshCircuitOpen: true,
|
|
21208
|
+
refreshTelemetrySuppressed: suppressed,
|
|
21209
|
+
tokenRefresh: { attempted: false, success: false }
|
|
21210
|
+
};
|
|
21211
|
+
}
|
|
21212
|
+
async function lockAcquireFailureStatus(ctx, error) {
|
|
21213
|
+
const msg = errorMessage(error);
|
|
21214
|
+
const globalHint = await ctx.globalHint();
|
|
21215
|
+
if (globalHint) {
|
|
21216
|
+
return {
|
|
21217
|
+
loginStatus: "Expired",
|
|
21218
|
+
accessToken: ctx.accessToken,
|
|
21219
|
+
refreshToken: ctx.refreshToken,
|
|
21220
|
+
baseUrl: ctx.credentials.UIPATH_URL,
|
|
21221
|
+
organizationName: ctx.credentials.UIPATH_ORGANIZATION_NAME,
|
|
21222
|
+
organizationId: ctx.credentials.UIPATH_ORGANIZATION_ID,
|
|
21223
|
+
tenantName: ctx.credentials.UIPATH_TENANT_NAME,
|
|
21224
|
+
tenantId: ctx.credentials.UIPATH_TENANT_ID,
|
|
21225
|
+
expiration: ctx.expiration,
|
|
21226
|
+
source: "file" /* File */,
|
|
21227
|
+
hint: globalHint,
|
|
21228
|
+
tokenRefresh: {
|
|
21229
|
+
attempted: false,
|
|
21230
|
+
success: false,
|
|
21231
|
+
errorMessage: `lock acquisition failed: ${msg}`
|
|
21232
|
+
}
|
|
21233
|
+
};
|
|
21234
|
+
}
|
|
21235
|
+
return {
|
|
21236
|
+
loginStatus: "Refresh Failed",
|
|
21237
|
+
hint: "Could not acquire the auth-file lock — too many concurrent `uip` processes, or a permission issue on the auth directory. Retry, or run 'uip login' to re-authenticate.",
|
|
21238
|
+
tokenRefresh: {
|
|
21239
|
+
attempted: false,
|
|
21240
|
+
success: false,
|
|
21241
|
+
errorMessage: `lock acquisition failed: ${msg}`
|
|
21242
|
+
}
|
|
21243
|
+
};
|
|
21244
|
+
}
|
|
20749
21245
|
async function runRefreshLocked(inputs) {
|
|
20750
21246
|
const {
|
|
20751
21247
|
absolutePath,
|
|
@@ -20755,7 +21251,10 @@ async function runRefreshLocked(inputs) {
|
|
|
20755
21251
|
loadEnvFile,
|
|
20756
21252
|
saveEnvFile,
|
|
20757
21253
|
refreshFn,
|
|
20758
|
-
resolveConfig
|
|
21254
|
+
resolveConfig,
|
|
21255
|
+
loadBreaker,
|
|
21256
|
+
saveBreaker,
|
|
21257
|
+
clearBreaker
|
|
20759
21258
|
} = inputs;
|
|
20760
21259
|
const expirationThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
20761
21260
|
let fresh;
|
|
@@ -20778,6 +21277,7 @@ async function runRefreshLocked(inputs) {
|
|
|
20778
21277
|
const freshAccess = fresh.UIPATH_ACCESS_TOKEN;
|
|
20779
21278
|
const freshExp = freshAccess ? getTokenExpiration(freshAccess) : undefined;
|
|
20780
21279
|
if (freshAccess && freshExp && freshExp > expirationThreshold) {
|
|
21280
|
+
await clearBreaker(absolutePath);
|
|
20781
21281
|
return {
|
|
20782
21282
|
kind: "ok",
|
|
20783
21283
|
accessToken: freshAccess,
|
|
@@ -20801,8 +21301,21 @@ async function runRefreshLocked(inputs) {
|
|
|
20801
21301
|
refreshedRefresh = refreshed.refreshToken;
|
|
20802
21302
|
} catch (error) {
|
|
20803
21303
|
const isOAuthFailure = isTokenRefreshOAuthFailure(error);
|
|
20804
|
-
const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
|
|
21304
|
+
const hint = isOAuthFailure ? "Run 'uip login' to re-authenticate — the stored refresh token is invalid or expired. In a non-interactive context, authenticate with: uip login --client-id <id> --client-secret <secret> -t <tenant>." : "Token refresh failed. Check your network connection, then retry or run 'uip login' to re-authenticate.";
|
|
20805
21305
|
const message = isOAuthFailure ? normalizeTokenRefreshFailure() : normalizeTokenRefreshUnavailableFailure();
|
|
21306
|
+
const fp = await refreshTokenFingerprint(tokenForIdP);
|
|
21307
|
+
if (isOAuthFailure) {
|
|
21308
|
+
await saveBreaker(absolutePath, { deadTokenFp: fp });
|
|
21309
|
+
} else {
|
|
21310
|
+
const prior = await loadBreaker(absolutePath).catch(() => ({}));
|
|
21311
|
+
const attempts = (prior.attempts ?? 0) + 1;
|
|
21312
|
+
await saveBreaker(absolutePath, {
|
|
21313
|
+
...prior,
|
|
21314
|
+
deadTokenFp: undefined,
|
|
21315
|
+
attempts,
|
|
21316
|
+
backoffUntilMs: Date.now() + nextBackoffMs(attempts)
|
|
21317
|
+
});
|
|
21318
|
+
}
|
|
20806
21319
|
return {
|
|
20807
21320
|
kind: "fail",
|
|
20808
21321
|
status: {
|
|
@@ -20831,6 +21344,7 @@ async function runRefreshLocked(inputs) {
|
|
|
20831
21344
|
}
|
|
20832
21345
|
};
|
|
20833
21346
|
}
|
|
21347
|
+
await clearBreaker(absolutePath);
|
|
20834
21348
|
try {
|
|
20835
21349
|
await saveEnvFile({
|
|
20836
21350
|
envPath: absolutePath,
|
|
@@ -20863,215 +21377,21 @@ async function runRefreshLocked(inputs) {
|
|
|
20863
21377
|
};
|
|
20864
21378
|
}
|
|
20865
21379
|
}
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
20875
|
-
} = deps;
|
|
20876
|
-
if (isRobotAuthEnforced()) {
|
|
20877
|
-
if (isEnvAuthEnabled()) {
|
|
20878
|
-
throw new EnvAuthConfigError(`${ENV_AUTH_ENABLE_VAR}=true and ${ENFORCE_ROBOT_AUTH_VAR}=true ` + `are mutually exclusive. Unset one of them and re-run.`);
|
|
20879
|
-
}
|
|
20880
|
-
const robotCreds = await robotFallback({ force: true });
|
|
20881
|
-
if (!robotCreds) {
|
|
20882
|
-
return {
|
|
20883
|
-
loginStatus: "Not logged in",
|
|
20884
|
-
hint: `${ENFORCE_ROBOT_AUTH_VAR}=true but the UiPath Robot ` + `session is unavailable. Start and sign in to the Assistant, ` + `or unset ${ENFORCE_ROBOT_AUTH_VAR} to fall back to file or ` + `env-var authentication.`
|
|
20885
|
-
};
|
|
20886
|
-
}
|
|
20887
|
-
const expiration2 = getTokenExpiration(robotCreds.accessToken);
|
|
20888
|
-
return {
|
|
20889
|
-
loginStatus: "Logged in",
|
|
20890
|
-
accessToken: robotCreds.accessToken,
|
|
20891
|
-
baseUrl: robotCreds.baseUrl,
|
|
20892
|
-
organizationName: robotCreds.organizationName,
|
|
20893
|
-
organizationId: robotCreds.organizationId,
|
|
20894
|
-
tenantName: robotCreds.tenantName,
|
|
20895
|
-
tenantId: robotCreds.tenantId,
|
|
20896
|
-
expiration: expiration2,
|
|
20897
|
-
source: "robot" /* Robot */
|
|
20898
|
-
};
|
|
20899
|
-
}
|
|
20900
|
-
if (isEnvAuthEnabled()) {
|
|
20901
|
-
return readAuthFromEnv();
|
|
20902
|
-
}
|
|
20903
|
-
const { envFilePath = DEFAULT_ENV_FILENAME, ensureTokenValidityMinutes } = options;
|
|
20904
|
-
const { absolutePath } = await resolveEnvFilePath(envFilePath);
|
|
20905
|
-
if (absolutePath === undefined) {
|
|
20906
|
-
const robotCreds = await robotFallback();
|
|
20907
|
-
if (robotCreds) {
|
|
20908
|
-
const expiration2 = getTokenExpiration(robotCreds.accessToken);
|
|
20909
|
-
const status = {
|
|
20910
|
-
loginStatus: "Logged in",
|
|
20911
|
-
accessToken: robotCreds.accessToken,
|
|
20912
|
-
baseUrl: robotCreds.baseUrl,
|
|
20913
|
-
organizationName: robotCreds.organizationName,
|
|
20914
|
-
organizationId: robotCreds.organizationId,
|
|
20915
|
-
tenantName: robotCreds.tenantName,
|
|
20916
|
-
tenantId: robotCreds.tenantId,
|
|
20917
|
-
expiration: expiration2,
|
|
20918
|
-
source: "robot" /* Robot */
|
|
20919
|
-
};
|
|
20920
|
-
return status;
|
|
20921
|
-
}
|
|
20922
|
-
return { loginStatus: "Not logged in" };
|
|
20923
|
-
}
|
|
20924
|
-
let credentials;
|
|
20925
|
-
try {
|
|
20926
|
-
credentials = await loadEnvFile({ envPath: absolutePath });
|
|
20927
|
-
} catch (error) {
|
|
20928
|
-
if (isFileNotFoundError(error)) {
|
|
20929
|
-
return { loginStatus: "Not logged in" };
|
|
20930
|
-
}
|
|
20931
|
-
throw error;
|
|
20932
|
-
}
|
|
20933
|
-
if (!credentials.UIPATH_ACCESS_TOKEN) {
|
|
20934
|
-
return { loginStatus: "Not logged in" };
|
|
20935
|
-
}
|
|
20936
|
-
let accessToken = credentials.UIPATH_ACCESS_TOKEN;
|
|
20937
|
-
let refreshToken = credentials.UIPATH_REFRESH_TOKEN;
|
|
20938
|
-
let expiration = getTokenExpiration(accessToken);
|
|
20939
|
-
let persistenceWarning;
|
|
20940
|
-
let lockReleaseFailed = false;
|
|
20941
|
-
let tokenRefresh;
|
|
20942
|
-
const outerThreshold = computeExpirationThreshold(ensureTokenValidityMinutes);
|
|
20943
|
-
const tryGlobalCredsHint = async () => {
|
|
20944
|
-
const fs7 = getFs();
|
|
20945
|
-
const globalPath = fs7.path.join(fs7.env.homedir(), envFilePath);
|
|
20946
|
-
if (absolutePath === globalPath)
|
|
20947
|
-
return;
|
|
20948
|
-
if (!await fs7.exists(globalPath))
|
|
20949
|
-
return;
|
|
20950
|
-
try {
|
|
20951
|
-
const globalCreds = await loadEnvFile({ envPath: globalPath });
|
|
20952
|
-
if (!globalCreds.UIPATH_ACCESS_TOKEN)
|
|
20953
|
-
return;
|
|
20954
|
-
const globalExp = getTokenExpiration(globalCreds.UIPATH_ACCESS_TOKEN);
|
|
20955
|
-
if (globalExp && globalExp <= new Date)
|
|
20956
|
-
return;
|
|
20957
|
-
return `Local credentials file at ${absolutePath} has expired credentials. Valid credentials exist in ${globalPath}. Remove the local file or run 'uip login' to re-authenticate.`;
|
|
20958
|
-
} catch {
|
|
20959
|
-
return;
|
|
20960
|
-
}
|
|
20961
|
-
};
|
|
20962
|
-
if (expiration && expiration <= outerThreshold && refreshToken) {
|
|
20963
|
-
let release;
|
|
20964
|
-
try {
|
|
20965
|
-
release = await getFs().acquireLock(absolutePath);
|
|
20966
|
-
} catch (error) {
|
|
20967
|
-
const msg = errorMessage(error);
|
|
20968
|
-
const globalHint = await tryGlobalCredsHint();
|
|
20969
|
-
if (globalHint) {
|
|
20970
|
-
return {
|
|
20971
|
-
loginStatus: "Expired",
|
|
20972
|
-
accessToken,
|
|
20973
|
-
refreshToken,
|
|
20974
|
-
baseUrl: credentials.UIPATH_URL,
|
|
20975
|
-
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
20976
|
-
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
20977
|
-
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
20978
|
-
tenantId: credentials.UIPATH_TENANT_ID,
|
|
20979
|
-
expiration,
|
|
20980
|
-
source: "file" /* File */,
|
|
20981
|
-
hint: globalHint,
|
|
20982
|
-
tokenRefresh: {
|
|
20983
|
-
attempted: false,
|
|
20984
|
-
success: false,
|
|
20985
|
-
errorMessage: `lock acquisition failed: ${msg}`
|
|
20986
|
-
}
|
|
20987
|
-
};
|
|
20988
|
-
}
|
|
20989
|
-
return {
|
|
20990
|
-
loginStatus: "Refresh Failed",
|
|
20991
|
-
hint: "Could not acquire the auth-file lock — too many concurrent `uip` processes, or a permission issue on the auth directory. Retry, or run 'uip login' to re-authenticate.",
|
|
20992
|
-
tokenRefresh: {
|
|
20993
|
-
attempted: false,
|
|
20994
|
-
success: false,
|
|
20995
|
-
errorMessage: `lock acquisition failed: ${msg}`
|
|
20996
|
-
}
|
|
20997
|
-
};
|
|
20998
|
-
}
|
|
20999
|
-
let lockedFailure;
|
|
21000
|
-
try {
|
|
21001
|
-
const outcome = await runRefreshLocked({
|
|
21002
|
-
absolutePath,
|
|
21003
|
-
refreshToken,
|
|
21004
|
-
customAuthority: credentials.UIPATH_URL,
|
|
21005
|
-
ensureTokenValidityMinutes,
|
|
21006
|
-
loadEnvFile,
|
|
21007
|
-
saveEnvFile,
|
|
21008
|
-
refreshFn: refreshTokenFn,
|
|
21009
|
-
resolveConfig
|
|
21010
|
-
});
|
|
21011
|
-
if (outcome.kind === "fail") {
|
|
21012
|
-
lockedFailure = outcome.status;
|
|
21013
|
-
} else {
|
|
21014
|
-
accessToken = outcome.accessToken;
|
|
21015
|
-
refreshToken = outcome.refreshToken;
|
|
21016
|
-
expiration = outcome.expiration;
|
|
21017
|
-
tokenRefresh = outcome.tokenRefresh;
|
|
21018
|
-
if (outcome.persistenceWarning) {
|
|
21019
|
-
persistenceWarning = outcome.persistenceWarning;
|
|
21020
|
-
}
|
|
21021
|
-
}
|
|
21022
|
-
} finally {
|
|
21023
|
-
try {
|
|
21024
|
-
await release();
|
|
21025
|
-
} catch {
|
|
21026
|
-
lockReleaseFailed = true;
|
|
21027
|
-
}
|
|
21028
|
-
}
|
|
21029
|
-
if (lockedFailure) {
|
|
21030
|
-
const globalHint = await tryGlobalCredsHint();
|
|
21031
|
-
const base = globalHint ? {
|
|
21032
|
-
...lockedFailure,
|
|
21033
|
-
loginStatus: "Expired",
|
|
21034
|
-
hint: globalHint
|
|
21035
|
-
} : lockedFailure;
|
|
21036
|
-
return lockReleaseFailed ? { ...base, lockReleaseFailed: true } : base;
|
|
21037
|
-
}
|
|
21038
|
-
}
|
|
21039
|
-
const result = {
|
|
21040
|
-
loginStatus: expiration && expiration <= new Date ? "Expired" : "Logged in",
|
|
21041
|
-
accessToken,
|
|
21042
|
-
refreshToken,
|
|
21043
|
-
baseUrl: credentials.UIPATH_URL,
|
|
21044
|
-
organizationName: credentials.UIPATH_ORGANIZATION_NAME,
|
|
21045
|
-
organizationId: credentials.UIPATH_ORGANIZATION_ID,
|
|
21046
|
-
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
21047
|
-
tenantId: credentials.UIPATH_TENANT_ID,
|
|
21048
|
-
expiration,
|
|
21049
|
-
source: "file" /* File */,
|
|
21050
|
-
...persistenceWarning ? { hint: persistenceWarning, persistenceFailed: true } : {},
|
|
21051
|
-
...lockReleaseFailed ? { lockReleaseFailed: true } : {},
|
|
21052
|
-
...tokenRefresh ? { tokenRefresh } : {}
|
|
21053
|
-
};
|
|
21054
|
-
if (result.loginStatus === "Expired") {
|
|
21055
|
-
const globalHint = await tryGlobalCredsHint();
|
|
21056
|
-
if (globalHint) {
|
|
21057
|
-
result.hint = globalHint;
|
|
21058
|
-
}
|
|
21059
|
-
}
|
|
21060
|
-
return result;
|
|
21061
|
-
};
|
|
21062
|
-
var isFileNotFoundError = (error) => {
|
|
21063
|
-
if (!(error instanceof Object))
|
|
21064
|
-
return false;
|
|
21065
|
-
return error.code === "ENOENT";
|
|
21066
|
-
};
|
|
21067
|
-
var getLoginStatusAsync = async (options = {}) => {
|
|
21068
|
-
return getLoginStatusWithDeps(options);
|
|
21069
|
-
};
|
|
21380
|
+
function normalizeTokenRefreshFailure() {
|
|
21381
|
+
return "stored refresh token is invalid or expired";
|
|
21382
|
+
}
|
|
21383
|
+
function normalizeTokenRefreshUnavailableFailure() {
|
|
21384
|
+
return "token refresh failed before authentication completed";
|
|
21385
|
+
}
|
|
21386
|
+
function errorMessage(error) {
|
|
21387
|
+
return error instanceof Error ? error.message : String(error);
|
|
21388
|
+
}
|
|
21070
21389
|
|
|
21071
21390
|
// src/authContext.ts
|
|
21072
21391
|
var getAuthContext = async (options = {}) => {
|
|
21073
21392
|
const status = await getLoginStatusAsync({
|
|
21074
|
-
ensureTokenValidityMinutes: options.ensureTokenValidityMinutes
|
|
21393
|
+
ensureTokenValidityMinutes: options.ensureTokenValidityMinutes,
|
|
21394
|
+
envFilePath: options.envFilePath
|
|
21075
21395
|
});
|
|
21076
21396
|
if (status.loginStatus !== "Logged in" || !status.baseUrl || !status.accessToken) {
|
|
21077
21397
|
throw new Error(status.hint ? `Not logged in. ${status.hint}` : "Not logged in. Run 'uip login' first.");
|
|
@@ -21098,7 +21418,43 @@ var getAuthContext = async (options = {}) => {
|
|
|
21098
21418
|
tenantName
|
|
21099
21419
|
};
|
|
21100
21420
|
};
|
|
21421
|
+
var getAuthEnv = async (options = {}) => {
|
|
21422
|
+
const authEnv = {};
|
|
21423
|
+
let status;
|
|
21424
|
+
try {
|
|
21425
|
+
status = await getLoginStatusAsync(options);
|
|
21426
|
+
} catch {
|
|
21427
|
+
return { authEnv };
|
|
21428
|
+
}
|
|
21429
|
+
if (status.loginStatus === "Logged in" && status.accessToken) {
|
|
21430
|
+
authEnv.UIPATH_ACCESS_TOKEN = status.accessToken;
|
|
21431
|
+
if (status.baseUrl) {
|
|
21432
|
+
const org = status.organizationName || status.organizationId;
|
|
21433
|
+
const tenant = status.tenantName || status.tenantId;
|
|
21434
|
+
if (org && tenant) {
|
|
21435
|
+
authEnv.UIPATH_URL = `${status.baseUrl.replace(/\/+$/, "")}/${org}/${tenant}`;
|
|
21436
|
+
}
|
|
21437
|
+
}
|
|
21438
|
+
if (status.organizationId)
|
|
21439
|
+
authEnv.UIPATH_ORGANIZATION_ID = status.organizationId;
|
|
21440
|
+
if (status.organizationName)
|
|
21441
|
+
authEnv.UIPATH_ORGANIZATION_NAME = status.organizationName;
|
|
21442
|
+
if (status.tenantId)
|
|
21443
|
+
authEnv.UIPATH_TENANT_ID = status.tenantId;
|
|
21444
|
+
if (status.tenantName)
|
|
21445
|
+
authEnv.UIPATH_TENANT_NAME = status.tenantName;
|
|
21446
|
+
}
|
|
21447
|
+
return { authEnv, loginStatus: status };
|
|
21448
|
+
};
|
|
21101
21449
|
// src/clientCredentials.ts
|
|
21450
|
+
class ClientCredentialsAuthenticationError extends Error {
|
|
21451
|
+
status;
|
|
21452
|
+
constructor(message, status) {
|
|
21453
|
+
super(message);
|
|
21454
|
+
this.name = "ClientCredentialsAuthenticationError";
|
|
21455
|
+
this.status = status;
|
|
21456
|
+
}
|
|
21457
|
+
}
|
|
21102
21458
|
var clientCredentialsLogin = async ({
|
|
21103
21459
|
clientId,
|
|
21104
21460
|
clientSecret,
|
|
@@ -21146,9 +21502,9 @@ Troubleshooting:` + `
|
|
|
21146
21502
|
• The requested scopes may not be available for your account` + `
|
|
21147
21503
|
• Try using default scopes or contact your UiPath administrator`;
|
|
21148
21504
|
}
|
|
21149
|
-
throw new
|
|
21505
|
+
throw new ClientCredentialsAuthenticationError(`Client Credentials authentication failed (${tokenResponse.status})
|
|
21150
21506
|
` + `Error: ${errorType}
|
|
21151
|
-
` + `Details: ${errorDesc}${troubleshooting}
|
|
21507
|
+
` + `Details: ${errorDesc}${troubleshooting}`, tokenResponse.status);
|
|
21152
21508
|
}
|
|
21153
21509
|
return {
|
|
21154
21510
|
UIPATH_ACCESS_TOKEN: tokenData.access_token,
|
|
@@ -21178,6 +21534,49 @@ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId)
|
|
|
21178
21534
|
};
|
|
21179
21535
|
|
|
21180
21536
|
// src/selectTenant.ts
|
|
21537
|
+
var TENANT_SELECTION_REQUIRED_CODE = "TENANT_SELECTION_REQUIRED";
|
|
21538
|
+
var INVALID_TENANT_CODE = "INVALID_TENANT";
|
|
21539
|
+
|
|
21540
|
+
class TenantSelectionError extends Error {
|
|
21541
|
+
availableTenants;
|
|
21542
|
+
organizationName;
|
|
21543
|
+
constructor(message, organizationName, availableTenants) {
|
|
21544
|
+
super(message);
|
|
21545
|
+
this.organizationName = organizationName;
|
|
21546
|
+
this.availableTenants = availableTenants;
|
|
21547
|
+
}
|
|
21548
|
+
}
|
|
21549
|
+
|
|
21550
|
+
class TenantSelectionRequiredError extends TenantSelectionError {
|
|
21551
|
+
code = TENANT_SELECTION_REQUIRED_CODE;
|
|
21552
|
+
constructor(organizationName, availableTenants) {
|
|
21553
|
+
super(`Multiple tenants available in organization "${organizationName}"; none selected.`, organizationName, availableTenants);
|
|
21554
|
+
this.name = "TenantSelectionRequiredError";
|
|
21555
|
+
}
|
|
21556
|
+
}
|
|
21557
|
+
|
|
21558
|
+
class InvalidTenantError extends TenantSelectionError {
|
|
21559
|
+
code = INVALID_TENANT_CODE;
|
|
21560
|
+
requestedTenant;
|
|
21561
|
+
constructor(requestedTenant, organizationName, availableTenants) {
|
|
21562
|
+
super(`Invalid tenant requested: "${requestedTenant}"
|
|
21563
|
+
` + `Organization: ${organizationName}
|
|
21564
|
+
` + `Available tenants: ${availableTenants.join(", ")}`, organizationName, availableTenants);
|
|
21565
|
+
this.name = "InvalidTenantError";
|
|
21566
|
+
this.requestedTenant = requestedTenant;
|
|
21567
|
+
}
|
|
21568
|
+
}
|
|
21569
|
+
var TENANT_SELECTION_CODES = new Set([
|
|
21570
|
+
TENANT_SELECTION_REQUIRED_CODE,
|
|
21571
|
+
INVALID_TENANT_CODE
|
|
21572
|
+
]);
|
|
21573
|
+
function isTenantSelectionError(error) {
|
|
21574
|
+
if (!(error instanceof Object) || !("code" in error)) {
|
|
21575
|
+
return false;
|
|
21576
|
+
}
|
|
21577
|
+
const code = error.code;
|
|
21578
|
+
return typeof code === "string" && TENANT_SELECTION_CODES.has(code) && Array.isArray(error.availableTenants);
|
|
21579
|
+
}
|
|
21181
21580
|
var selectTenantWithDeps = async (baseUrl, accessToken, organizationId, targetTenantName, interactive, deps = {}) => {
|
|
21182
21581
|
const {
|
|
21183
21582
|
fetchTenantsAndOrgs = fetchTenantsAndOrganizations,
|
|
@@ -21190,13 +21589,10 @@ var selectTenantWithDeps = async (baseUrl, accessToken, organizationId, targetTe
|
|
|
21190
21589
|
}
|
|
21191
21590
|
const tenantNames = tenants.map((tenant) => tenant.name);
|
|
21192
21591
|
let selectedIndex;
|
|
21193
|
-
if (targetTenantName) {
|
|
21592
|
+
if (targetTenantName !== undefined) {
|
|
21194
21593
|
selectedIndex = tenants.findIndex((tenant) => tenant.name === targetTenantName);
|
|
21195
21594
|
if (selectedIndex === -1) {
|
|
21196
|
-
|
|
21197
|
-
throw new Error(`Invalid tenant requested: "${targetTenantName}"
|
|
21198
|
-
` + `Organization: ${organization.name}
|
|
21199
|
-
` + `Available tenants: ${availableTenants}`);
|
|
21595
|
+
throw new InvalidTenantError(targetTenantName, organization.name, tenantNames);
|
|
21200
21596
|
}
|
|
21201
21597
|
} else if (tenants.length === 1) {
|
|
21202
21598
|
selectedIndex = 0;
|
|
@@ -21206,7 +21602,7 @@ var selectTenantWithDeps = async (baseUrl, accessToken, organizationId, targetTe
|
|
|
21206
21602
|
}
|
|
21207
21603
|
selectedIndex = await selectFromList(tenantNames, "Select a tenant:");
|
|
21208
21604
|
} else {
|
|
21209
|
-
|
|
21605
|
+
throw new TenantSelectionRequiredError(organization.name, tenantNames);
|
|
21210
21606
|
}
|
|
21211
21607
|
const selectedTenant = tenants[selectedIndex];
|
|
21212
21608
|
return [selectedTenant.name, selectedTenant.id, organization.name];
|
|
@@ -21234,7 +21630,9 @@ var interactiveLoginWithDeps = async (options, deps) => {
|
|
|
21234
21630
|
tenant,
|
|
21235
21631
|
organization,
|
|
21236
21632
|
interactive,
|
|
21237
|
-
onEvent
|
|
21633
|
+
onEvent,
|
|
21634
|
+
timeoutMs,
|
|
21635
|
+
noBrowser
|
|
21238
21636
|
} = options;
|
|
21239
21637
|
const emit = (event) => {
|
|
21240
21638
|
if (!onEvent)
|
|
@@ -21243,12 +21641,22 @@ var interactiveLoginWithDeps = async (options, deps) => {
|
|
|
21243
21641
|
onEvent(event);
|
|
21244
21642
|
} catch {}
|
|
21245
21643
|
};
|
|
21644
|
+
const deliverAuthUrl = (url) => {
|
|
21645
|
+
try {
|
|
21646
|
+
onEvent?.({ type: "auth-url", url });
|
|
21647
|
+
} catch (error) {
|
|
21648
|
+
throw new Error("Failed to deliver the authorize URL to the onEvent subscriber; " + "cannot continue headless login.", { cause: error });
|
|
21649
|
+
}
|
|
21650
|
+
};
|
|
21246
21651
|
const config = await resolveConfig({
|
|
21247
21652
|
customAuthority: authority,
|
|
21248
21653
|
customClientId: clientId,
|
|
21249
21654
|
customClientSecret: clientSecret
|
|
21250
21655
|
});
|
|
21251
21656
|
const { clientSecret: resolvedSecret } = config;
|
|
21657
|
+
if (noBrowser && !resolvedSecret && !onEvent) {
|
|
21658
|
+
throw new Error("noBrowser login requires an onEvent subscriber to receive the " + "auth-url event — the authorize URL is delivered through it.");
|
|
21659
|
+
}
|
|
21252
21660
|
const authPromise = resolvedSecret ? (async () => {
|
|
21253
21661
|
return await clientCredentials({
|
|
21254
21662
|
clientId: config.clientId,
|
|
@@ -21262,7 +21670,10 @@ var interactiveLoginWithDeps = async (options, deps) => {
|
|
|
21262
21670
|
clientId,
|
|
21263
21671
|
clientSecret,
|
|
21264
21672
|
scope,
|
|
21265
|
-
organization
|
|
21673
|
+
organization,
|
|
21674
|
+
timeoutMs,
|
|
21675
|
+
noBrowser,
|
|
21676
|
+
onAuthUrl: noBrowser ? (url) => deliverAuthUrl(url) : undefined
|
|
21266
21677
|
});
|
|
21267
21678
|
return {
|
|
21268
21679
|
UIPATH_ACCESS_TOKEN: authTokens.accessToken,
|
|
@@ -21293,10 +21704,12 @@ var interactiveLoginWithDeps = async (options, deps) => {
|
|
|
21293
21704
|
credentials.UIPATH_TENANT_NAME = tenantName;
|
|
21294
21705
|
credentials.UIPATH_TENANT_ID = tenantId;
|
|
21295
21706
|
} catch (error) {
|
|
21296
|
-
|
|
21297
|
-
|
|
21298
|
-
|
|
21299
|
-
|
|
21707
|
+
if (!isTenantSelectionError(error)) {
|
|
21708
|
+
emit({
|
|
21709
|
+
type: "tenant-fetch-failed",
|
|
21710
|
+
message: error instanceof Error ? error.message : String(error)
|
|
21711
|
+
});
|
|
21712
|
+
}
|
|
21300
21713
|
throw error;
|
|
21301
21714
|
}
|
|
21302
21715
|
const fs7 = getFs();
|
|
@@ -21361,10 +21774,12 @@ init_src();
|
|
|
21361
21774
|
async function logoutWithDeps(options, deps = {}) {
|
|
21362
21775
|
const {
|
|
21363
21776
|
resolveEnvFilePath = resolveEnvFilePathAsync,
|
|
21364
|
-
getFileSystem: getFs = getFileSystem
|
|
21777
|
+
getFileSystem: getFs = getFileSystem,
|
|
21778
|
+
clearBreaker = clearRefreshBreaker,
|
|
21779
|
+
getActiveProfileFilePath = getActiveAuthProfileFilePath
|
|
21365
21780
|
} = deps;
|
|
21366
21781
|
const fs7 = getFs();
|
|
21367
|
-
const { absolutePath } = await resolveEnvFilePath(options.file);
|
|
21782
|
+
const { absolutePath } = await resolveEnvFilePath(options.file ?? getActiveProfileFilePath());
|
|
21368
21783
|
if (absolutePath && await fs7.exists(absolutePath)) {
|
|
21369
21784
|
let release;
|
|
21370
21785
|
try {
|
|
@@ -21376,6 +21791,7 @@ async function logoutWithDeps(options, deps = {}) {
|
|
|
21376
21791
|
}
|
|
21377
21792
|
try {
|
|
21378
21793
|
await fs7.rm(absolutePath);
|
|
21794
|
+
await clearBreaker(absolutePath);
|
|
21379
21795
|
} finally {
|
|
21380
21796
|
if (release) {
|
|
21381
21797
|
await release().catch(() => {});
|
|
@@ -21405,7 +21821,10 @@ var authenticate = async ({
|
|
|
21405
21821
|
clientSecret,
|
|
21406
21822
|
redirectUri,
|
|
21407
21823
|
scope,
|
|
21408
|
-
organization
|
|
21824
|
+
organization,
|
|
21825
|
+
timeoutMs,
|
|
21826
|
+
noBrowser,
|
|
21827
|
+
onAuthUrl
|
|
21409
21828
|
}) => {
|
|
21410
21829
|
const config = await resolveConfigAsync({
|
|
21411
21830
|
customAuthority: baseUrl,
|
|
@@ -21455,7 +21874,7 @@ var authenticate = async ({
|
|
|
21455
21874
|
const { NodeAuthStrategy: NodeAuthStrategy2 } = await Promise.resolve().then(() => (init_node_strategy(), exports_node_strategy));
|
|
21456
21875
|
strategy = new NodeAuthStrategy2;
|
|
21457
21876
|
}
|
|
21458
|
-
const code = await strategy.execute(authUrl, effectiveRedirectUriUrl, state);
|
|
21877
|
+
const code = await strategy.execute(authUrl, effectiveRedirectUriUrl, state, { timeoutMs, noBrowser, onAuthUrl });
|
|
21459
21878
|
return await exchangeCodeForTokens({
|
|
21460
21879
|
code,
|
|
21461
21880
|
codeVerifier: code_verifier,
|
|
@@ -21467,17 +21886,25 @@ var authenticate = async ({
|
|
|
21467
21886
|
};
|
|
21468
21887
|
export {
|
|
21469
21888
|
setAuthFileConfig,
|
|
21889
|
+
setActiveAuthProfile,
|
|
21470
21890
|
selectTenantWithDeps,
|
|
21891
|
+
saveRefreshBreaker,
|
|
21471
21892
|
saveEnvFileAsync,
|
|
21893
|
+
runWithAuthProfile,
|
|
21472
21894
|
resolveEnvFilePathAsync,
|
|
21473
21895
|
resolveEnvFileLocationAsync,
|
|
21896
|
+
resolveAuthProfileFilePath,
|
|
21897
|
+
refreshTokenFingerprint,
|
|
21474
21898
|
refreshAccessToken,
|
|
21475
21899
|
readAuthFromEnv,
|
|
21476
21900
|
parseJWT,
|
|
21901
|
+
normalizeAuthProfileName,
|
|
21477
21902
|
logoutWithDeps,
|
|
21478
21903
|
logout,
|
|
21904
|
+
loadRefreshBreaker,
|
|
21479
21905
|
loadEnvFileAsync,
|
|
21480
21906
|
isTokenRefreshOAuthFailure,
|
|
21907
|
+
isTenantSelectionError,
|
|
21481
21908
|
isRobotAuthEnforced,
|
|
21482
21909
|
isNode,
|
|
21483
21910
|
isEnvAuthEnabled,
|
|
@@ -21486,18 +21913,33 @@ export {
|
|
|
21486
21913
|
interactiveLogin,
|
|
21487
21914
|
getLoginStatusWithDeps,
|
|
21488
21915
|
getLoginStatusAsync,
|
|
21916
|
+
getAuthEnv,
|
|
21489
21917
|
getAuthContext,
|
|
21918
|
+
getActiveAuthProfileFilePath,
|
|
21919
|
+
getActiveAuthProfile,
|
|
21490
21920
|
fetchTenantsAndOrganizations,
|
|
21491
21921
|
clientCredentialsLogin,
|
|
21922
|
+
clearRefreshBreaker,
|
|
21923
|
+
clearActiveAuthProfile,
|
|
21492
21924
|
authenticate,
|
|
21493
21925
|
TokenRefreshOAuthError,
|
|
21926
|
+
TenantSelectionRequiredError,
|
|
21927
|
+
TenantSelectionError,
|
|
21928
|
+
TENANT_SELECTION_REQUIRED_CODE,
|
|
21494
21929
|
LoginStatusSource,
|
|
21930
|
+
InvalidTenantError,
|
|
21495
21931
|
InvalidBaseUrlError,
|
|
21932
|
+
INVALID_TENANT_CODE,
|
|
21496
21933
|
EnvAuthConfigError,
|
|
21497
21934
|
ENV_AUTH_VARS,
|
|
21498
21935
|
ENV_AUTH_ENABLE_VAR,
|
|
21499
21936
|
ENFORCE_ROBOT_AUTH_VAR,
|
|
21500
21937
|
DEFAULT_ENV_FILENAME,
|
|
21938
|
+
DEFAULT_AUTH_PROFILE,
|
|
21501
21939
|
DEFAULT_AUTH_FILENAME,
|
|
21940
|
+
ClientCredentialsAuthenticationError,
|
|
21941
|
+
AuthProfileValidationError,
|
|
21502
21942
|
AUTH_TIMEOUT_ERROR_CODE
|
|
21503
21943
|
};
|
|
21944
|
+
|
|
21945
|
+
//# debugId=B1F2D5989CE27CF464756E2164756E21
|