@uipath/auth 1.200.0-preview.120 → 1.201.0-preview.121
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/constants.d.ts +1 -0
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +107 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +228 -121
- package/dist/loginStatus.d.ts +17 -4
- package/dist/server.d.ts +2 -2
- package/dist/sessionIdentity.d.ts +35 -0
- package/dist/tenantSelection.d.ts +13 -1
- package/package.json +2 -2
package/dist/constants.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare const AUTH_FILENAME = ".auth";
|
|
|
6
6
|
export declare const DEFAULT_BASE_URL = "https://cloud.uipath.com";
|
|
7
7
|
/** Auth callback server timeout (5 minutes). */
|
|
8
8
|
export declare const DEFAULT_AUTH_TIMEOUT_MS: number;
|
|
9
|
+
export declare const AUTH_TIMEOUT_ERROR_CODE = "EAUTHTIMEOUT";
|
|
9
10
|
export declare const AUTH_CANCELLED_ERROR_CODE = "EAUTHCANCELLED";
|
|
10
11
|
/** Localhost OIDC redirect URI. */
|
|
11
12
|
export declare const DEFAULT_REDIRECT_URI = "http://localhost:8104/oidc/login";
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./clientCredentials";
|
|
|
4
4
|
export { type AuthFileConfig, InvalidBaseUrlError, setAuthFileConfig, } from "./config";
|
|
5
5
|
export * from "./loginStatus";
|
|
6
6
|
export * from "./logout";
|
|
7
|
+
export { type IdentityType, parseAuthFlow, resolveSessionIdentity, type SessionIdentity, } from "./sessionIdentity";
|
|
7
8
|
export { fetchTenantsAndOrganizations, type Tenant, type TenantsAndOrganizations, } from "./tenantSelection";
|
|
8
9
|
export * from "./tokenRefresh";
|
|
9
10
|
export { AUTH_FLOW_ENV_VAR, type AuthFlow, type BaseCredentials, } from "./types";
|
package/dist/index.browser.js
CHANGED
|
@@ -18452,6 +18452,67 @@ var getTokenExpiration = (accessToken) => {
|
|
|
18452
18452
|
}
|
|
18453
18453
|
};
|
|
18454
18454
|
|
|
18455
|
+
// src/sessionIdentity.ts
|
|
18456
|
+
var parseAuthFlow = (value) => value === "authorization_code" || value === "client_credentials" || value === "federated_credentials" ? value : undefined;
|
|
18457
|
+
var decodeClaims = (accessToken) => {
|
|
18458
|
+
const [error, claims] = catchError(() => parseJWT(accessToken));
|
|
18459
|
+
return error ? undefined : claims;
|
|
18460
|
+
};
|
|
18461
|
+
var asString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
18462
|
+
var resolveIdentityType = (claims, authFlow, email) => {
|
|
18463
|
+
const subType = asString(claims?.sub_type);
|
|
18464
|
+
if (subType) {
|
|
18465
|
+
return subType.startsWith("service") ? "Application" : "User";
|
|
18466
|
+
}
|
|
18467
|
+
if (authFlow) {
|
|
18468
|
+
return authFlow === "authorization_code" ? "User" : "Application";
|
|
18469
|
+
}
|
|
18470
|
+
if (email)
|
|
18471
|
+
return "User";
|
|
18472
|
+
if (asString(claims?.client_id) && !asString(claims?.sub)) {
|
|
18473
|
+
return "Application";
|
|
18474
|
+
}
|
|
18475
|
+
return;
|
|
18476
|
+
};
|
|
18477
|
+
var looksLikeEmail = (value) => value?.includes("@") ?? false;
|
|
18478
|
+
var pickEmail = (claims) => {
|
|
18479
|
+
for (const candidate of [claims?.email, claims?.preferred_username]) {
|
|
18480
|
+
const value = asString(candidate);
|
|
18481
|
+
if (looksLikeEmail(value))
|
|
18482
|
+
return value;
|
|
18483
|
+
}
|
|
18484
|
+
return;
|
|
18485
|
+
};
|
|
18486
|
+
var pickName = (claims) => {
|
|
18487
|
+
const username = asString(claims?.preferred_username);
|
|
18488
|
+
return asString(claims?.name) ?? (looksLikeEmail(username) ? undefined : username);
|
|
18489
|
+
};
|
|
18490
|
+
var resolveSessionIdentity = (accessToken, authFlow) => {
|
|
18491
|
+
const claims = accessToken ? decodeClaims(accessToken) : undefined;
|
|
18492
|
+
const email = pickEmail(claims);
|
|
18493
|
+
const type = resolveIdentityType(claims, authFlow, email);
|
|
18494
|
+
if (!type)
|
|
18495
|
+
return;
|
|
18496
|
+
const identity = { type };
|
|
18497
|
+
if (authFlow)
|
|
18498
|
+
identity.authFlow = authFlow;
|
|
18499
|
+
if (type === "User") {
|
|
18500
|
+
const userId = asString(claims?.sub);
|
|
18501
|
+
if (userId)
|
|
18502
|
+
identity.userId = userId;
|
|
18503
|
+
if (email)
|
|
18504
|
+
identity.userEmail = email;
|
|
18505
|
+
const name = pickName(claims);
|
|
18506
|
+
if (name)
|
|
18507
|
+
identity.userName = name;
|
|
18508
|
+
return identity;
|
|
18509
|
+
}
|
|
18510
|
+
const clientId = asString(claims?.client_id);
|
|
18511
|
+
if (clientId)
|
|
18512
|
+
identity.clientId = clientId;
|
|
18513
|
+
return identity;
|
|
18514
|
+
};
|
|
18515
|
+
|
|
18455
18516
|
// src/envAuth.ts
|
|
18456
18517
|
var ENV_AUTH_ENABLE_VAR = "UIPATH_CLI_ENABLE_ENV_AUTH";
|
|
18457
18518
|
var ENFORCE_ROBOT_AUTH_VAR = "UIPATH_CLI_ENFORCE_ROBOT_AUTH";
|
|
@@ -18501,6 +18562,7 @@ var readAuthFromEnv = () => {
|
|
|
18501
18562
|
}
|
|
18502
18563
|
const expiration = getTokenExpiration(accessToken);
|
|
18503
18564
|
const loginStatus = expiration && expiration <= new Date ? "Expired" : "Logged in";
|
|
18565
|
+
const identity = resolveSessionIdentity(accessToken);
|
|
18504
18566
|
return {
|
|
18505
18567
|
loginStatus,
|
|
18506
18568
|
accessToken,
|
|
@@ -18510,7 +18572,8 @@ var readAuthFromEnv = () => {
|
|
|
18510
18572
|
tenantName,
|
|
18511
18573
|
tenantId,
|
|
18512
18574
|
expiration,
|
|
18513
|
-
source: "env" /*
|
|
18575
|
+
source: "env-vars" /* EnvironmentVariables */,
|
|
18576
|
+
...identity ? { identity } : {}
|
|
18514
18577
|
};
|
|
18515
18578
|
};
|
|
18516
18579
|
|
|
@@ -18763,6 +18826,9 @@ var refreshAccessToken = async ({
|
|
|
18763
18826
|
return { accessToken: newAccessToken, refreshToken: newRefreshToken };
|
|
18764
18827
|
};
|
|
18765
18828
|
|
|
18829
|
+
// src/types.ts
|
|
18830
|
+
var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
|
|
18831
|
+
|
|
18766
18832
|
// src/utils/envFile.ts
|
|
18767
18833
|
import { getFileSystem as getFileSystem4 } from "@uipath/filesystem";
|
|
18768
18834
|
var DEFAULT_AUTH_FILENAME = AUTH_FILENAME;
|
|
@@ -18925,12 +18991,12 @@ var saveEnvFileAsync = async ({
|
|
|
18925
18991
|
};
|
|
18926
18992
|
|
|
18927
18993
|
// src/loginStatus.ts
|
|
18928
|
-
var
|
|
18929
|
-
((
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
})(
|
|
18994
|
+
var CredentialSource;
|
|
18995
|
+
((CredentialSource2) => {
|
|
18996
|
+
CredentialSource2["SavedLogin"] = "saved-login";
|
|
18997
|
+
CredentialSource2["Robot"] = "robot";
|
|
18998
|
+
CredentialSource2["EnvironmentVariables"] = "env-vars";
|
|
18999
|
+
})(CredentialSource ||= {});
|
|
18934
19000
|
var getLoginStatusAsync = async (options = {}) => {
|
|
18935
19001
|
return getLoginStatusWithDeps(options);
|
|
18936
19002
|
};
|
|
@@ -19136,7 +19202,8 @@ async function buildFileStatus(tokens, credentials, globalHint) {
|
|
|
19136
19202
|
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
19137
19203
|
tenantId: credentials.UIPATH_TENANT_ID,
|
|
19138
19204
|
expiration: tokens.expiration,
|
|
19139
|
-
source: "
|
|
19205
|
+
source: "saved-login" /* SavedLogin */,
|
|
19206
|
+
...identityFields(tokens.accessToken, credentials),
|
|
19140
19207
|
...tokens.persistenceWarning ? { hint: tokens.persistenceWarning, persistenceFailed: true } : {},
|
|
19141
19208
|
...tokens.lockReleaseFailed ? { lockReleaseFailed: true } : {},
|
|
19142
19209
|
...tokens.tokenRefresh ? { tokenRefresh: tokens.tokenRefresh } : {}
|
|
@@ -19149,7 +19216,12 @@ async function buildFileStatus(tokens, credentials, globalHint) {
|
|
|
19149
19216
|
}
|
|
19150
19217
|
return result;
|
|
19151
19218
|
}
|
|
19219
|
+
function identityFields(accessToken, credentials) {
|
|
19220
|
+
const identity = resolveSessionIdentity(accessToken, parseAuthFlow(credentials[AUTH_FLOW_ENV_VAR]));
|
|
19221
|
+
return identity ? { identity } : {};
|
|
19222
|
+
}
|
|
19152
19223
|
function buildRobotStatus(robotCreds) {
|
|
19224
|
+
const identity = resolveSessionIdentity(robotCreds.accessToken);
|
|
19153
19225
|
return {
|
|
19154
19226
|
loginStatus: "Logged in",
|
|
19155
19227
|
accessToken: robotCreds.accessToken,
|
|
@@ -19160,7 +19232,8 @@ function buildRobotStatus(robotCreds) {
|
|
|
19160
19232
|
tenantId: robotCreds.tenantId,
|
|
19161
19233
|
issuer: robotCreds.issuer,
|
|
19162
19234
|
expiration: getTokenExpiration(robotCreds.accessToken),
|
|
19163
|
-
source: "robot" /* Robot
|
|
19235
|
+
source: "robot" /* Robot */,
|
|
19236
|
+
...identity ? { identity } : {}
|
|
19164
19237
|
};
|
|
19165
19238
|
}
|
|
19166
19239
|
var isFileNotFoundError = (error) => {
|
|
@@ -19211,7 +19284,8 @@ async function circuitBreakerShortCircuit(ctx) {
|
|
|
19211
19284
|
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
19212
19285
|
tenantId: credentials.UIPATH_TENANT_ID,
|
|
19213
19286
|
expiration,
|
|
19214
|
-
source: "
|
|
19287
|
+
source: "saved-login" /* SavedLogin */,
|
|
19288
|
+
...identityFields(accessToken, credentials)
|
|
19215
19289
|
} : {},
|
|
19216
19290
|
hint: globalHint ?? (tokenIsDead ? deadHint : backoffHint),
|
|
19217
19291
|
refreshCircuitOpen: true,
|
|
@@ -19233,7 +19307,8 @@ async function lockAcquireFailureStatus(ctx, error) {
|
|
|
19233
19307
|
tenantName: ctx.credentials.UIPATH_TENANT_NAME,
|
|
19234
19308
|
tenantId: ctx.credentials.UIPATH_TENANT_ID,
|
|
19235
19309
|
expiration: ctx.expiration,
|
|
19236
|
-
source: "
|
|
19310
|
+
source: "saved-login" /* SavedLogin */,
|
|
19311
|
+
...identityFields(ctx.accessToken, ctx.credentials),
|
|
19237
19312
|
hint: globalHint,
|
|
19238
19313
|
tokenRefresh: {
|
|
19239
19314
|
attempted: false,
|
|
@@ -19604,6 +19679,16 @@ async function logout(options) {
|
|
|
19604
19679
|
return logoutWithDeps(options);
|
|
19605
19680
|
}
|
|
19606
19681
|
// src/tenantSelection.ts
|
|
19682
|
+
var LOGIN_STATUS_HINT = "Run 'uip login status' to see the organization the CLI is signed in to.";
|
|
19683
|
+
var organizationHint = (organizationId) => `The request used '${organizationId}' as the organization. ${LOGIN_STATUS_HINT}`;
|
|
19684
|
+
var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
|
|
19685
|
+
var describeNonJsonResponse = (organizationId, response, parseError) => {
|
|
19686
|
+
if (response.redirected) {
|
|
19687
|
+
return `Could not find organization '${organizationId}': the request was ` + `redirected to a sign-in page instead of the organization's tenant ` + `list. ${LOGIN_STATUS_HINT}`;
|
|
19688
|
+
}
|
|
19689
|
+
const contentType = response.headers.get("content-type") ?? "unknown";
|
|
19690
|
+
return `The organization service returned a '${contentType}' response instead ` + `of JSON: ${parseError.message}. ${organizationHint(organizationId)}`;
|
|
19691
|
+
};
|
|
19607
19692
|
var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId) => {
|
|
19608
19693
|
const url = `${baseUrl}/${organizationId}/portal_/api/filtering/leftnav/tenantsAndOrganizationInfo`;
|
|
19609
19694
|
const response = await fetch(url, {
|
|
@@ -19613,26 +19698,30 @@ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId)
|
|
|
19613
19698
|
});
|
|
19614
19699
|
if (!response.ok) {
|
|
19615
19700
|
if (response.status === 401) {
|
|
19616
|
-
throw new Error(
|
|
19701
|
+
throw new Error(`Unauthorized: the access token was rejected, it was not ` + `issued for organization '${organizationId}', or ` + `'${organizationId}' was not accepted as an organization ` + `URL segment in this environment. ` + LOGIN_STATUS_HINT);
|
|
19617
19702
|
}
|
|
19618
19703
|
const errorText = await response.text();
|
|
19619
|
-
|
|
19704
|
+
const message = `Failed to get tenants and organizations: ${response.status} ${errorText}`;
|
|
19705
|
+
throw new Error(IDENTIFIER_STATUSES.has(response.status) ? `${message}. ${organizationHint(organizationId)}` : message);
|
|
19706
|
+
}
|
|
19707
|
+
const [parseError, data] = await catchError(response.json());
|
|
19708
|
+
if (parseError) {
|
|
19709
|
+
throw new Error(describeNonJsonResponse(organizationId, response, parseError));
|
|
19620
19710
|
}
|
|
19621
|
-
const data = await response.json();
|
|
19622
19711
|
return data;
|
|
19623
19712
|
};
|
|
19624
|
-
// src/types.ts
|
|
19625
|
-
var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
|
|
19626
19713
|
export {
|
|
19627
19714
|
setAuthFileConfig,
|
|
19628
19715
|
setActiveAuthProfile,
|
|
19629
19716
|
saveEnvFileAsync,
|
|
19630
19717
|
runWithAuthProfile,
|
|
19718
|
+
resolveSessionIdentity,
|
|
19631
19719
|
resolveEnvFilePathAsync,
|
|
19632
19720
|
resolveEnvFileLocationAsync,
|
|
19633
19721
|
resolveAuthProfileFilePath,
|
|
19634
19722
|
refreshAccessToken,
|
|
19635
19723
|
parseJWT,
|
|
19724
|
+
parseAuthFlow,
|
|
19636
19725
|
normalizeAuthProfileName,
|
|
19637
19726
|
logoutWithDeps,
|
|
19638
19727
|
logout,
|
|
@@ -19650,14 +19739,14 @@ export {
|
|
|
19650
19739
|
clientCredentialsLogin,
|
|
19651
19740
|
clearActiveAuthProfile,
|
|
19652
19741
|
TokenRefreshOAuthError,
|
|
19653
|
-
LoginStatusSource,
|
|
19654
19742
|
InvalidBaseUrlError,
|
|
19655
19743
|
DEFAULT_ENV_FILENAME,
|
|
19656
19744
|
DEFAULT_AUTH_PROFILE,
|
|
19657
19745
|
DEFAULT_AUTH_FILENAME,
|
|
19746
|
+
CredentialSource,
|
|
19658
19747
|
ClientCredentialsAuthenticationError,
|
|
19659
19748
|
AuthProfileValidationError,
|
|
19660
19749
|
AUTH_FLOW_ENV_VAR
|
|
19661
19750
|
};
|
|
19662
19751
|
|
|
19663
|
-
//# debugId=
|
|
19752
|
+
//# debugId=7467DDE1FA7C205564756E2164756E21
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./authContext";
|
|
|
2
2
|
export * from "./authProfile";
|
|
3
3
|
export * from "./clientCredentials";
|
|
4
4
|
export { type AuthFileConfig, InvalidBaseUrlError, setAuthFileConfig, } from "./config";
|
|
5
|
-
export { AUTH_CANCELLED_ERROR_CODE, DEFAULT_AUTH_TIMEOUT_MS, } from "./constants";
|
|
5
|
+
export { AUTH_CANCELLED_ERROR_CODE, AUTH_TIMEOUT_ERROR_CODE, DEFAULT_AUTH_TIMEOUT_MS, } from "./constants";
|
|
6
6
|
export { ENFORCE_ROBOT_AUTH_VAR, ENV_AUTH_ENABLE_VAR, ENV_AUTH_VARS, EnvAuthConfigError, isEnvAuthEnabled, isRobotAuthEnforced, readAuthFromEnv, } from "./envAuth";
|
|
7
7
|
export { FederatedCredentialsAuthenticationError, federatedCredentialsLogin, JWT_BEARER_ASSERTION_TYPE, } from "./federatedCredentials";
|
|
8
8
|
export * from "./interactive";
|
|
@@ -11,7 +11,7 @@ export * from "./logout";
|
|
|
11
11
|
export { clearRefreshBreaker, loadRefreshBreaker, type RefreshBreakerState, refreshTokenFingerprint, saveRefreshBreaker, } from "./refreshCircuitBreaker";
|
|
12
12
|
export { type RobotClientModuleLoader, registerRobotClientLoader, } from "./robotClientFallback";
|
|
13
13
|
export { INVALID_TENANT_CODE, InvalidTenantError, isTenantSelectionError, type SelectFromList, selectTenantWithDeps, TENANT_SELECTION_REQUIRED_CODE, TenantSelectionError, TenantSelectionRequiredError, } from "./selectTenant";
|
|
14
|
-
export {
|
|
14
|
+
export { type IdentityType, parseAuthFlow, resolveSessionIdentity, type SessionIdentity, } from "./sessionIdentity";
|
|
15
15
|
export { fetchTenantsAndOrganizations, type Tenant, type TenantsAndOrganizations, } from "./tenantSelection";
|
|
16
16
|
export * from "./tokenRefresh";
|
|
17
17
|
export { AUTH_FLOW_ENV_VAR, type AuthFlow, type BaseCredentials, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ function settlePromiseLike(thenable) {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
// src/constants.ts
|
|
48
|
-
var UIPATH_HOME_DIR = ".uipath", AUTH_FILENAME = ".auth", DEFAULT_BASE_URL = "https://cloud.uipath.com", DEFAULT_AUTH_TIMEOUT_MS, AUTH_CANCELLED_ERROR_CODE = "EAUTHCANCELLED", DEFAULT_REDIRECT_URI = "http://localhost:8104/oidc/login";
|
|
48
|
+
var UIPATH_HOME_DIR = ".uipath", AUTH_FILENAME = ".auth", DEFAULT_BASE_URL = "https://cloud.uipath.com", DEFAULT_AUTH_TIMEOUT_MS, AUTH_TIMEOUT_ERROR_CODE = "EAUTHTIMEOUT", AUTH_CANCELLED_ERROR_CODE = "EAUTHCANCELLED", DEFAULT_REDIRECT_URI = "http://localhost:8104/oidc/login";
|
|
49
49
|
var init_constants = __esm(() => {
|
|
50
50
|
DEFAULT_AUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
51
51
|
});
|
|
@@ -409,6 +409,12 @@ var init_is_in_ssh = __esm(() => {
|
|
|
409
409
|
});
|
|
410
410
|
|
|
411
411
|
// ../../node_modules/open/index.js
|
|
412
|
+
var exports_open = {};
|
|
413
|
+
__export(exports_open, {
|
|
414
|
+
openApp: () => openApp,
|
|
415
|
+
default: () => open_default,
|
|
416
|
+
apps: () => apps
|
|
417
|
+
});
|
|
412
418
|
import process8 from "node:process";
|
|
413
419
|
import path from "node:path";
|
|
414
420
|
import { fileURLToPath } from "node:url";
|
|
@@ -642,6 +648,21 @@ var fallbackAttemptSymbol, __dirname2, localXdgOpenPath, platform, arch, tryEach
|
|
|
642
648
|
...options,
|
|
643
649
|
target
|
|
644
650
|
});
|
|
651
|
+
}, openApp = (name, options) => {
|
|
652
|
+
if (typeof name !== "string" && !Array.isArray(name)) {
|
|
653
|
+
throw new TypeError("Expected a valid `name`");
|
|
654
|
+
}
|
|
655
|
+
const { arguments: appArguments = [] } = options ?? {};
|
|
656
|
+
if (appArguments !== undefined && appArguments !== null && !Array.isArray(appArguments)) {
|
|
657
|
+
throw new TypeError("Expected `appArguments` as Array type");
|
|
658
|
+
}
|
|
659
|
+
return baseOpen({
|
|
660
|
+
...options,
|
|
661
|
+
app: {
|
|
662
|
+
name,
|
|
663
|
+
arguments: appArguments
|
|
664
|
+
}
|
|
665
|
+
});
|
|
645
666
|
}, apps, open_default;
|
|
646
667
|
var init_open = __esm(() => {
|
|
647
668
|
init_wsl_utils();
|
|
@@ -721,7 +742,8 @@ class NodeFileSystem {
|
|
|
721
742
|
};
|
|
722
743
|
utils = {
|
|
723
744
|
open: async (url) => {
|
|
724
|
-
await
|
|
745
|
+
const { default: open2 } = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
746
|
+
await open2(url);
|
|
725
747
|
}
|
|
726
748
|
};
|
|
727
749
|
async readFile(path3, options) {
|
|
@@ -916,9 +938,7 @@ class NodeFileSystem {
|
|
|
916
938
|
}
|
|
917
939
|
}
|
|
918
940
|
var LOCK_HEARTBEAT_MS = 5000, LOCK_STALE_MS = 15000, LOCK_MAX_WAIT_MS = 20000, LOCK_MAX_HOLD_MS = 60000, LOCK_RETRY_MIN_MS = 100, LOCK_RETRY_JITTER_MS = 200;
|
|
919
|
-
var init_node =
|
|
920
|
-
init_open();
|
|
921
|
-
});
|
|
941
|
+
var init_node = () => {};
|
|
922
942
|
// ../filesystem/src/index.ts
|
|
923
943
|
var fsInstance, getFileSystem = () => fsInstance;
|
|
924
944
|
var init_src = __esm(() => {
|
|
@@ -927,6 +947,101 @@ var init_src = __esm(() => {
|
|
|
927
947
|
fsInstance = new NodeFileSystem;
|
|
928
948
|
});
|
|
929
949
|
|
|
950
|
+
// src/strategies/browser-strategy.ts
|
|
951
|
+
var exports_browser_strategy = {};
|
|
952
|
+
__export(exports_browser_strategy, {
|
|
953
|
+
BrowserAuthStrategy: () => BrowserAuthStrategy
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
class BrowserAuthStrategy {
|
|
957
|
+
async execute(url, _redirectUri, expectedState, opts) {
|
|
958
|
+
const global = getGlobalThis();
|
|
959
|
+
if (!global?.window) {
|
|
960
|
+
throw new Error("Browser environment required for authentication");
|
|
961
|
+
}
|
|
962
|
+
const screenWidth = global.window.screen?.width ?? 1024;
|
|
963
|
+
const screenHeight = global.window.screen?.height ?? 768;
|
|
964
|
+
const width = 600;
|
|
965
|
+
const height = 700;
|
|
966
|
+
const left = screenWidth / 2 - width / 2;
|
|
967
|
+
const top = screenHeight / 2 - height / 2;
|
|
968
|
+
if (!global.window.open) {
|
|
969
|
+
throw new Error("window.open is not available");
|
|
970
|
+
}
|
|
971
|
+
const popupResult = global.window.open(url, "uip_auth", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes,status=yes`);
|
|
972
|
+
const popup = popupResult;
|
|
973
|
+
if (!popup) {
|
|
974
|
+
throw new Error(`Authentication popup was blocked by your browser.
|
|
975
|
+
|
|
976
|
+
` + `To continue:
|
|
977
|
+
` + `1. Look for a popup blocker icon in your address bar
|
|
978
|
+
` + `2. Allow popups for this site
|
|
979
|
+
` + `3. Try logging in again
|
|
980
|
+
|
|
981
|
+
` + "If using an ad blocker, you may need to temporarily disable it.");
|
|
982
|
+
}
|
|
983
|
+
return new Promise((resolve2, reject) => {
|
|
984
|
+
let timer;
|
|
985
|
+
const messageHandler = (event) => {
|
|
986
|
+
if (event.data?.type === "UIP_AUTH_CODE" && event.data.code) {
|
|
987
|
+
if (event.data.state !== expectedState) {
|
|
988
|
+
cleanup();
|
|
989
|
+
reject(new Error("OAuth state mismatch — the callback state does not match the expected value. " + "This may indicate a CSRF attack. Please try signing in again."));
|
|
990
|
+
popup.close();
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
cleanup();
|
|
994
|
+
resolve2(event.data.code);
|
|
995
|
+
popup.close();
|
|
996
|
+
} else if (event.data?.type === "UIP_AUTH_ERROR") {
|
|
997
|
+
cleanup();
|
|
998
|
+
const errorMsg = event.data.error || "Authentication failed";
|
|
999
|
+
reject(new Error(`Authentication failed: ${errorMsg}
|
|
1000
|
+
|
|
1001
|
+
` + "Please check your credentials and try again. " + "If the problem persists, verify your UiPath account is active."));
|
|
1002
|
+
popup.close();
|
|
1003
|
+
}
|
|
1004
|
+
};
|
|
1005
|
+
const cleanup = () => {
|
|
1006
|
+
global.window?.removeEventListener?.("message", messageHandler);
|
|
1007
|
+
opts?.signal?.removeEventListener("abort", onAbort);
|
|
1008
|
+
if (timer)
|
|
1009
|
+
clearInterval(timer);
|
|
1010
|
+
};
|
|
1011
|
+
const onAbort = () => {
|
|
1012
|
+
cleanup();
|
|
1013
|
+
const err = new Error(`Authentication was cancelled.
|
|
1014
|
+
|
|
1015
|
+
` + "The sign-in was cancelled before completing the login process. " + "Please try again and complete the authentication flow.");
|
|
1016
|
+
err.code = AUTH_CANCELLED_ERROR_CODE;
|
|
1017
|
+
reject(err);
|
|
1018
|
+
popup.close();
|
|
1019
|
+
};
|
|
1020
|
+
if (opts?.signal) {
|
|
1021
|
+
if (opts.signal.aborted) {
|
|
1022
|
+
onAbort();
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
1026
|
+
}
|
|
1027
|
+
if (global.window?.addEventListener) {
|
|
1028
|
+
global.window.addEventListener("message", messageHandler);
|
|
1029
|
+
}
|
|
1030
|
+
timer = setInterval(() => {
|
|
1031
|
+
if (popup.closed) {
|
|
1032
|
+
cleanup();
|
|
1033
|
+
reject(new Error(`Authentication was cancelled.
|
|
1034
|
+
|
|
1035
|
+
` + "The authentication popup was closed before completing the login process. " + "Please try again and complete the authentication flow."));
|
|
1036
|
+
}
|
|
1037
|
+
}, 1000);
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
var init_browser_strategy = __esm(() => {
|
|
1042
|
+
init_constants();
|
|
1043
|
+
});
|
|
1044
|
+
|
|
930
1045
|
// src/getBaseHtml.ts
|
|
931
1046
|
var escapeHtml = (value) => value.replace(/[&<>"']/g, (char) => {
|
|
932
1047
|
switch (char) {
|
|
@@ -1090,7 +1205,7 @@ var escapeHtml = (value) => value.replace(/[&<>"']/g, (char) => {
|
|
|
1090
1205
|
};
|
|
1091
1206
|
|
|
1092
1207
|
// src/server.ts
|
|
1093
|
-
var
|
|
1208
|
+
var startServer = async ({
|
|
1094
1209
|
redirectUri,
|
|
1095
1210
|
timeoutMs = DEFAULT_AUTH_TIMEOUT_MS,
|
|
1096
1211
|
onListening,
|
|
@@ -1209,101 +1324,6 @@ var init_server = __esm(() => {
|
|
|
1209
1324
|
init_constants();
|
|
1210
1325
|
});
|
|
1211
1326
|
|
|
1212
|
-
// src/strategies/browser-strategy.ts
|
|
1213
|
-
var exports_browser_strategy = {};
|
|
1214
|
-
__export(exports_browser_strategy, {
|
|
1215
|
-
BrowserAuthStrategy: () => BrowserAuthStrategy
|
|
1216
|
-
});
|
|
1217
|
-
|
|
1218
|
-
class BrowserAuthStrategy {
|
|
1219
|
-
async execute(url, _redirectUri, expectedState, opts) {
|
|
1220
|
-
const global = getGlobalThis();
|
|
1221
|
-
if (!global?.window) {
|
|
1222
|
-
throw new Error("Browser environment required for authentication");
|
|
1223
|
-
}
|
|
1224
|
-
const screenWidth = global.window.screen?.width ?? 1024;
|
|
1225
|
-
const screenHeight = global.window.screen?.height ?? 768;
|
|
1226
|
-
const width = 600;
|
|
1227
|
-
const height = 700;
|
|
1228
|
-
const left = screenWidth / 2 - width / 2;
|
|
1229
|
-
const top = screenHeight / 2 - height / 2;
|
|
1230
|
-
if (!global.window.open) {
|
|
1231
|
-
throw new Error("window.open is not available");
|
|
1232
|
-
}
|
|
1233
|
-
const popupResult = global.window.open(url, "uip_auth", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes,status=yes`);
|
|
1234
|
-
const popup = popupResult;
|
|
1235
|
-
if (!popup) {
|
|
1236
|
-
throw new Error(`Authentication popup was blocked by your browser.
|
|
1237
|
-
|
|
1238
|
-
` + `To continue:
|
|
1239
|
-
` + `1. Look for a popup blocker icon in your address bar
|
|
1240
|
-
` + `2. Allow popups for this site
|
|
1241
|
-
` + `3. Try logging in again
|
|
1242
|
-
|
|
1243
|
-
` + "If using an ad blocker, you may need to temporarily disable it.");
|
|
1244
|
-
}
|
|
1245
|
-
return new Promise((resolve2, reject) => {
|
|
1246
|
-
let timer;
|
|
1247
|
-
const messageHandler = (event) => {
|
|
1248
|
-
if (event.data?.type === "UIP_AUTH_CODE" && event.data.code) {
|
|
1249
|
-
if (event.data.state !== expectedState) {
|
|
1250
|
-
cleanup();
|
|
1251
|
-
reject(new Error("OAuth state mismatch — the callback state does not match the expected value. " + "This may indicate a CSRF attack. Please try signing in again."));
|
|
1252
|
-
popup.close();
|
|
1253
|
-
return;
|
|
1254
|
-
}
|
|
1255
|
-
cleanup();
|
|
1256
|
-
resolve2(event.data.code);
|
|
1257
|
-
popup.close();
|
|
1258
|
-
} else if (event.data?.type === "UIP_AUTH_ERROR") {
|
|
1259
|
-
cleanup();
|
|
1260
|
-
const errorMsg = event.data.error || "Authentication failed";
|
|
1261
|
-
reject(new Error(`Authentication failed: ${errorMsg}
|
|
1262
|
-
|
|
1263
|
-
` + "Please check your credentials and try again. " + "If the problem persists, verify your UiPath account is active."));
|
|
1264
|
-
popup.close();
|
|
1265
|
-
}
|
|
1266
|
-
};
|
|
1267
|
-
const cleanup = () => {
|
|
1268
|
-
global.window?.removeEventListener?.("message", messageHandler);
|
|
1269
|
-
opts?.signal?.removeEventListener("abort", onAbort);
|
|
1270
|
-
if (timer)
|
|
1271
|
-
clearInterval(timer);
|
|
1272
|
-
};
|
|
1273
|
-
const onAbort = () => {
|
|
1274
|
-
cleanup();
|
|
1275
|
-
const err = new Error(`Authentication was cancelled.
|
|
1276
|
-
|
|
1277
|
-
` + "The sign-in was cancelled before completing the login process. " + "Please try again and complete the authentication flow.");
|
|
1278
|
-
err.code = AUTH_CANCELLED_ERROR_CODE;
|
|
1279
|
-
reject(err);
|
|
1280
|
-
popup.close();
|
|
1281
|
-
};
|
|
1282
|
-
if (opts?.signal) {
|
|
1283
|
-
if (opts.signal.aborted) {
|
|
1284
|
-
onAbort();
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
1288
|
-
}
|
|
1289
|
-
if (global.window?.addEventListener) {
|
|
1290
|
-
global.window.addEventListener("message", messageHandler);
|
|
1291
|
-
}
|
|
1292
|
-
timer = setInterval(() => {
|
|
1293
|
-
if (popup.closed) {
|
|
1294
|
-
cleanup();
|
|
1295
|
-
reject(new Error(`Authentication was cancelled.
|
|
1296
|
-
|
|
1297
|
-
` + "The authentication popup was closed before completing the login process. " + "Please try again and complete the authentication flow."));
|
|
1298
|
-
}
|
|
1299
|
-
}, 1000);
|
|
1300
|
-
});
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
var init_browser_strategy = __esm(() => {
|
|
1304
|
-
init_constants();
|
|
1305
|
-
});
|
|
1306
|
-
|
|
1307
1327
|
// src/strategies/node-strategy.ts
|
|
1308
1328
|
var exports_node_strategy = {};
|
|
1309
1329
|
__export(exports_node_strategy, {
|
|
@@ -2266,6 +2286,67 @@ var getTokenExpiration = (accessToken) => {
|
|
|
2266
2286
|
}
|
|
2267
2287
|
};
|
|
2268
2288
|
|
|
2289
|
+
// src/sessionIdentity.ts
|
|
2290
|
+
var parseAuthFlow = (value) => value === "authorization_code" || value === "client_credentials" || value === "federated_credentials" ? value : undefined;
|
|
2291
|
+
var decodeClaims = (accessToken) => {
|
|
2292
|
+
const [error, claims] = catchError(() => parseJWT(accessToken));
|
|
2293
|
+
return error ? undefined : claims;
|
|
2294
|
+
};
|
|
2295
|
+
var asString = (value) => typeof value === "string" && value.length > 0 ? value : undefined;
|
|
2296
|
+
var resolveIdentityType = (claims, authFlow, email) => {
|
|
2297
|
+
const subType = asString(claims?.sub_type);
|
|
2298
|
+
if (subType) {
|
|
2299
|
+
return subType.startsWith("service") ? "Application" : "User";
|
|
2300
|
+
}
|
|
2301
|
+
if (authFlow) {
|
|
2302
|
+
return authFlow === "authorization_code" ? "User" : "Application";
|
|
2303
|
+
}
|
|
2304
|
+
if (email)
|
|
2305
|
+
return "User";
|
|
2306
|
+
if (asString(claims?.client_id) && !asString(claims?.sub)) {
|
|
2307
|
+
return "Application";
|
|
2308
|
+
}
|
|
2309
|
+
return;
|
|
2310
|
+
};
|
|
2311
|
+
var looksLikeEmail = (value) => value?.includes("@") ?? false;
|
|
2312
|
+
var pickEmail = (claims) => {
|
|
2313
|
+
for (const candidate of [claims?.email, claims?.preferred_username]) {
|
|
2314
|
+
const value = asString(candidate);
|
|
2315
|
+
if (looksLikeEmail(value))
|
|
2316
|
+
return value;
|
|
2317
|
+
}
|
|
2318
|
+
return;
|
|
2319
|
+
};
|
|
2320
|
+
var pickName = (claims) => {
|
|
2321
|
+
const username = asString(claims?.preferred_username);
|
|
2322
|
+
return asString(claims?.name) ?? (looksLikeEmail(username) ? undefined : username);
|
|
2323
|
+
};
|
|
2324
|
+
var resolveSessionIdentity = (accessToken, authFlow) => {
|
|
2325
|
+
const claims = accessToken ? decodeClaims(accessToken) : undefined;
|
|
2326
|
+
const email = pickEmail(claims);
|
|
2327
|
+
const type = resolveIdentityType(claims, authFlow, email);
|
|
2328
|
+
if (!type)
|
|
2329
|
+
return;
|
|
2330
|
+
const identity = { type };
|
|
2331
|
+
if (authFlow)
|
|
2332
|
+
identity.authFlow = authFlow;
|
|
2333
|
+
if (type === "User") {
|
|
2334
|
+
const userId = asString(claims?.sub);
|
|
2335
|
+
if (userId)
|
|
2336
|
+
identity.userId = userId;
|
|
2337
|
+
if (email)
|
|
2338
|
+
identity.userEmail = email;
|
|
2339
|
+
const name = pickName(claims);
|
|
2340
|
+
if (name)
|
|
2341
|
+
identity.userName = name;
|
|
2342
|
+
return identity;
|
|
2343
|
+
}
|
|
2344
|
+
const clientId = asString(claims?.client_id);
|
|
2345
|
+
if (clientId)
|
|
2346
|
+
identity.clientId = clientId;
|
|
2347
|
+
return identity;
|
|
2348
|
+
};
|
|
2349
|
+
|
|
2269
2350
|
// src/envAuth.ts
|
|
2270
2351
|
var ENV_AUTH_ENABLE_VAR = "UIPATH_CLI_ENABLE_ENV_AUTH";
|
|
2271
2352
|
var ENFORCE_ROBOT_AUTH_VAR = "UIPATH_CLI_ENFORCE_ROBOT_AUTH";
|
|
@@ -2315,6 +2396,7 @@ var readAuthFromEnv = () => {
|
|
|
2315
2396
|
}
|
|
2316
2397
|
const expiration = getTokenExpiration(accessToken);
|
|
2317
2398
|
const loginStatus = expiration && expiration <= new Date ? "Expired" : "Logged in";
|
|
2399
|
+
const identity = resolveSessionIdentity(accessToken);
|
|
2318
2400
|
return {
|
|
2319
2401
|
loginStatus,
|
|
2320
2402
|
accessToken,
|
|
@@ -2324,7 +2406,8 @@ var readAuthFromEnv = () => {
|
|
|
2324
2406
|
tenantName,
|
|
2325
2407
|
tenantId,
|
|
2326
2408
|
expiration,
|
|
2327
|
-
source: "env" /*
|
|
2409
|
+
source: "env-vars" /* EnvironmentVariables */,
|
|
2410
|
+
...identity ? { identity } : {}
|
|
2328
2411
|
};
|
|
2329
2412
|
};
|
|
2330
2413
|
|
|
@@ -2580,6 +2663,9 @@ var refreshAccessToken = async ({
|
|
|
2580
2663
|
return { accessToken: newAccessToken, refreshToken: newRefreshToken };
|
|
2581
2664
|
};
|
|
2582
2665
|
|
|
2666
|
+
// src/types.ts
|
|
2667
|
+
var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
|
|
2668
|
+
|
|
2583
2669
|
// src/utils/envFile.ts
|
|
2584
2670
|
init_src();
|
|
2585
2671
|
init_constants();
|
|
@@ -2743,12 +2829,12 @@ var saveEnvFileAsync = async ({
|
|
|
2743
2829
|
};
|
|
2744
2830
|
|
|
2745
2831
|
// src/loginStatus.ts
|
|
2746
|
-
var
|
|
2747
|
-
((
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
})(
|
|
2832
|
+
var CredentialSource;
|
|
2833
|
+
((CredentialSource2) => {
|
|
2834
|
+
CredentialSource2["SavedLogin"] = "saved-login";
|
|
2835
|
+
CredentialSource2["Robot"] = "robot";
|
|
2836
|
+
CredentialSource2["EnvironmentVariables"] = "env-vars";
|
|
2837
|
+
})(CredentialSource ||= {});
|
|
2752
2838
|
var getLoginStatusAsync = async (options = {}) => {
|
|
2753
2839
|
return getLoginStatusWithDeps(options);
|
|
2754
2840
|
};
|
|
@@ -2954,7 +3040,8 @@ async function buildFileStatus(tokens, credentials, globalHint) {
|
|
|
2954
3040
|
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
2955
3041
|
tenantId: credentials.UIPATH_TENANT_ID,
|
|
2956
3042
|
expiration: tokens.expiration,
|
|
2957
|
-
source: "
|
|
3043
|
+
source: "saved-login" /* SavedLogin */,
|
|
3044
|
+
...identityFields(tokens.accessToken, credentials),
|
|
2958
3045
|
...tokens.persistenceWarning ? { hint: tokens.persistenceWarning, persistenceFailed: true } : {},
|
|
2959
3046
|
...tokens.lockReleaseFailed ? { lockReleaseFailed: true } : {},
|
|
2960
3047
|
...tokens.tokenRefresh ? { tokenRefresh: tokens.tokenRefresh } : {}
|
|
@@ -2967,7 +3054,12 @@ async function buildFileStatus(tokens, credentials, globalHint) {
|
|
|
2967
3054
|
}
|
|
2968
3055
|
return result;
|
|
2969
3056
|
}
|
|
3057
|
+
function identityFields(accessToken, credentials) {
|
|
3058
|
+
const identity = resolveSessionIdentity(accessToken, parseAuthFlow(credentials[AUTH_FLOW_ENV_VAR]));
|
|
3059
|
+
return identity ? { identity } : {};
|
|
3060
|
+
}
|
|
2970
3061
|
function buildRobotStatus(robotCreds) {
|
|
3062
|
+
const identity = resolveSessionIdentity(robotCreds.accessToken);
|
|
2971
3063
|
return {
|
|
2972
3064
|
loginStatus: "Logged in",
|
|
2973
3065
|
accessToken: robotCreds.accessToken,
|
|
@@ -2978,7 +3070,8 @@ function buildRobotStatus(robotCreds) {
|
|
|
2978
3070
|
tenantId: robotCreds.tenantId,
|
|
2979
3071
|
issuer: robotCreds.issuer,
|
|
2980
3072
|
expiration: getTokenExpiration(robotCreds.accessToken),
|
|
2981
|
-
source: "robot" /* Robot
|
|
3073
|
+
source: "robot" /* Robot */,
|
|
3074
|
+
...identity ? { identity } : {}
|
|
2982
3075
|
};
|
|
2983
3076
|
}
|
|
2984
3077
|
var isFileNotFoundError = (error) => {
|
|
@@ -3029,7 +3122,8 @@ async function circuitBreakerShortCircuit(ctx) {
|
|
|
3029
3122
|
tenantName: credentials.UIPATH_TENANT_NAME,
|
|
3030
3123
|
tenantId: credentials.UIPATH_TENANT_ID,
|
|
3031
3124
|
expiration,
|
|
3032
|
-
source: "
|
|
3125
|
+
source: "saved-login" /* SavedLogin */,
|
|
3126
|
+
...identityFields(accessToken, credentials)
|
|
3033
3127
|
} : {},
|
|
3034
3128
|
hint: globalHint ?? (tokenIsDead ? deadHint : backoffHint),
|
|
3035
3129
|
refreshCircuitOpen: true,
|
|
@@ -3051,7 +3145,8 @@ async function lockAcquireFailureStatus(ctx, error) {
|
|
|
3051
3145
|
tenantName: ctx.credentials.UIPATH_TENANT_NAME,
|
|
3052
3146
|
tenantId: ctx.credentials.UIPATH_TENANT_ID,
|
|
3053
3147
|
expiration: ctx.expiration,
|
|
3054
|
-
source: "
|
|
3148
|
+
source: "saved-login" /* SavedLogin */,
|
|
3149
|
+
...identityFields(ctx.accessToken, ctx.credentials),
|
|
3055
3150
|
hint: globalHint,
|
|
3056
3151
|
tokenRefresh: {
|
|
3057
3152
|
attempted: false,
|
|
@@ -3452,6 +3547,16 @@ var federatedCredentialsLogin = async ({
|
|
|
3452
3547
|
init_src();
|
|
3453
3548
|
|
|
3454
3549
|
// src/tenantSelection.ts
|
|
3550
|
+
var LOGIN_STATUS_HINT = "Run 'uip login status' to see the organization the CLI is signed in to.";
|
|
3551
|
+
var organizationHint = (organizationId) => `The request used '${organizationId}' as the organization. ${LOGIN_STATUS_HINT}`;
|
|
3552
|
+
var IDENTIFIER_STATUSES = new Set([400, 403, 404]);
|
|
3553
|
+
var describeNonJsonResponse = (organizationId, response, parseError) => {
|
|
3554
|
+
if (response.redirected) {
|
|
3555
|
+
return `Could not find organization '${organizationId}': the request was ` + `redirected to a sign-in page instead of the organization's tenant ` + `list. ${LOGIN_STATUS_HINT}`;
|
|
3556
|
+
}
|
|
3557
|
+
const contentType = response.headers.get("content-type") ?? "unknown";
|
|
3558
|
+
return `The organization service returned a '${contentType}' response instead ` + `of JSON: ${parseError.message}. ${organizationHint(organizationId)}`;
|
|
3559
|
+
};
|
|
3455
3560
|
var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId) => {
|
|
3456
3561
|
const url = `${baseUrl}/${organizationId}/portal_/api/filtering/leftnav/tenantsAndOrganizationInfo`;
|
|
3457
3562
|
const response = await fetch(url, {
|
|
@@ -3461,12 +3566,16 @@ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId)
|
|
|
3461
3566
|
});
|
|
3462
3567
|
if (!response.ok) {
|
|
3463
3568
|
if (response.status === 401) {
|
|
3464
|
-
throw new Error(
|
|
3569
|
+
throw new Error(`Unauthorized: the access token was rejected, it was not ` + `issued for organization '${organizationId}', or ` + `'${organizationId}' was not accepted as an organization ` + `URL segment in this environment. ` + LOGIN_STATUS_HINT);
|
|
3465
3570
|
}
|
|
3466
3571
|
const errorText = await response.text();
|
|
3467
|
-
|
|
3572
|
+
const message = `Failed to get tenants and organizations: ${response.status} ${errorText}`;
|
|
3573
|
+
throw new Error(IDENTIFIER_STATUSES.has(response.status) ? `${message}. ${organizationHint(organizationId)}` : message);
|
|
3574
|
+
}
|
|
3575
|
+
const [parseError, data] = await catchError(response.json());
|
|
3576
|
+
if (parseError) {
|
|
3577
|
+
throw new Error(describeNonJsonResponse(organizationId, response, parseError));
|
|
3468
3578
|
}
|
|
3469
|
-
const data = await response.json();
|
|
3470
3579
|
return data;
|
|
3471
3580
|
};
|
|
3472
3581
|
|
|
@@ -3545,9 +3654,6 @@ var selectTenantWithDeps = async (baseUrl, accessToken, organizationId, targetTe
|
|
|
3545
3654
|
return [selectedTenant.name, selectedTenant.id, organization.name];
|
|
3546
3655
|
};
|
|
3547
3656
|
|
|
3548
|
-
// src/types.ts
|
|
3549
|
-
var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
|
|
3550
|
-
|
|
3551
3657
|
// src/interactive.ts
|
|
3552
3658
|
var interactiveLoginWithDeps = async (options, deps) => {
|
|
3553
3659
|
const {
|
|
@@ -3771,7 +3877,6 @@ async function logout(options) {
|
|
|
3771
3877
|
}
|
|
3772
3878
|
|
|
3773
3879
|
// src/index.ts
|
|
3774
|
-
init_server();
|
|
3775
3880
|
var authenticate = async ({
|
|
3776
3881
|
baseUrl,
|
|
3777
3882
|
clientId,
|
|
@@ -3854,6 +3959,7 @@ export {
|
|
|
3854
3959
|
saveRefreshBreaker,
|
|
3855
3960
|
saveEnvFileAsync,
|
|
3856
3961
|
runWithAuthProfile,
|
|
3962
|
+
resolveSessionIdentity,
|
|
3857
3963
|
resolveEnvFilePathAsync,
|
|
3858
3964
|
resolveEnvFileLocationAsync,
|
|
3859
3965
|
resolveAuthProfileFilePath,
|
|
@@ -3862,6 +3968,7 @@ export {
|
|
|
3862
3968
|
refreshAccessToken,
|
|
3863
3969
|
readAuthFromEnv,
|
|
3864
3970
|
parseJWT,
|
|
3971
|
+
parseAuthFlow,
|
|
3865
3972
|
normalizeAuthProfileName,
|
|
3866
3973
|
logoutWithDeps,
|
|
3867
3974
|
logout,
|
|
@@ -3891,7 +3998,6 @@ export {
|
|
|
3891
3998
|
TenantSelectionRequiredError,
|
|
3892
3999
|
TenantSelectionError,
|
|
3893
4000
|
TENANT_SELECTION_REQUIRED_CODE,
|
|
3894
|
-
LoginStatusSource,
|
|
3895
4001
|
JWT_BEARER_ASSERTION_TYPE,
|
|
3896
4002
|
InvalidTenantError,
|
|
3897
4003
|
InvalidBaseUrlError,
|
|
@@ -3905,6 +4011,7 @@ export {
|
|
|
3905
4011
|
DEFAULT_AUTH_TIMEOUT_MS,
|
|
3906
4012
|
DEFAULT_AUTH_PROFILE,
|
|
3907
4013
|
DEFAULT_AUTH_FILENAME,
|
|
4014
|
+
CredentialSource,
|
|
3908
4015
|
ClientCredentialsAuthenticationError,
|
|
3909
4016
|
AuthProfileValidationError,
|
|
3910
4017
|
AUTH_TIMEOUT_ERROR_CODE,
|
|
@@ -3912,4 +4019,4 @@ export {
|
|
|
3912
4019
|
AUTH_CANCELLED_ERROR_CODE
|
|
3913
4020
|
};
|
|
3914
4021
|
|
|
3915
|
-
//# debugId=
|
|
4022
|
+
//# debugId=C655D07F97343A8C64756E2164756E21
|
package/dist/loginStatus.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { getFileSystem } from "@uipath/filesystem";
|
|
|
2
2
|
import { resolveConfigAsync } from "./config";
|
|
3
3
|
import { clearRefreshBreaker, loadRefreshBreaker, saveRefreshBreaker } from "./refreshCircuitBreaker";
|
|
4
4
|
import { tryRobotClientFallback } from "./robotClientFallback";
|
|
5
|
+
import { type SessionIdentity } from "./sessionIdentity";
|
|
5
6
|
import { refreshAccessToken } from "./tokenRefresh";
|
|
6
7
|
import { loadEnvFileAsync, resolveEnvFilePathAsync, saveEnvFileAsync } from "./utils/envFile";
|
|
7
8
|
/**
|
|
@@ -10,10 +11,15 @@ import { loadEnvFileAsync, resolveEnvFilePathAsync, saveEnvFileAsync } from "./u
|
|
|
10
11
|
* refresh was tried and could not complete with a usable token.
|
|
11
12
|
*/
|
|
12
13
|
export type LoginStatusValue = "Logged in" | "Not logged in" | "Expired" | "Refresh Failed";
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Where the CLI read the credential from — not who is acting and not how they
|
|
16
|
+
* authenticated. See {@link SessionIdentity} for those; the three are
|
|
17
|
+
* independent (a `Robot` credential normally carries a `User` identity).
|
|
18
|
+
*/
|
|
19
|
+
export declare enum CredentialSource {
|
|
20
|
+
SavedLogin = "saved-login",
|
|
15
21
|
Robot = "robot",
|
|
16
|
-
|
|
22
|
+
EnvironmentVariables = "env-vars"
|
|
17
23
|
}
|
|
18
24
|
export interface TokenRefreshTelemetry {
|
|
19
25
|
attempted: boolean;
|
|
@@ -38,7 +44,14 @@ export interface LoginStatus {
|
|
|
38
44
|
issuer?: string;
|
|
39
45
|
expiration?: Date;
|
|
40
46
|
hint?: string;
|
|
41
|
-
source?:
|
|
47
|
+
source?: CredentialSource;
|
|
48
|
+
/**
|
|
49
|
+
* Who the session acts as, read from the access token's claims. Present
|
|
50
|
+
* whenever a token is available to derive it from — including `"Expired"`,
|
|
51
|
+
* so the user can see whose session lapsed. Display only: the claims are
|
|
52
|
+
* not signature-verified.
|
|
53
|
+
*/
|
|
54
|
+
identity?: SessionIdentity;
|
|
42
55
|
/**
|
|
43
56
|
* True when a refresh rotated successfully at the identity server but
|
|
44
57
|
* persisting the new pair to disk failed. The returned `accessToken` is
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { AUTH_TIMEOUT_ERROR_CODE } from "./constants";
|
|
2
|
+
export { AUTH_TIMEOUT_ERROR_CODE };
|
|
2
3
|
interface StartCallbackServerProps {
|
|
3
4
|
redirectUri: URL;
|
|
4
5
|
timeoutMs?: number;
|
|
@@ -12,4 +13,3 @@ interface StartCallbackServerProps {
|
|
|
12
13
|
signal?: AbortSignal;
|
|
13
14
|
}
|
|
14
15
|
export declare const startServer: ({ redirectUri, timeoutMs, onListening, signal, }: StartCallbackServerProps) => Promise<URL>;
|
|
15
|
-
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AuthFlow } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Whether the session acts as a person or as an external application.
|
|
4
|
+
* Deliberately coarse — `authFlow` carries the precision.
|
|
5
|
+
*/
|
|
6
|
+
export type IdentityType = "User" | "Application";
|
|
7
|
+
/**
|
|
8
|
+
* Who the current session acts as, as reported by the access token.
|
|
9
|
+
*
|
|
10
|
+
* Every field here is read from *unverified* token claims (base64 decode, no
|
|
11
|
+
* signature check) and exists to be shown to a human. Never branch on it for
|
|
12
|
+
* an authorization or trust decision.
|
|
13
|
+
*/
|
|
14
|
+
export interface SessionIdentity {
|
|
15
|
+
type: IdentityType;
|
|
16
|
+
/** Absent when the CLI did not run the flow itself (e.g. Robot-borrowed). */
|
|
17
|
+
authFlow?: AuthFlow;
|
|
18
|
+
/** User identities only — the token's `sub`. */
|
|
19
|
+
userId?: string;
|
|
20
|
+
userEmail?: string;
|
|
21
|
+
userName?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Application identities only. User tokens also carry a `client_id` — the
|
|
24
|
+
* CLI's own — and surfacing that would read as if an app were acting.
|
|
25
|
+
*/
|
|
26
|
+
clientId?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Narrow an on-disk `UIPATH_AUTH_FLOW` value to a known flow. */
|
|
29
|
+
export declare const parseAuthFlow: (value: string | undefined) => AuthFlow | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Derive the acting identity from an access token and, when known, the flow
|
|
32
|
+
* that produced it. Returns undefined when neither says anything — better to
|
|
33
|
+
* omit the fields than to guess at who is acting.
|
|
34
|
+
*/
|
|
35
|
+
export declare const resolveSessionIdentity: (accessToken: string | undefined, authFlow?: AuthFlow) => SessionIdentity | undefined;
|
|
@@ -12,6 +12,18 @@ export interface TenantsAndOrganizations {
|
|
|
12
12
|
tenants: Tenant[];
|
|
13
13
|
organization: Organization;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Fetch tenants and organizations from UiPath Cloud.
|
|
17
|
+
*
|
|
18
|
+
* @param organizationId - The organization segment of the portal URL. Pass the
|
|
19
|
+
* organization's name whenever it is known: the name is the segment that
|
|
20
|
+
* routes reliably, and it is never confused with the account GUID that
|
|
21
|
+
* licensing and analytics APIs take as `accountId`. The id works during login,
|
|
22
|
+
* where the token is always fresh — login has only the id at this point, the
|
|
23
|
+
* name is what this call returns — but it is not a like-for-like substitute
|
|
24
|
+
* later on: the portal has been seen answering `401` to the id (and to a
|
|
25
|
+
* case-variant of the name) on an aged-but-valid session that the exact name
|
|
26
|
+
* still resolves. So the id is a last-resort fallback, not an equal option.
|
|
27
|
+
*/
|
|
16
28
|
export declare const fetchTenantsAndOrganizations: (baseUrl: string, accessToken: string, organizationId: string) => Promise<TenantsAndOrganizations>;
|
|
17
29
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/auth",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.201.0-preview.121",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/UiPath/cli.git",
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"mihaigirleanu",
|
|
38
38
|
"vlad-uipath"
|
|
39
39
|
],
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "c70ccfc0b12e637441d67df1d212b71d7784b5f8"
|
|
41
41
|
}
|