@uipath/auth 1.200.0-preview.109 → 1.201.0-preview.115

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.
@@ -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";
@@ -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";
@@ -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" /* 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 LoginStatusSource;
18929
- ((LoginStatusSource2) => {
18930
- LoginStatusSource2["File"] = "file";
18931
- LoginStatusSource2["Robot"] = "robot";
18932
- LoginStatusSource2["Env"] = "env";
18933
- })(LoginStatusSource ||= {});
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: "file" /* File */,
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: "file" /* File */
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: "file" /* File */,
19310
+ source: "saved-login" /* SavedLogin */,
19311
+ ...identityFields(ctx.accessToken, ctx.credentials),
19237
19312
  hint: globalHint,
19238
19313
  tokenRefresh: {
19239
19314
  attempted: false,
@@ -19621,18 +19696,18 @@ var fetchTenantsAndOrganizations = async (baseUrl, accessToken, organizationId)
19621
19696
  const data = await response.json();
19622
19697
  return data;
19623
19698
  };
19624
- // src/types.ts
19625
- var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
19626
19699
  export {
19627
19700
  setAuthFileConfig,
19628
19701
  setActiveAuthProfile,
19629
19702
  saveEnvFileAsync,
19630
19703
  runWithAuthProfile,
19704
+ resolveSessionIdentity,
19631
19705
  resolveEnvFilePathAsync,
19632
19706
  resolveEnvFileLocationAsync,
19633
19707
  resolveAuthProfileFilePath,
19634
19708
  refreshAccessToken,
19635
19709
  parseJWT,
19710
+ parseAuthFlow,
19636
19711
  normalizeAuthProfileName,
19637
19712
  logoutWithDeps,
19638
19713
  logout,
@@ -19650,14 +19725,14 @@ export {
19650
19725
  clientCredentialsLogin,
19651
19726
  clearActiveAuthProfile,
19652
19727
  TokenRefreshOAuthError,
19653
- LoginStatusSource,
19654
19728
  InvalidBaseUrlError,
19655
19729
  DEFAULT_ENV_FILENAME,
19656
19730
  DEFAULT_AUTH_PROFILE,
19657
19731
  DEFAULT_AUTH_FILENAME,
19732
+ CredentialSource,
19658
19733
  ClientCredentialsAuthenticationError,
19659
19734
  AuthProfileValidationError,
19660
19735
  AUTH_FLOW_ENV_VAR
19661
19736
  };
19662
19737
 
19663
- //# debugId=EAD5BC5B9162A5E464756E2164756E21
19738
+ //# debugId=A433BD3381C7E18264756E2164756E21
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 { AUTH_TIMEOUT_ERROR_CODE } from "./server";
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 open_default(url);
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 = __esm(() => {
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 AUTH_TIMEOUT_ERROR_CODE = "EAUTHTIMEOUT", startServer = async ({
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" /* 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 LoginStatusSource;
2747
- ((LoginStatusSource2) => {
2748
- LoginStatusSource2["File"] = "file";
2749
- LoginStatusSource2["Robot"] = "robot";
2750
- LoginStatusSource2["Env"] = "env";
2751
- })(LoginStatusSource ||= {});
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: "file" /* File */,
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: "file" /* File */
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: "file" /* File */,
3148
+ source: "saved-login" /* SavedLogin */,
3149
+ ...identityFields(ctx.accessToken, ctx.credentials),
3055
3150
  hint: globalHint,
3056
3151
  tokenRefresh: {
3057
3152
  attempted: false,
@@ -3545,9 +3640,6 @@ var selectTenantWithDeps = async (baseUrl, accessToken, organizationId, targetTe
3545
3640
  return [selectedTenant.name, selectedTenant.id, organization.name];
3546
3641
  };
3547
3642
 
3548
- // src/types.ts
3549
- var AUTH_FLOW_ENV_VAR = "UIPATH_AUTH_FLOW";
3550
-
3551
3643
  // src/interactive.ts
3552
3644
  var interactiveLoginWithDeps = async (options, deps) => {
3553
3645
  const {
@@ -3771,7 +3863,6 @@ async function logout(options) {
3771
3863
  }
3772
3864
 
3773
3865
  // src/index.ts
3774
- init_server();
3775
3866
  var authenticate = async ({
3776
3867
  baseUrl,
3777
3868
  clientId,
@@ -3854,6 +3945,7 @@ export {
3854
3945
  saveRefreshBreaker,
3855
3946
  saveEnvFileAsync,
3856
3947
  runWithAuthProfile,
3948
+ resolveSessionIdentity,
3857
3949
  resolveEnvFilePathAsync,
3858
3950
  resolveEnvFileLocationAsync,
3859
3951
  resolveAuthProfileFilePath,
@@ -3862,6 +3954,7 @@ export {
3862
3954
  refreshAccessToken,
3863
3955
  readAuthFromEnv,
3864
3956
  parseJWT,
3957
+ parseAuthFlow,
3865
3958
  normalizeAuthProfileName,
3866
3959
  logoutWithDeps,
3867
3960
  logout,
@@ -3891,7 +3984,6 @@ export {
3891
3984
  TenantSelectionRequiredError,
3892
3985
  TenantSelectionError,
3893
3986
  TENANT_SELECTION_REQUIRED_CODE,
3894
- LoginStatusSource,
3895
3987
  JWT_BEARER_ASSERTION_TYPE,
3896
3988
  InvalidTenantError,
3897
3989
  InvalidBaseUrlError,
@@ -3905,6 +3997,7 @@ export {
3905
3997
  DEFAULT_AUTH_TIMEOUT_MS,
3906
3998
  DEFAULT_AUTH_PROFILE,
3907
3999
  DEFAULT_AUTH_FILENAME,
4000
+ CredentialSource,
3908
4001
  ClientCredentialsAuthenticationError,
3909
4002
  AuthProfileValidationError,
3910
4003
  AUTH_TIMEOUT_ERROR_CODE,
@@ -3912,4 +4005,4 @@ export {
3912
4005
  AUTH_CANCELLED_ERROR_CODE
3913
4006
  };
3914
4007
 
3915
- //# debugId=B8729C58CA2817B364756E2164756E21
4008
+ //# debugId=FB7C8F900705E0B964756E2164756E21
@@ -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
- export declare enum LoginStatusSource {
14
- File = "file",
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
- Env = "env"
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?: LoginStatusSource;
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
- export declare const AUTH_TIMEOUT_ERROR_CODE = "EAUTHTIMEOUT";
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;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uipath/auth",
3
3
  "license": "MIT",
4
- "version": "1.200.0-preview.109",
4
+ "version": "1.201.0-preview.115",
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": "fcc01cdae81bbd0c25d3d4fc287537a9d19d99f4"
40
+ "gitHead": "f1086b73654d7728cb71f280588b3e0c77d535fc"
41
41
  }