@uipath/auth 1.1.0 → 1.195.0
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 +17 -0
- package/dist/catch-error.d.ts +5 -0
- package/dist/clientCredentials.d.ts +9 -0
- package/dist/config.d.ts +73 -0
- package/dist/constants.d.ts +10 -0
- package/dist/envAuth.d.ts +75 -0
- package/dist/getBaseHtml.d.ts +7 -0
- package/dist/index.browser.d.ts +10 -0
- package/dist/index.browser.js +234 -99
- package/dist/index.d.ts +27 -0
- package/dist/index.js +435 -188
- package/dist/interactive.d.ts +93 -0
- package/dist/loginStatus.d.ts +73 -0
- package/dist/logout.d.ts +44 -0
- package/dist/oidc.d.ts +5 -0
- package/dist/robotClientFallback.d.ts +63 -0
- package/dist/selectTenant.d.ts +8 -0
- package/dist/server.d.ts +8 -0
- package/dist/strategies/auth-strategy.d.ts +3 -0
- package/dist/strategies/browser-strategy.d.ts +4 -0
- package/dist/strategies/node-strategy.d.ts +4 -0
- package/dist/tenantSelection.d.ts +17 -0
- package/dist/tokenExchange.d.ts +13 -0
- package/dist/tokenRefresh.d.ts +27 -0
- package/dist/types.d.ts +5 -0
- package/dist/utils/envFile.d.ts +101 -0
- package/dist/utils/jwt.d.ts +43 -0
- package/dist/utils/platform.d.ts +36 -0
- package/package.json +38 -43
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { getFileSystem } from "@uipath/filesystem";
|
|
2
|
+
import { clientCredentialsLogin } from "./clientCredentials";
|
|
3
|
+
import { resolveConfigAsync } from "./config";
|
|
4
|
+
import { authenticate } from "./index";
|
|
5
|
+
import { type SelectFromList } from "./selectTenant";
|
|
6
|
+
import type { BaseCredentials } from "./types";
|
|
7
|
+
import { loadEnvFileAsync, saveEnvFileAsync } from "./utils/envFile";
|
|
8
|
+
import { assertIssuerMatchesAuthority, parseJWT } from "./utils/jwt";
|
|
9
|
+
/**
|
|
10
|
+
* Structured progress events emitted during interactive login. Auth has no
|
|
11
|
+
* logger of its own (see `refactor(auth): remove common dependency`), so the
|
|
12
|
+
* CLI subscribes to these events and routes them to its logger / output sink.
|
|
13
|
+
*/
|
|
14
|
+
export type InteractiveLoginEvent = {
|
|
15
|
+
type: "info";
|
|
16
|
+
message: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: "warn";
|
|
19
|
+
message: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: "saved";
|
|
22
|
+
path: string;
|
|
23
|
+
locality: "local" | "global";
|
|
24
|
+
} | {
|
|
25
|
+
type: "tenant-fetch-failed";
|
|
26
|
+
message: string;
|
|
27
|
+
};
|
|
28
|
+
interface InteractiveLoginOptions {
|
|
29
|
+
envFilePath?: string;
|
|
30
|
+
scope?: string[];
|
|
31
|
+
authority?: string;
|
|
32
|
+
clientId?: string;
|
|
33
|
+
clientSecret?: string;
|
|
34
|
+
tenant?: string;
|
|
35
|
+
organization?: string;
|
|
36
|
+
interactive?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Callback used when interactive tenant selection is required (multiple
|
|
39
|
+
* tenants and `interactive` is true). Auth has no UI dependency of its
|
|
40
|
+
* own — the host (e.g. the CLI) supplies the prompt implementation.
|
|
41
|
+
*/
|
|
42
|
+
selectFromList?: SelectFromList;
|
|
43
|
+
/** Optional subscriber for user-facing progress events. */
|
|
44
|
+
onEvent?: (event: InteractiveLoginEvent) => void;
|
|
45
|
+
}
|
|
46
|
+
export interface InteractiveLoginDependencies {
|
|
47
|
+
resolveConfig?: typeof resolveConfigAsync;
|
|
48
|
+
clientCredentials?: typeof clientCredentialsLogin;
|
|
49
|
+
auth?: typeof authenticate;
|
|
50
|
+
saveEnvFile?: typeof saveEnvFileAsync;
|
|
51
|
+
loadEnvFile?: typeof loadEnvFileAsync;
|
|
52
|
+
getFs?: typeof getFileSystem;
|
|
53
|
+
jwtParser?: typeof parseJWT;
|
|
54
|
+
issuerAsserter?: typeof assertIssuerMatchesAuthority;
|
|
55
|
+
tenantSelector?: (baseUrl: string, accessToken: string, organizationId: string, tenantName?: string, interactive?: boolean) => Promise<[string, string, string]>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Perform interactive login to UiPath Cloud using either Client Credentials or Authorization Code flow.
|
|
59
|
+
*
|
|
60
|
+
* This function automatically selects the appropriate authentication flow:
|
|
61
|
+
* - If clientSecret is provided: Uses Client Credentials (silent)
|
|
62
|
+
* - Otherwise: Uses Authorization Code with PKCE (opens browser)
|
|
63
|
+
*
|
|
64
|
+
* After successful authentication, credentials are saved to the specified credentials file and
|
|
65
|
+
* the organization ID is extracted from the JWT token.
|
|
66
|
+
*
|
|
67
|
+
* @param options - Login configuration options
|
|
68
|
+
* @param options.envFilePath - Path to save credentials (default: ".uipath/.auth")
|
|
69
|
+
* @param options.scope - OAuth scopes to request (optional)
|
|
70
|
+
* @param options.authority - Custom authority URL (optional)
|
|
71
|
+
* @param options.clientId - Custom client ID (optional)
|
|
72
|
+
* @param options.clientSecret - Client secret for Client Credentials flow (optional)
|
|
73
|
+
* @returns Promise resolving to the saved credentials including access token and organization ID
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // Interactive browser-based login
|
|
78
|
+
* const creds = await interactiveLogin({
|
|
79
|
+
* envFilePath: '.uipath/.auth',
|
|
80
|
+
* scope: ['OR.Machines', 'OR.Robots']
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* // Client Credentials login
|
|
84
|
+
* const creds = await interactiveLogin({
|
|
85
|
+
* envFilePath: '.uipath/.auth',
|
|
86
|
+
* clientId: 'my-app',
|
|
87
|
+
* clientSecret: 'secret-key'
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare const interactiveLoginWithDeps: (options: InteractiveLoginOptions, deps: InteractiveLoginDependencies) => Promise<BaseCredentials>;
|
|
92
|
+
export declare const interactiveLogin: (options: InteractiveLoginOptions) => Promise<BaseCredentials>;
|
|
93
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getFileSystem } from "@uipath/filesystem";
|
|
2
|
+
import { resolveConfigAsync } from "./config";
|
|
3
|
+
import { tryRobotClientFallback } from "./robotClientFallback";
|
|
4
|
+
import { refreshAccessToken } from "./tokenRefresh";
|
|
5
|
+
import { loadEnvFileAsync, resolveEnvFilePathAsync, saveEnvFileAsync } from "./utils/envFile";
|
|
6
|
+
/**
|
|
7
|
+
* `"Expired"` means no refresh was attempted (no refresh token on file);
|
|
8
|
+
* recovery may be as cheap as copying a file. `"Refresh Failed"` means
|
|
9
|
+
* refresh was tried and could not complete with a usable token.
|
|
10
|
+
*/
|
|
11
|
+
export type LoginStatusValue = "Logged in" | "Not logged in" | "Expired" | "Refresh Failed";
|
|
12
|
+
export declare enum LoginStatusSource {
|
|
13
|
+
File = "file",
|
|
14
|
+
Robot = "robot"
|
|
15
|
+
}
|
|
16
|
+
export interface TokenRefreshTelemetry {
|
|
17
|
+
attempted: boolean;
|
|
18
|
+
success: boolean;
|
|
19
|
+
errorMessage?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface LoginStatus {
|
|
22
|
+
loginStatus: LoginStatusValue;
|
|
23
|
+
accessToken?: string;
|
|
24
|
+
refreshToken?: string;
|
|
25
|
+
baseUrl?: string;
|
|
26
|
+
organizationName?: string;
|
|
27
|
+
organizationId?: string;
|
|
28
|
+
tenantName?: string;
|
|
29
|
+
tenantId?: string;
|
|
30
|
+
expiration?: Date;
|
|
31
|
+
hint?: string;
|
|
32
|
+
source?: LoginStatusSource;
|
|
33
|
+
/**
|
|
34
|
+
* True when a refresh rotated successfully at the identity server but
|
|
35
|
+
* persisting the new pair to disk failed. The returned `accessToken` is
|
|
36
|
+
* valid for THIS call; the next invocation will fail until the on-disk
|
|
37
|
+
* pair can be updated.
|
|
38
|
+
*/
|
|
39
|
+
persistenceFailed?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* True when the advisory file lock was acquired during refresh but its
|
|
42
|
+
* release rejected. The refresh outcome itself is unaffected — peers
|
|
43
|
+
* reclaim the leftover lock as stale on their next attempt. Carried as
|
|
44
|
+
* a structured signal so consumers can branch on it without parsing
|
|
45
|
+
* the user-facing `hint`.
|
|
46
|
+
*/
|
|
47
|
+
lockReleaseFailed?: boolean;
|
|
48
|
+
tokenRefresh?: TokenRefreshTelemetry;
|
|
49
|
+
}
|
|
50
|
+
export interface GetLoginStatusOptions {
|
|
51
|
+
envFilePath?: string;
|
|
52
|
+
ensureTokenValidityMinutes?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface LoginStatusDependencies {
|
|
55
|
+
resolveEnvFilePath?: typeof resolveEnvFilePathAsync;
|
|
56
|
+
loadEnvFile?: typeof loadEnvFileAsync;
|
|
57
|
+
saveEnvFile?: typeof saveEnvFileAsync;
|
|
58
|
+
getFs?: typeof getFileSystem;
|
|
59
|
+
refreshToken?: typeof refreshAccessToken;
|
|
60
|
+
resolveConfig?: typeof resolveConfigAsync;
|
|
61
|
+
robotFallback?: typeof tryRobotClientFallback;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the current login status by reading credentials from the credentials file (with DI for testing)
|
|
65
|
+
*/
|
|
66
|
+
export declare const getLoginStatusWithDeps: (options?: GetLoginStatusOptions, deps?: LoginStatusDependencies) => Promise<LoginStatus>;
|
|
67
|
+
/**
|
|
68
|
+
* Get the current login status by reading credentials from the credentials file
|
|
69
|
+
* @param envFilePath - Path to the credentials file (defaults to ".uipath/.auth")
|
|
70
|
+
* @param ensureTokenValidityMinutes - If provided, refreshes the token when it expires within this many minutes
|
|
71
|
+
* @returns LoginStatus object with authentication information
|
|
72
|
+
*/
|
|
73
|
+
export declare const getLoginStatusAsync: (options?: GetLoginStatusOptions) => Promise<LoginStatus>;
|
package/dist/logout.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getFileSystem } from "@uipath/filesystem";
|
|
2
|
+
import { resolveEnvFilePathAsync } from "./utils/envFile";
|
|
3
|
+
export interface LogoutOptions {
|
|
4
|
+
file?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LogoutResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
message: string;
|
|
9
|
+
removedPath?: string;
|
|
10
|
+
reason?: "no_credentials_file";
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* File system interface for logout operations
|
|
14
|
+
*/
|
|
15
|
+
export interface LogoutFileSystem {
|
|
16
|
+
exists: (path: string) => Promise<boolean>;
|
|
17
|
+
rm: (path: string) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Dependency injection interface for testing
|
|
21
|
+
*/
|
|
22
|
+
export interface LogoutDependencies {
|
|
23
|
+
resolveEnvFilePath?: typeof resolveEnvFilePathAsync;
|
|
24
|
+
getFileSystem?: typeof getFileSystem;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Logout from UiPath Cloud by removing the credentials file.
|
|
28
|
+
*
|
|
29
|
+
* This function removes the credentials file containing authentication credentials.
|
|
30
|
+
* It uses dependency injection for testability.
|
|
31
|
+
*
|
|
32
|
+
* @param options - Logout configuration options
|
|
33
|
+
* @param options.file - Path to credentials file (optional, uses default resolution if not provided)
|
|
34
|
+
* @param deps - Injected dependencies for testing
|
|
35
|
+
* @returns Promise resolving to the logout result
|
|
36
|
+
*/
|
|
37
|
+
export declare function logoutWithDeps(options: LogoutOptions, deps?: LogoutDependencies): Promise<LogoutResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Logout from UiPath Cloud by removing the credentials file.
|
|
40
|
+
*
|
|
41
|
+
* @param options - Logout configuration options
|
|
42
|
+
* @returns Promise resolving to the logout result
|
|
43
|
+
*/
|
|
44
|
+
export declare function logout(options: LogoutOptions): Promise<LogoutResult>;
|
package/dist/oidc.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal structural view of `@uipath/robot-client` — covers only the two
|
|
3
|
+
* methods we consume. Defined locally so that this file compiles even when
|
|
4
|
+
* the package is absent (it is loaded via dynamic `import()` at runtime).
|
|
5
|
+
*/
|
|
6
|
+
interface IInteractiveConnectFlow {
|
|
7
|
+
IsEnabled(): Promise<boolean>;
|
|
8
|
+
}
|
|
9
|
+
interface IAccessProvider {
|
|
10
|
+
GetResourceUrl(scope: "Orchestrator"): Promise<string>;
|
|
11
|
+
GetAccessToken(scope: "Orchestrator", refresh: boolean): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
interface IRobotAgentProxy {
|
|
14
|
+
readonly interactiveConnectFlow: IInteractiveConnectFlow;
|
|
15
|
+
readonly accessProvider: IAccessProvider;
|
|
16
|
+
CloseAsync(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
interface RobotClientModule {
|
|
19
|
+
RobotProxyConstructor: new () => IRobotAgentProxy;
|
|
20
|
+
}
|
|
21
|
+
export interface RobotClientFallbackResult {
|
|
22
|
+
accessToken: string;
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
organizationName: string;
|
|
25
|
+
organizationId: string;
|
|
26
|
+
tenantName: string;
|
|
27
|
+
tenantId?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface RobotClientFallbackOptions {
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
/** Test seam: report whether the Robot IPC endpoint exists. */
|
|
32
|
+
isRobotIpcAvailable?: () => Promise<boolean>;
|
|
33
|
+
/** Test seam: provide a stubbed module loader. */
|
|
34
|
+
loadModule?: () => Promise<RobotClientModule | undefined>;
|
|
35
|
+
/**
|
|
36
|
+
* When true, skip the soft guards that protect the *default* fallback
|
|
37
|
+
* path: the `UIPATH_URL`-set short-circuit and the CI heuristic. Used by
|
|
38
|
+
* `UIPATH_CLI_ENFORCE_ROBOT_AUTH=true` callers who have explicitly opted
|
|
39
|
+
* into Robot-only auth and accept the IPC handshake cost. Browser is still
|
|
40
|
+
* skipped (no IPC there structurally).
|
|
41
|
+
*/
|
|
42
|
+
force?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read credentials from the running UiPath Robot/Assistant via its local IPC.
|
|
46
|
+
*
|
|
47
|
+
* Returns `undefined` — and falls back to the standard "Not logged in" path —
|
|
48
|
+
* when any of the following is true:
|
|
49
|
+
* - running in a browser
|
|
50
|
+
* - `UIPATH_URL` is set (explicit user override takes precedence) — unless
|
|
51
|
+
* `options.force === true`
|
|
52
|
+
* - the process looks like a CI runner (`CI`/`GITHUB_ACTIONS` set) — unless
|
|
53
|
+
* `options.force === true`
|
|
54
|
+
* - `@uipath/robot-client` is not installed or fails to load
|
|
55
|
+
* - Robot is not running, or sign-in is disabled
|
|
56
|
+
* - an IPC call exceeds the timeout
|
|
57
|
+
* - the returned resource URL or access token is malformed/empty
|
|
58
|
+
*
|
|
59
|
+
* Credentials returned by this function are ephemeral: the caller MUST NOT
|
|
60
|
+
* persist them to the auth file.
|
|
61
|
+
*/
|
|
62
|
+
export declare const tryRobotClientFallback: (options?: RobotClientFallbackOptions) => Promise<RobotClientFallbackResult | undefined>;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type TenantsAndOrganizations } from "./tenantSelection";
|
|
2
|
+
export type SelectFromList = (options: string[], message: string) => Promise<number>;
|
|
3
|
+
interface TenantSelectionDependencies {
|
|
4
|
+
fetchTenantsAndOrgs?: (baseUrl: string, accessToken: string, organizationId: string) => Promise<TenantsAndOrganizations>;
|
|
5
|
+
selectFromList?: SelectFromList;
|
|
6
|
+
}
|
|
7
|
+
export declare const selectTenantWithDeps: (baseUrl: string, accessToken: string, organizationId: string, targetTenantName?: string, interactive?: boolean, deps?: TenantSelectionDependencies) => Promise<[string, string, string]>;
|
|
8
|
+
export {};
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const AUTH_TIMEOUT_ERROR_CODE = "EAUTHTIMEOUT";
|
|
2
|
+
interface StartCallbackServerProps {
|
|
3
|
+
redirectUri: URL;
|
|
4
|
+
timeoutMs?: number;
|
|
5
|
+
onListening?: () => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export declare const startServer: ({ redirectUri, timeoutMs, onListening, }: StartCallbackServerProps) => Promise<URL>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface Tenant {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
interface Organization {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface TenantsAndOrganizations {
|
|
12
|
+
tenants: Tenant[];
|
|
13
|
+
organization: Organization;
|
|
14
|
+
}
|
|
15
|
+
/** Fetch tenants and organizations from UiPath Cloud. */
|
|
16
|
+
export declare const fetchTenantsAndOrganizations: (baseUrl: string, accessToken: string, organizationId: string) => Promise<TenantsAndOrganizations>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface ExchangeCodeForTokensProps {
|
|
2
|
+
code: string;
|
|
3
|
+
codeVerifier: string;
|
|
4
|
+
redirectUri: URL;
|
|
5
|
+
clientId: string;
|
|
6
|
+
clientSecret?: string;
|
|
7
|
+
tokenEndpoint: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const exchangeCodeForTokens: ({ code, codeVerifier, redirectUri, clientId, clientSecret, tokenEndpoint, }: ExchangeCodeForTokensProps) => Promise<{
|
|
10
|
+
accessToken: string;
|
|
11
|
+
refreshToken: string;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
interface RefreshTokenParams {
|
|
2
|
+
refreshToken: string;
|
|
3
|
+
tokenEndpoint: string;
|
|
4
|
+
clientId: string;
|
|
5
|
+
/**
|
|
6
|
+
* The authority that originally minted the token (e.g.
|
|
7
|
+
* `https://cloud.uipath.com`). When provided, the refreshed access
|
|
8
|
+
* token's `iss` claim is validated against `<authority>/identity_`
|
|
9
|
+
* to defend against a token endpoint that has been swapped or
|
|
10
|
+
* MITM'd between sessions to issue tokens from a foreign IdP.
|
|
11
|
+
*/
|
|
12
|
+
expectedAuthority?: string;
|
|
13
|
+
}
|
|
14
|
+
interface TokenResponse {
|
|
15
|
+
accessToken: string;
|
|
16
|
+
refreshToken: string;
|
|
17
|
+
}
|
|
18
|
+
export declare class TokenRefreshOAuthError extends Error {
|
|
19
|
+
readonly __brand = "TokenRefreshOAuthError";
|
|
20
|
+
constructor();
|
|
21
|
+
}
|
|
22
|
+
export declare function isTokenRefreshOAuthFailure(error: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Refresh an access token using a refresh token
|
|
25
|
+
*/
|
|
26
|
+
export declare const refreshAccessToken: ({ refreshToken, tokenEndpoint, clientId, expectedAuthority, }: RefreshTokenParams) => Promise<TokenResponse>;
|
|
27
|
+
export {};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export declare const DEFAULT_AUTH_FILENAME = ".auth";
|
|
2
|
+
export declare const DEFAULT_ENV_FILENAME = ".uipath/.auth";
|
|
3
|
+
interface LoadEnvFileProps {
|
|
4
|
+
envPath: string;
|
|
5
|
+
}
|
|
6
|
+
interface SaveEnvFileProps {
|
|
7
|
+
envPath: string;
|
|
8
|
+
data: Record<string, string | undefined>;
|
|
9
|
+
merge?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface ResolveEnvFilePathResult {
|
|
12
|
+
absolutePath: string | undefined;
|
|
13
|
+
errorMessage?: string;
|
|
14
|
+
}
|
|
15
|
+
export type EnvFileSource = "absolute" | "cwd" | "ancestor" | "home" | "default";
|
|
16
|
+
/**
|
|
17
|
+
* Why the candidate at {@link EnvFileLocation.absolutePath} is not a usable
|
|
18
|
+
* credentials file. Surfaced so callers can tell "file is missing" (run
|
|
19
|
+
* `uip login`) apart from "file exists but cannot be read" (fix permissions
|
|
20
|
+
* or unblock the path) — the older `exists: boolean` API silently collapsed
|
|
21
|
+
* both into `false` and made permission errors look like a fresh install.
|
|
22
|
+
*/
|
|
23
|
+
export type EnvFileUnusableReason =
|
|
24
|
+
/** stat() threw — typically EACCES, EPERM, ELOOP, broken symlink. */
|
|
25
|
+
"unreadable"
|
|
26
|
+
/** Path resolves to a directory, not a regular file. */
|
|
27
|
+
| "not-a-file";
|
|
28
|
+
/**
|
|
29
|
+
* Bounded set of `unusable.code` values the resolver can produce. Errno
|
|
30
|
+
* codes from filesystem rejections that fall outside this list are
|
|
31
|
+
* narrowed to `"EUNKNOWN"` rather than passed through verbatim — that
|
|
32
|
+
* keeps the public surface stable as new POSIX errnos appear.
|
|
33
|
+
*/
|
|
34
|
+
export type EnvFileErrorCode = "EISDIR" | "EACCES" | "EPERM" | "ELOOP" | "ENOTDIR" | "EUNKNOWN";
|
|
35
|
+
export interface EnvFileUnusable {
|
|
36
|
+
readonly reason: EnvFileUnusableReason;
|
|
37
|
+
readonly code: EnvFileErrorCode;
|
|
38
|
+
readonly message: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Discriminated on `exists`. The `exists: true` branch can never carry an
|
|
42
|
+
* `unusable` block, and `source: "default"` only appears on the
|
|
43
|
+
* `exists: false` branch — both invariants are codified in the type so a
|
|
44
|
+
* buggy producer cannot construct an impossible state.
|
|
45
|
+
*/
|
|
46
|
+
export type EnvFileLocation = {
|
|
47
|
+
readonly exists: true;
|
|
48
|
+
readonly absolutePath: string;
|
|
49
|
+
readonly source: Exclude<EnvFileSource, "default">;
|
|
50
|
+
} | {
|
|
51
|
+
readonly exists: false;
|
|
52
|
+
readonly absolutePath: string;
|
|
53
|
+
readonly source: EnvFileSource;
|
|
54
|
+
/**
|
|
55
|
+
* Set when the resolver picked this candidate but it is not a
|
|
56
|
+
* usable regular file. Absent when the file is simply missing
|
|
57
|
+
* (ENOENT). When set, `code`/`message` are the underlying
|
|
58
|
+
* filesystem error.
|
|
59
|
+
*/
|
|
60
|
+
readonly unusable?: EnvFileUnusable;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Locate the credentials file the CLI would use, without requiring it to
|
|
64
|
+
* exist. Search order: absolute path → walk up from cwd → ~/ fallback.
|
|
65
|
+
* Designed for tools that need to register watchers, cache keys, or status
|
|
66
|
+
* displays before the user has authenticated. Never reads file contents.
|
|
67
|
+
*
|
|
68
|
+
* Uses `fs.stat` (not `fs.exists`) so a candidate that exists but is
|
|
69
|
+
* unreadable (EACCES) or is a directory is reported with `exists: false`
|
|
70
|
+
* **and** an `unusable` block — callers can branch on `unusable.reason`
|
|
71
|
+
* to distinguish "fresh install" from "permissions broken".
|
|
72
|
+
*
|
|
73
|
+
* During cwd walk-up an unreadable/directory candidate is treated as
|
|
74
|
+
* "not found" and the search continues; only the final candidate (the
|
|
75
|
+
* one actually returned) carries the `unusable` block.
|
|
76
|
+
*/
|
|
77
|
+
export declare const resolveEnvFileLocationAsync: (envFilePath?: string) => Promise<EnvFileLocation>;
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the absolute path to an environment file, returning an
|
|
80
|
+
* `errorMessage` if no existing usable file was found. Delegates the
|
|
81
|
+
* search (absolute → cwd walk-up → ~/ fallback) and the regular-file
|
|
82
|
+
* check to {@link resolveEnvFileLocationAsync}; see there for full
|
|
83
|
+
* semantics including the unreadable-vs-missing distinction.
|
|
84
|
+
*
|
|
85
|
+
* @param envFilePath - Path to the credentials file (defaults to ".uipath/.auth")
|
|
86
|
+
*/
|
|
87
|
+
export declare const resolveEnvFilePathAsync: (envFilePath?: string) => Promise<ResolveEnvFilePathResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Load environment variables from a credentials file
|
|
90
|
+
* @param envPath - Path to the credentials file (relative to cwd or absolute)
|
|
91
|
+
* @returns Object with environment variables
|
|
92
|
+
*/
|
|
93
|
+
export declare const loadEnvFileAsync: ({ envPath }: LoadEnvFileProps) => Promise<Record<string, string>>;
|
|
94
|
+
/**
|
|
95
|
+
* Save environment variables to a credentials file atomically
|
|
96
|
+
* @param envPath - Path to the credentials file (relative to cwd or absolute)
|
|
97
|
+
* @param data - Object with environment variables to save
|
|
98
|
+
* @param merge - If true, merge with existing file, otherwise overwrite
|
|
99
|
+
*/
|
|
100
|
+
export declare const saveEnvFileAsync: ({ envPath, data, merge, }: SaveEnvFileProps) => Promise<void>;
|
|
101
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
interface JWTPayload {
|
|
2
|
+
exp: number;
|
|
3
|
+
iat: number;
|
|
4
|
+
iss?: string;
|
|
5
|
+
sub?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
preferred_username?: string;
|
|
8
|
+
email?: string;
|
|
9
|
+
first_name?: string;
|
|
10
|
+
last_name?: string;
|
|
11
|
+
prtId?: string;
|
|
12
|
+
organizationId?: string;
|
|
13
|
+
prt_id?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown when a token's `iss` claim does not identify the
|
|
18
|
+
* authority the CLI thought it was talking to. Defends against OIDC
|
|
19
|
+
* issuer mix-up (RFC 9207) and against silently accepting tokens from
|
|
20
|
+
* an unexpected identity server reached via misconfig or proxy.
|
|
21
|
+
*/
|
|
22
|
+
export declare class InvalidIssuerError extends Error {
|
|
23
|
+
readonly expected: string;
|
|
24
|
+
readonly actual: string | undefined;
|
|
25
|
+
constructor(expected: string, actual: string | undefined);
|
|
26
|
+
}
|
|
27
|
+
export declare const parseJWT: (token: string) => JWTPayload;
|
|
28
|
+
/**
|
|
29
|
+
* Verify that a token was issued by the authority the caller intends
|
|
30
|
+
* to trust. Throws {@link InvalidIssuerError} on mismatch, missing
|
|
31
|
+
* claim, or malformed token.
|
|
32
|
+
*
|
|
33
|
+
* UiPath identity servers emit `iss` as `<authority>/identity_` (e.g.
|
|
34
|
+
* authority `https://cloud.uipath.com` → `iss` `https://cloud.uipath.com/identity_`).
|
|
35
|
+
* Trailing slashes on either side are tolerated; everything else is strict.
|
|
36
|
+
*/
|
|
37
|
+
export declare const assertIssuerMatchesAuthority: (token: string, authority: string) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Extract the expiration date from a JWT access token.
|
|
40
|
+
* Returns undefined if the token is malformed or has no exp claim.
|
|
41
|
+
*/
|
|
42
|
+
export declare const getTokenExpiration: (accessToken: string) => Date | undefined;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform detection utilities with proper type guards
|
|
3
|
+
* Use these instead of @ts-expect-error suppressions
|
|
4
|
+
*/
|
|
5
|
+
interface BrowserWindow {
|
|
6
|
+
document?: unknown;
|
|
7
|
+
screen?: {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
11
|
+
location?: {
|
|
12
|
+
origin: string;
|
|
13
|
+
};
|
|
14
|
+
open?: (url: string, target: string, features: string) => unknown;
|
|
15
|
+
addEventListener?: (event: string, handler: (event: unknown) => void) => void;
|
|
16
|
+
removeEventListener?: (event: string, handler: (event: unknown) => void) => void;
|
|
17
|
+
}
|
|
18
|
+
interface BrowserDocument {
|
|
19
|
+
createElement?: (tag: string) => unknown;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Check if code is running in a browser environment
|
|
23
|
+
*/
|
|
24
|
+
export declare function isBrowser(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if code is running in Node.js environment
|
|
27
|
+
*/
|
|
28
|
+
export declare function isNode(): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Get the global object safely
|
|
31
|
+
*/
|
|
32
|
+
export declare function getGlobalThis(): (typeof globalThis & {
|
|
33
|
+
window?: BrowserWindow;
|
|
34
|
+
document?: BrowserDocument;
|
|
35
|
+
}) | undefined;
|
|
36
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,46 +1,41 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
"name": "@uipath/auth",
|
|
3
|
+
"license": "MIT",
|
|
4
|
+
"version": "1.195.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/UiPath/cli.git",
|
|
8
|
+
"directory": "packages/auth"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"registry": "https://registry.npmjs.org/"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"browser": {
|
|
19
|
+
"types": "./dist/index.browser.d.ts",
|
|
20
|
+
"default": "./dist/index.browser.js"
|
|
21
|
+
},
|
|
22
|
+
"default": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"default": "./dist/index.js"
|
|
25
|
+
}
|
|
8
26
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
"./browser": {
|
|
26
|
-
"types": "./dist/index.browser.d.ts",
|
|
27
|
-
"default": "./dist/index.browser.js"
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
"files": [
|
|
31
|
-
"dist"
|
|
32
|
-
],
|
|
33
|
-
"maintainers": [
|
|
34
|
-
"aoltean16",
|
|
35
|
-
"mihaigirleanu",
|
|
36
|
-
"vlad-uipath"
|
|
37
|
-
],
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"@types/node": "^25.5.2",
|
|
40
|
-
"@uipath/filesystem": "1.1.0",
|
|
41
|
-
"@uipath/robot-client": "26.0.193-alpha22964",
|
|
42
|
-
"openid-client": "^6.8.2",
|
|
43
|
-
"typescript": "^6.0.2"
|
|
44
|
-
},
|
|
45
|
-
"gitHead": "06e8c8f566df4b87da4a008635483c62f64f33f0"
|
|
27
|
+
"./browser": {
|
|
28
|
+
"types": "./dist/index.browser.d.ts",
|
|
29
|
+
"default": "./dist/index.browser.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"maintainers": [
|
|
36
|
+
"aoltean16",
|
|
37
|
+
"mihaigirleanu",
|
|
38
|
+
"vlad-uipath"
|
|
39
|
+
],
|
|
40
|
+
"gitHead": "65fabb84552758b2710d8ca68470e70a9b1d19bc"
|
|
46
41
|
}
|