@vercel/cli-auth 0.1.0 → 0.2.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/credentials-store.d.ts +13 -43
- package/credentials-store.js +16 -358
- package/credentials-store.js.map +1 -1
- package/credentials-store.ts +16 -494
- package/package.json +1 -3
package/credentials-store.d.ts
CHANGED
|
@@ -1,59 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
readonly FILE: "file";
|
|
4
|
-
readonly KEYRING: "keyring";
|
|
5
|
-
};
|
|
6
|
-
type KeyringEntry = {
|
|
7
|
-
getPassword(): string | null;
|
|
8
|
-
setPassword(password: string): void;
|
|
9
|
-
deleteCredential(): boolean;
|
|
10
|
-
};
|
|
11
|
-
type KeyringEntryConstructor = new (service: string, account: string) => KeyringEntry;
|
|
12
|
-
type LoadKeyringModule = () => {
|
|
13
|
-
Entry: KeyringEntryConstructor;
|
|
14
|
-
};
|
|
15
|
-
export type AuthTokenStorage = (typeof AUTH_TOKEN_STORAGE)[keyof typeof AUTH_TOKEN_STORAGE];
|
|
16
|
-
export type CredentialsStorageLocation = Exclude<AuthTokenStorage, (typeof AUTH_TOKEN_STORAGE)['AUTO']>;
|
|
17
|
-
export interface GlobalConfig {
|
|
18
|
-
authTokenStorage?: AuthTokenStorage;
|
|
19
|
-
}
|
|
20
|
-
export interface Credentials {
|
|
1
|
+
import { z } from 'zod/mini';
|
|
2
|
+
declare const Credentials: z.ZodMiniObject<{
|
|
21
3
|
/** An `access_token` obtained using the OAuth Device Authorization flow. */
|
|
22
|
-
token
|
|
4
|
+
token: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
23
5
|
/** A `refresh_token` obtained using the OAuth Device Authorization flow. */
|
|
24
|
-
refreshToken
|
|
6
|
+
refreshToken: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
25
7
|
/**
|
|
26
8
|
* The absolute time (seconds) when the {@link Credentials.token} expires.
|
|
27
9
|
* Used to optimistically check if the token is still valid.
|
|
28
10
|
*/
|
|
29
|
-
expiresAt
|
|
11
|
+
expiresAt: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
30
12
|
/** Whether to skip writing the credentials to disk during {@link CredentialsStore.update} */
|
|
31
|
-
skipWrite
|
|
32
|
-
'// Note'
|
|
33
|
-
'// Docs'
|
|
34
|
-
}
|
|
35
|
-
export
|
|
36
|
-
export declare function resolveAuthTokenStorage(value: unknown): AuthTokenStorage;
|
|
13
|
+
skipWrite: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
|
|
14
|
+
'// Note': z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
15
|
+
'// Docs': z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export type Credentials = z.infer<typeof Credentials>;
|
|
37
18
|
/**
|
|
38
19
|
* Returns in which directory the config should be present
|
|
39
20
|
* @internal Should only be used in {@link CredentialsStore} or tests.
|
|
40
21
|
*/
|
|
41
|
-
export declare function getGlobalPathConfig(
|
|
42
|
-
export declare function
|
|
43
|
-
export declare function getAuthConfigFilePath(dir: string): string;
|
|
44
|
-
export declare function readGlobalConfig(dir: string): GlobalConfig;
|
|
45
|
-
export declare function getAuthTokenStorage(dir: string, config?: GlobalConfig): AuthTokenStorage;
|
|
46
|
-
export declare function setLoadKeyringModuleForTesting(nextLoadKeyringModule?: LoadKeyringModule): void;
|
|
47
|
-
export declare function CredentialsStore(dir: string, config?: GlobalConfig): {
|
|
22
|
+
export declare function getGlobalPathConfig(dir: string): string;
|
|
23
|
+
export declare function CredentialsStore(dir: string): {
|
|
48
24
|
configPath: string;
|
|
49
25
|
get(): Credentials;
|
|
50
26
|
/** Update the credentials store. If `skipWrite` is set, the update will be skipped. */
|
|
51
|
-
update(config: Partial<Credentials>):
|
|
52
|
-
delete(): void;
|
|
27
|
+
update(config: Partial<Credentials>): void;
|
|
53
28
|
};
|
|
54
|
-
export declare function readCredentials(dir: string, config?: GlobalConfig): Credentials;
|
|
55
|
-
export declare function writeCredentials(dir: string, credentials: Partial<Credentials>, config?: GlobalConfig): void | CredentialsStorageLocation;
|
|
56
|
-
export declare function clearCredentials(dir: string, config?: GlobalConfig): void;
|
|
57
|
-
export declare function clearAllCredentials(dir: string): void;
|
|
58
|
-
export declare function clearAllCredentialsStrict(dir: string): void;
|
|
59
29
|
export {};
|
package/credentials-store.js
CHANGED
|
@@ -36,78 +36,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.hasCredentials = hasCredentials;
|
|
40
|
-
exports.resolveAuthTokenStorage = resolveAuthTokenStorage;
|
|
41
39
|
exports.getGlobalPathConfig = getGlobalPathConfig;
|
|
42
|
-
exports.getConfigFilePath = getConfigFilePath;
|
|
43
|
-
exports.getAuthConfigFilePath = getAuthConfigFilePath;
|
|
44
|
-
exports.readGlobalConfig = readGlobalConfig;
|
|
45
|
-
exports.getAuthTokenStorage = getAuthTokenStorage;
|
|
46
|
-
exports.setLoadKeyringModuleForTesting = setLoadKeyringModuleForTesting;
|
|
47
40
|
exports.CredentialsStore = CredentialsStore;
|
|
48
|
-
exports.readCredentials = readCredentials;
|
|
49
|
-
exports.writeCredentials = writeCredentials;
|
|
50
|
-
exports.clearCredentials = clearCredentials;
|
|
51
|
-
exports.clearAllCredentials = clearAllCredentials;
|
|
52
|
-
exports.clearAllCredentialsStrict = clearAllCredentialsStrict;
|
|
53
41
|
const node_path_1 = __importDefault(require("node:path"));
|
|
54
|
-
const node_crypto_1 = require("node:crypto");
|
|
55
42
|
const fs = __importStar(require("node:fs"));
|
|
56
43
|
const node_os_1 = require("node:os");
|
|
57
44
|
// NOTE: We are pinned on v5 because newer versions behave differently
|
|
58
45
|
// when there are dots in the application name, eg. `com.vercel.cli` becomes `com.vercel`
|
|
59
46
|
const xdg_app_paths_1 = __importDefault(require("xdg-app-paths"));
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
const AUTH_TOKEN_STORAGE = {
|
|
63
|
-
AUTO: 'auto',
|
|
64
|
-
FILE: 'file',
|
|
65
|
-
KEYRING: 'keyring',
|
|
66
|
-
};
|
|
67
|
-
const AUTH_TOKEN_STORAGE_VALUES = Object.values(AUTH_TOKEN_STORAGE);
|
|
68
|
-
const DEFAULT_AUTH_TOKEN_STORAGE = AUTH_TOKEN_STORAGE.FILE;
|
|
69
|
-
const KEYRING_SERVICE = 'Vercel Auth';
|
|
70
|
-
const KEYRING_UNAVAILABLE_ERROR = 'OS keyring support is unavailable. Set `authTokenStorage` to `auto` or `file` to store credentials in auth.json instead.';
|
|
71
|
-
const defaultLoadKeyringModule = () => require('@napi-rs/keyring');
|
|
72
|
-
let loadKeyringModule = defaultLoadKeyringModule;
|
|
73
|
-
const CredentialsSchema = z.object({
|
|
47
|
+
const mini_1 = require("zod/mini");
|
|
48
|
+
const Credentials = mini_1.z.object({
|
|
74
49
|
/** An `access_token` obtained using the OAuth Device Authorization flow. */
|
|
75
|
-
token: z.optional(z.string()),
|
|
76
|
-
/** The ID of the currently authenticated user, cached from `/v2/user`. */
|
|
77
|
-
userId: z.optional(z.string()),
|
|
50
|
+
token: mini_1.z.optional(mini_1.z.string()),
|
|
78
51
|
/** A `refresh_token` obtained using the OAuth Device Authorization flow. */
|
|
79
|
-
refreshToken: z.optional(z.string()),
|
|
52
|
+
refreshToken: mini_1.z.optional(mini_1.z.string()),
|
|
80
53
|
/**
|
|
81
54
|
* The absolute time (seconds) when the {@link Credentials.token} expires.
|
|
82
55
|
* Used to optimistically check if the token is still valid.
|
|
83
56
|
*/
|
|
84
|
-
expiresAt: z.optional(z.number()),
|
|
57
|
+
expiresAt: mini_1.z.optional(mini_1.z.number()),
|
|
85
58
|
/** Whether to skip writing the credentials to disk during {@link CredentialsStore.update} */
|
|
86
|
-
skipWrite: z.optional(z.boolean()),
|
|
87
|
-
'// Note': z.optional(z.string()),
|
|
88
|
-
'// Docs': z.optional(z.string()),
|
|
59
|
+
skipWrite: mini_1.z.optional(mini_1.z.boolean()),
|
|
60
|
+
'// Note': mini_1.z.optional(mini_1.z.string()),
|
|
61
|
+
'// Docs': mini_1.z.optional(mini_1.z.string()),
|
|
89
62
|
});
|
|
90
|
-
function hasCredentials(credentials) {
|
|
91
|
-
return Boolean(credentials.token ||
|
|
92
|
-
credentials.refreshToken ||
|
|
93
|
-
typeof credentials.expiresAt === 'number');
|
|
94
|
-
}
|
|
95
|
-
function parseCredentials(value) {
|
|
96
|
-
return CredentialsSchema.parse(value);
|
|
97
|
-
}
|
|
98
|
-
function isAuthTokenStorage(value) {
|
|
99
|
-
return (typeof value === 'string' &&
|
|
100
|
-
AUTH_TOKEN_STORAGE_VALUES.some(storage => storage === value));
|
|
101
|
-
}
|
|
102
|
-
function resolveAuthTokenStorage(value) {
|
|
103
|
-
if (typeof value === 'undefined') {
|
|
104
|
-
return DEFAULT_AUTH_TOKEN_STORAGE;
|
|
105
|
-
}
|
|
106
|
-
if (isAuthTokenStorage(value)) {
|
|
107
|
-
return value;
|
|
108
|
-
}
|
|
109
|
-
throw new Error(`Invalid value for \`authTokenStorage\`: ${JSON.stringify(value)}. Expected one of: ${AUTH_TOKEN_STORAGE_VALUES.map(storage => JSON.stringify(storage)).join(', ')}.`);
|
|
110
|
-
}
|
|
111
63
|
/** Returns whether a directory exists */
|
|
112
64
|
function isDirectory(path) {
|
|
113
65
|
try {
|
|
@@ -122,8 +74,8 @@ function isDirectory(path) {
|
|
|
122
74
|
* Returns in which directory the config should be present
|
|
123
75
|
* @internal Should only be used in {@link CredentialsStore} or tests.
|
|
124
76
|
*/
|
|
125
|
-
function getGlobalPathConfig(
|
|
126
|
-
const vercelDirectories = (0, xdg_app_paths_1.default)(
|
|
77
|
+
function getGlobalPathConfig(dir) {
|
|
78
|
+
const vercelDirectories = (0, xdg_app_paths_1.default)(dir).dataDirs();
|
|
127
79
|
const possibleConfigPaths = [
|
|
128
80
|
...vercelDirectories, // latest vercel directory
|
|
129
81
|
node_path_1.default.join((0, node_os_1.homedir)(), '.now'), // legacy config in user's home directory
|
|
@@ -136,315 +88,21 @@ function getGlobalPathConfig(appName) {
|
|
|
136
88
|
return (possibleConfigPaths.find(configPath => isDirectory(configPath)) ||
|
|
137
89
|
vercelDirectories[0]);
|
|
138
90
|
}
|
|
139
|
-
function
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
function getAuthConfigFilePath(dir) {
|
|
143
|
-
return node_path_1.default.join(dir, 'auth.json');
|
|
144
|
-
}
|
|
145
|
-
function readGlobalConfig(dir) {
|
|
146
|
-
const configPath = getConfigFilePath(dir);
|
|
147
|
-
let config;
|
|
148
|
-
try {
|
|
149
|
-
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
if (isENOENTError(error)) {
|
|
153
|
-
return {};
|
|
154
|
-
}
|
|
155
|
-
throw error;
|
|
156
|
-
}
|
|
157
|
-
return {
|
|
158
|
-
authTokenStorage: typeof config.authTokenStorage === 'undefined'
|
|
159
|
-
? undefined
|
|
160
|
-
: resolveAuthTokenStorage(config.authTokenStorage),
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
function getAuthTokenStorage(dir, config) {
|
|
164
|
-
if (config?.authTokenStorage) {
|
|
165
|
-
return resolveAuthTokenStorage(config.authTokenStorage);
|
|
166
|
-
}
|
|
167
|
-
return resolveAuthTokenStorage(readGlobalConfig(dir).authTokenStorage);
|
|
168
|
-
}
|
|
169
|
-
function getKeyringAccount(configPath) {
|
|
170
|
-
const digest = (0, node_crypto_1.createHash)('sha256').update(configPath).digest('hex');
|
|
171
|
-
return `cli:${digest.slice(0, 16)}`;
|
|
172
|
-
}
|
|
173
|
-
function setLoadKeyringModuleForTesting(nextLoadKeyringModule) {
|
|
174
|
-
loadKeyringModule = nextLoadKeyringModule ?? defaultLoadKeyringModule;
|
|
175
|
-
}
|
|
176
|
-
function createKeyringEntry(configPath) {
|
|
177
|
-
try {
|
|
178
|
-
const { Entry } = loadKeyringModule();
|
|
179
|
-
return new Entry(KEYRING_SERVICE, getKeyringAccount(configPath));
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
const wrappedError = new Error(KEYRING_UNAVAILABLE_ERROR);
|
|
183
|
-
wrappedError.cause = error;
|
|
184
|
-
throw wrappedError;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
function isKeyringUnavailableError(error) {
|
|
188
|
-
return error instanceof Error && error.message === KEYRING_UNAVAILABLE_ERROR;
|
|
189
|
-
}
|
|
190
|
-
function readCredentialsFromFile(configPath) {
|
|
191
|
-
return parseCredentials(JSON.parse(fs.readFileSync(configPath, 'utf8')));
|
|
192
|
-
}
|
|
193
|
-
function isENOENTError(error) {
|
|
194
|
-
return (typeof error === 'object' &&
|
|
195
|
-
error !== null &&
|
|
196
|
-
'code' in error &&
|
|
197
|
-
error.code === 'ENOENT');
|
|
198
|
-
}
|
|
199
|
-
function createMissingCredentialsError(configPath) {
|
|
200
|
-
const error = new Error(`ENOENT: no such file or directory, open '${configPath}'`);
|
|
201
|
-
Object.assign(error, { code: 'ENOENT' });
|
|
202
|
-
return error;
|
|
203
|
-
}
|
|
204
|
-
function writeCredentialsToFile(configPath, config) {
|
|
205
|
-
const directory = node_path_1.default.dirname(configPath);
|
|
206
|
-
const temporaryPath = node_path_1.default.join(directory, `${node_path_1.default.basename(configPath)}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`);
|
|
207
|
-
fs.mkdirSync(node_path_1.default.dirname(configPath), { recursive: true });
|
|
208
|
-
try {
|
|
209
|
-
fs.writeFileSync(temporaryPath, JSON.stringify(config, null, 2) + '\n', {
|
|
210
|
-
mode: 0o600,
|
|
211
|
-
});
|
|
212
|
-
fs.renameSync(temporaryPath, configPath);
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
fs.rmSync(temporaryPath, { force: true });
|
|
216
|
-
throw error;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
function readCredentialsFromKeyring(configPath) {
|
|
220
|
-
const entry = createKeyringEntry(configPath);
|
|
221
|
-
const value = entry.getPassword();
|
|
222
|
-
if (value === null) {
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
return parseCredentials(JSON.parse(value));
|
|
226
|
-
}
|
|
227
|
-
function writeCredentialsToKeyring(configPath, config) {
|
|
228
|
-
const entry = createKeyringEntry(configPath);
|
|
229
|
-
entry.setPassword(JSON.stringify(config));
|
|
230
|
-
}
|
|
231
|
-
function deleteCredentialsFromKeyring(configPath) {
|
|
232
|
-
const entry = createKeyringEntry(configPath);
|
|
233
|
-
return entry.deleteCredential();
|
|
234
|
-
}
|
|
235
|
-
function deleteCredentialsFile(configPath) {
|
|
236
|
-
fs.rmSync(configPath, { force: true });
|
|
237
|
-
}
|
|
238
|
-
function tryDeleteCredentialsFromKeyring(configPath) {
|
|
239
|
-
try {
|
|
240
|
-
deleteCredentialsFromKeyring(configPath);
|
|
241
|
-
}
|
|
242
|
-
catch { }
|
|
243
|
-
}
|
|
244
|
-
function deleteCredentialsFromKeyringIfAvailable(configPath) {
|
|
245
|
-
try {
|
|
246
|
-
deleteCredentialsFromKeyring(configPath);
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
if (!isKeyringUnavailableError(error)) {
|
|
250
|
-
throw error;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
function migrateCredentialsToFile(configPath, credentials) {
|
|
255
|
-
writeCredentialsToFile(configPath, credentials);
|
|
256
|
-
tryDeleteCredentialsFromKeyring(configPath);
|
|
257
|
-
return credentials;
|
|
258
|
-
}
|
|
259
|
-
function tryReadKeyringCredentialsIntoFile(configPath) {
|
|
260
|
-
try {
|
|
261
|
-
const credentials = readCredentialsFromKeyring(configPath);
|
|
262
|
-
if (credentials === null) {
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
return migrateCredentialsToFile(configPath, credentials);
|
|
266
|
-
}
|
|
267
|
-
catch {
|
|
268
|
-
return null;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
function readFileStorageCredentials(configPath) {
|
|
272
|
-
try {
|
|
273
|
-
const credentials = readCredentialsFromFile(configPath);
|
|
274
|
-
if (hasCredentials(credentials)) {
|
|
275
|
-
return credentials;
|
|
276
|
-
}
|
|
277
|
-
// File mode treats keyring contents as stale-but-authoritative backup only
|
|
278
|
-
// when auth.json has no usable credentials.
|
|
279
|
-
return tryReadKeyringCredentialsIntoFile(configPath) ?? credentials;
|
|
280
|
-
}
|
|
281
|
-
catch (error) {
|
|
282
|
-
if (!isENOENTError(error)) {
|
|
283
|
-
throw error;
|
|
284
|
-
}
|
|
285
|
-
const credentials = tryReadKeyringCredentialsIntoFile(configPath);
|
|
286
|
-
if (credentials !== null) {
|
|
287
|
-
return credentials;
|
|
288
|
-
}
|
|
289
|
-
throw error;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
function migrateCredentialsToKeyring(configPath, credentials) {
|
|
293
|
-
writeCredentialsToKeyring(configPath, credentials);
|
|
294
|
-
deleteCredentialsFile(configPath);
|
|
295
|
-
return credentials;
|
|
296
|
-
}
|
|
297
|
-
function readKeyringStorageCredentials(configPath) {
|
|
298
|
-
const credentials = readCredentialsFromKeyring(configPath);
|
|
299
|
-
if (credentials !== null) {
|
|
300
|
-
return credentials;
|
|
301
|
-
}
|
|
302
|
-
try {
|
|
303
|
-
const fileCredentials = readCredentialsFromFile(configPath);
|
|
304
|
-
// Keyring mode eagerly migrates any remaining plaintext credentials out of
|
|
305
|
-
// auth.json after the first successful read.
|
|
306
|
-
return migrateCredentialsToKeyring(configPath, fileCredentials);
|
|
307
|
-
}
|
|
308
|
-
catch (error) {
|
|
309
|
-
if (isENOENTError(error)) {
|
|
310
|
-
throw createMissingCredentialsError(configPath);
|
|
311
|
-
}
|
|
312
|
-
throw error;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
function readAutoStorageCredentials(configPath) {
|
|
316
|
-
try {
|
|
317
|
-
const credentials = readCredentialsFromKeyring(configPath);
|
|
318
|
-
if (credentials !== null) {
|
|
319
|
-
return credentials;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
catch { }
|
|
323
|
-
// Auto mode intentionally avoids read-time migration so that machines
|
|
324
|
-
// without usable keyring support can keep working off auth.json.
|
|
325
|
-
return readCredentialsFromFile(configPath);
|
|
326
|
-
}
|
|
327
|
-
function writeFileStorageCredentials(configPath, credentials) {
|
|
328
|
-
writeCredentialsToFile(configPath, credentials);
|
|
329
|
-
tryDeleteCredentialsFromKeyring(configPath);
|
|
330
|
-
return 'file';
|
|
331
|
-
}
|
|
332
|
-
function writeKeyringStorageCredentials(configPath, credentials) {
|
|
333
|
-
writeCredentialsToKeyring(configPath, credentials);
|
|
334
|
-
deleteCredentialsFile(configPath);
|
|
335
|
-
return 'keyring';
|
|
336
|
-
}
|
|
337
|
-
function writeAutoStorageCredentials(configPath, credentials) {
|
|
338
|
-
try {
|
|
339
|
-
return writeKeyringStorageCredentials(configPath, credentials);
|
|
340
|
-
}
|
|
341
|
-
catch {
|
|
342
|
-
tryDeleteCredentialsFromKeyring(configPath);
|
|
343
|
-
return writeFileStorageCredentials(configPath, credentials);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
function deleteFileStorageCredentials(configPath) {
|
|
347
|
-
deleteCredentialsFile(configPath);
|
|
348
|
-
deleteCredentialsFromKeyringIfAvailable(configPath);
|
|
349
|
-
}
|
|
350
|
-
function deleteKeyringStorageCredentials(configPath) {
|
|
351
|
-
deleteCredentialsFromKeyring(configPath);
|
|
352
|
-
deleteCredentialsFile(configPath);
|
|
353
|
-
}
|
|
354
|
-
function deleteAutoStorageCredentials(configPath) {
|
|
355
|
-
try {
|
|
356
|
-
deleteCredentialsFromKeyring(configPath);
|
|
357
|
-
}
|
|
358
|
-
catch { }
|
|
359
|
-
deleteCredentialsFile(configPath);
|
|
360
|
-
}
|
|
361
|
-
function CredentialsStore(dir, config = {}) {
|
|
362
|
-
const configPath = getAuthConfigFilePath(dir);
|
|
363
|
-
const tokenStorage = getAuthTokenStorage(dir, config);
|
|
91
|
+
function CredentialsStore(dir) {
|
|
92
|
+
const configPath = node_path_1.default.join(getGlobalPathConfig(dir), 'auth.json');
|
|
364
93
|
return {
|
|
365
94
|
configPath,
|
|
366
95
|
get() {
|
|
367
|
-
|
|
368
|
-
case AUTH_TOKEN_STORAGE.FILE:
|
|
369
|
-
return readFileStorageCredentials(configPath);
|
|
370
|
-
case AUTH_TOKEN_STORAGE.KEYRING:
|
|
371
|
-
return readKeyringStorageCredentials(configPath);
|
|
372
|
-
case AUTH_TOKEN_STORAGE.AUTO:
|
|
373
|
-
return readAutoStorageCredentials(configPath);
|
|
374
|
-
}
|
|
96
|
+
return Credentials.parse(JSON.parse(fs.readFileSync(configPath, 'utf8')));
|
|
375
97
|
},
|
|
376
98
|
/** Update the credentials store. If `skipWrite` is set, the update will be skipped. */
|
|
377
99
|
update(config) {
|
|
378
100
|
if (config.skipWrite)
|
|
379
101
|
return;
|
|
380
|
-
const parsedConfig =
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
return writeFileStorageCredentials(configPath, parsedConfig);
|
|
384
|
-
case AUTH_TOKEN_STORAGE.KEYRING:
|
|
385
|
-
return writeKeyringStorageCredentials(configPath, parsedConfig);
|
|
386
|
-
case AUTH_TOKEN_STORAGE.AUTO:
|
|
387
|
-
return writeAutoStorageCredentials(configPath, parsedConfig);
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
delete() {
|
|
391
|
-
switch (tokenStorage) {
|
|
392
|
-
case AUTH_TOKEN_STORAGE.FILE:
|
|
393
|
-
deleteFileStorageCredentials(configPath);
|
|
394
|
-
break;
|
|
395
|
-
case AUTH_TOKEN_STORAGE.KEYRING:
|
|
396
|
-
deleteKeyringStorageCredentials(configPath);
|
|
397
|
-
break;
|
|
398
|
-
case AUTH_TOKEN_STORAGE.AUTO:
|
|
399
|
-
deleteAutoStorageCredentials(configPath);
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
102
|
+
const parsedConfig = Credentials.parse(config);
|
|
103
|
+
fs.mkdirSync(node_path_1.default.dirname(configPath), { recursive: true });
|
|
104
|
+
fs.writeFileSync(configPath, JSON.stringify(parsedConfig, null, 2) + '\n', { mode: 0o600 });
|
|
402
105
|
},
|
|
403
106
|
};
|
|
404
107
|
}
|
|
405
|
-
function readCredentials(dir, config = {}) {
|
|
406
|
-
return CredentialsStore(dir, config).get();
|
|
407
|
-
}
|
|
408
|
-
function writeCredentials(dir, credentials, config = {}) {
|
|
409
|
-
return CredentialsStore(dir, config).update(credentials);
|
|
410
|
-
}
|
|
411
|
-
function clearCredentials(dir, config = {}) {
|
|
412
|
-
CredentialsStore(dir, config).delete();
|
|
413
|
-
}
|
|
414
|
-
function clearAllCredentials(dir) {
|
|
415
|
-
for (const authTokenStorage of [
|
|
416
|
-
AUTH_TOKEN_STORAGE.FILE,
|
|
417
|
-
AUTH_TOKEN_STORAGE.KEYRING,
|
|
418
|
-
]) {
|
|
419
|
-
try {
|
|
420
|
-
clearCredentials(dir, { authTokenStorage });
|
|
421
|
-
}
|
|
422
|
-
catch { }
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
function clearAllCredentialsStrict(dir) {
|
|
426
|
-
const configPath = getAuthConfigFilePath(dir);
|
|
427
|
-
let fileError;
|
|
428
|
-
let keyringError;
|
|
429
|
-
try {
|
|
430
|
-
deleteCredentialsFile(configPath);
|
|
431
|
-
}
|
|
432
|
-
catch (error) {
|
|
433
|
-
fileError = error;
|
|
434
|
-
}
|
|
435
|
-
try {
|
|
436
|
-
deleteCredentialsFromKeyring(configPath);
|
|
437
|
-
}
|
|
438
|
-
catch (error) {
|
|
439
|
-
if (!isKeyringUnavailableError(error)) {
|
|
440
|
-
keyringError = error;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
if (keyringError) {
|
|
444
|
-
throw keyringError;
|
|
445
|
-
}
|
|
446
|
-
if (fileError) {
|
|
447
|
-
throw fileError;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
108
|
//# sourceMappingURL=credentials-store.js.map
|
package/credentials-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials-store.js","sourceRoot":"","sources":["credentials-store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"credentials-store.js","sourceRoot":"","sources":["credentials-store.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,kDAiBC;AAED,4CAmBC;AA9ED,0DAA6B;AAC7B,4CAA8B;AAC9B,qCAAkC;AAClC,sEAAsE;AACtE,yFAAyF;AACzF,kEAAwC;AACxC,mCAA6B;AAE7B,MAAM,WAAW,GAAG,QAAC,CAAC,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,KAAK,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,4EAA4E;IAC5E,YAAY,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IACpC;;;OAGG;IACH,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IACjC,6FAA6F;IAC7F,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,OAAO,EAAE,CAAC;IAClC,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IACjC,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;CAClC,CAAC,CAAC;AAIH,yCAAyC;AACzC,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0EAA0E;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,GAAW;IAC7C,MAAM,iBAAiB,GAAG,IAAA,uBAAW,EAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEtD,MAAM,mBAAmB,GAAG;QAC1B,GAAG,iBAAiB,EAAE,0BAA0B;QAChD,mBAAI,CAAC,IAAI,CAAC,IAAA,iBAAO,GAAE,EAAE,MAAM,CAAC,EAAE,yCAAyC;QACvE,GAAG,IAAA,uBAAW,EAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,uBAAuB;KAC1D,CAAC;IAEF,iDAAiD;IACjD,oCAAoC;IACpC,iCAAiC;IACjC,oDAAoD;IACpD,OAAO,CACL,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC/D,iBAAiB,CAAC,CAAC,CAAC,CACrB,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC;IACpE,OAAO;QACL,UAAU;QACV,GAAG;YACD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,uFAAuF;QACvF,MAAM,CAAC,MAA4B;YACjC,IAAI,MAAM,CAAC,SAAS;gBAAE,OAAO;YAC7B,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC/C,EAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,EAAE,CAAC,aAAa,CACd,UAAU,EACV,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAC5C,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/credentials-store.ts
CHANGED
|
@@ -1,63 +1,14 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { createHash, randomUUID } from 'node:crypto';
|
|
3
2
|
import * as fs from 'node:fs';
|
|
4
3
|
import { homedir } from 'node:os';
|
|
5
4
|
// NOTE: We are pinned on v5 because newer versions behave differently
|
|
6
5
|
// when there are dots in the application name, eg. `com.vercel.cli` becomes `com.vercel`
|
|
7
6
|
import XDGAppPaths from 'xdg-app-paths';
|
|
7
|
+
import { z } from 'zod/mini';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
const { z } = require('zod/mini') as { z: any };
|
|
11
|
-
|
|
12
|
-
const AUTH_TOKEN_STORAGE = {
|
|
13
|
-
AUTO: 'auto',
|
|
14
|
-
FILE: 'file',
|
|
15
|
-
KEYRING: 'keyring',
|
|
16
|
-
} as const;
|
|
17
|
-
const AUTH_TOKEN_STORAGE_VALUES = Object.values(AUTH_TOKEN_STORAGE);
|
|
18
|
-
const DEFAULT_AUTH_TOKEN_STORAGE = AUTH_TOKEN_STORAGE.FILE;
|
|
19
|
-
const KEYRING_SERVICE = 'Vercel Auth';
|
|
20
|
-
const KEYRING_UNAVAILABLE_ERROR =
|
|
21
|
-
'OS keyring support is unavailable. Set `authTokenStorage` to `auto` or `file` to store credentials in auth.json instead.';
|
|
22
|
-
|
|
23
|
-
type KeyringEntry = {
|
|
24
|
-
getPassword(): string | null;
|
|
25
|
-
setPassword(password: string): void;
|
|
26
|
-
deleteCredential(): boolean;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
type KeyringEntryConstructor = new (
|
|
30
|
-
service: string,
|
|
31
|
-
account: string
|
|
32
|
-
) => KeyringEntry;
|
|
33
|
-
|
|
34
|
-
type LoadKeyringModule = () => {
|
|
35
|
-
Entry: KeyringEntryConstructor;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const defaultLoadKeyringModule: LoadKeyringModule = () =>
|
|
39
|
-
require('@napi-rs/keyring') as {
|
|
40
|
-
Entry: KeyringEntryConstructor;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
let loadKeyringModule = defaultLoadKeyringModule;
|
|
44
|
-
|
|
45
|
-
export type AuthTokenStorage =
|
|
46
|
-
(typeof AUTH_TOKEN_STORAGE)[keyof typeof AUTH_TOKEN_STORAGE];
|
|
47
|
-
export type CredentialsStorageLocation = Exclude<
|
|
48
|
-
AuthTokenStorage,
|
|
49
|
-
(typeof AUTH_TOKEN_STORAGE)['AUTO']
|
|
50
|
-
>;
|
|
51
|
-
|
|
52
|
-
export interface GlobalConfig {
|
|
53
|
-
authTokenStorage?: AuthTokenStorage;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const CredentialsSchema = z.object({
|
|
9
|
+
const Credentials = z.object({
|
|
57
10
|
/** An `access_token` obtained using the OAuth Device Authorization flow. */
|
|
58
11
|
token: z.optional(z.string()),
|
|
59
|
-
/** The ID of the currently authenticated user, cached from `/v2/user`. */
|
|
60
|
-
userId: z.optional(z.string()),
|
|
61
12
|
/** A `refresh_token` obtained using the OAuth Device Authorization flow. */
|
|
62
13
|
refreshToken: z.optional(z.string()),
|
|
63
14
|
/**
|
|
@@ -71,56 +22,7 @@ const CredentialsSchema = z.object({
|
|
|
71
22
|
'// Docs': z.optional(z.string()),
|
|
72
23
|
});
|
|
73
24
|
|
|
74
|
-
export
|
|
75
|
-
/** An `access_token` obtained using the OAuth Device Authorization flow. */
|
|
76
|
-
token?: string;
|
|
77
|
-
/** A `refresh_token` obtained using the OAuth Device Authorization flow. */
|
|
78
|
-
refreshToken?: string;
|
|
79
|
-
/**
|
|
80
|
-
* The absolute time (seconds) when the {@link Credentials.token} expires.
|
|
81
|
-
* Used to optimistically check if the token is still valid.
|
|
82
|
-
*/
|
|
83
|
-
expiresAt?: number;
|
|
84
|
-
/** Whether to skip writing the credentials to disk during {@link CredentialsStore.update} */
|
|
85
|
-
skipWrite?: boolean;
|
|
86
|
-
'// Note'?: string;
|
|
87
|
-
'// Docs'?: string;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function hasCredentials(credentials: Partial<Credentials>): boolean {
|
|
91
|
-
return Boolean(
|
|
92
|
-
credentials.token ||
|
|
93
|
-
credentials.refreshToken ||
|
|
94
|
-
typeof credentials.expiresAt === 'number'
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function parseCredentials(value: unknown): Credentials {
|
|
99
|
-
return CredentialsSchema.parse(value) as Credentials;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function isAuthTokenStorage(value: unknown): value is AuthTokenStorage {
|
|
103
|
-
return (
|
|
104
|
-
typeof value === 'string' &&
|
|
105
|
-
AUTH_TOKEN_STORAGE_VALUES.some(storage => storage === value)
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function resolveAuthTokenStorage(value: unknown): AuthTokenStorage {
|
|
110
|
-
if (typeof value === 'undefined') {
|
|
111
|
-
return DEFAULT_AUTH_TOKEN_STORAGE;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (isAuthTokenStorage(value)) {
|
|
115
|
-
return value;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Invalid value for \`authTokenStorage\`: ${JSON.stringify(
|
|
120
|
-
value
|
|
121
|
-
)}. Expected one of: ${AUTH_TOKEN_STORAGE_VALUES.map(storage => JSON.stringify(storage)).join(', ')}.`
|
|
122
|
-
);
|
|
123
|
-
}
|
|
25
|
+
export type Credentials = z.infer<typeof Credentials>;
|
|
124
26
|
|
|
125
27
|
/** Returns whether a directory exists */
|
|
126
28
|
function isDirectory(path: string): boolean {
|
|
@@ -136,8 +38,8 @@ function isDirectory(path: string): boolean {
|
|
|
136
38
|
* Returns in which directory the config should be present
|
|
137
39
|
* @internal Should only be used in {@link CredentialsStore} or tests.
|
|
138
40
|
*/
|
|
139
|
-
export function getGlobalPathConfig(
|
|
140
|
-
const vercelDirectories = XDGAppPaths(
|
|
41
|
+
export function getGlobalPathConfig(dir: string): string {
|
|
42
|
+
const vercelDirectories = XDGAppPaths(dir).dataDirs();
|
|
141
43
|
|
|
142
44
|
const possibleConfigPaths = [
|
|
143
45
|
...vercelDirectories, // latest vercel directory
|
|
@@ -155,403 +57,23 @@ export function getGlobalPathConfig(appName: string): string {
|
|
|
155
57
|
);
|
|
156
58
|
}
|
|
157
59
|
|
|
158
|
-
export function
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export function getAuthConfigFilePath(dir: string): string {
|
|
163
|
-
return path.join(dir, 'auth.json');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export function readGlobalConfig(dir: string): GlobalConfig {
|
|
167
|
-
const configPath = getConfigFilePath(dir);
|
|
168
|
-
let config: {
|
|
169
|
-
authTokenStorage?: unknown;
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
try {
|
|
173
|
-
config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as {
|
|
174
|
-
authTokenStorage?: unknown;
|
|
175
|
-
};
|
|
176
|
-
} catch (error) {
|
|
177
|
-
if (isENOENTError(error)) {
|
|
178
|
-
return {};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
throw error;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
authTokenStorage:
|
|
186
|
-
typeof config.authTokenStorage === 'undefined'
|
|
187
|
-
? undefined
|
|
188
|
-
: resolveAuthTokenStorage(config.authTokenStorage),
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export function getAuthTokenStorage(
|
|
193
|
-
dir: string,
|
|
194
|
-
config?: GlobalConfig
|
|
195
|
-
): AuthTokenStorage {
|
|
196
|
-
if (config?.authTokenStorage) {
|
|
197
|
-
return resolveAuthTokenStorage(config.authTokenStorage);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return resolveAuthTokenStorage(readGlobalConfig(dir).authTokenStorage);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function getKeyringAccount(configPath: string): string {
|
|
204
|
-
const digest = createHash('sha256').update(configPath).digest('hex');
|
|
205
|
-
return `cli:${digest.slice(0, 16)}`;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function setLoadKeyringModuleForTesting(
|
|
209
|
-
nextLoadKeyringModule?: LoadKeyringModule
|
|
210
|
-
) {
|
|
211
|
-
loadKeyringModule = nextLoadKeyringModule ?? defaultLoadKeyringModule;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function createKeyringEntry(configPath: string): KeyringEntry {
|
|
215
|
-
try {
|
|
216
|
-
const { Entry } = loadKeyringModule();
|
|
217
|
-
|
|
218
|
-
return new Entry(KEYRING_SERVICE, getKeyringAccount(configPath));
|
|
219
|
-
} catch (error) {
|
|
220
|
-
const wrappedError = new Error(KEYRING_UNAVAILABLE_ERROR);
|
|
221
|
-
(wrappedError as Error & { cause?: unknown }).cause = error;
|
|
222
|
-
throw wrappedError;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function isKeyringUnavailableError(error: unknown): boolean {
|
|
227
|
-
return error instanceof Error && error.message === KEYRING_UNAVAILABLE_ERROR;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function readCredentialsFromFile(configPath: string): Credentials {
|
|
231
|
-
return parseCredentials(JSON.parse(fs.readFileSync(configPath, 'utf8')));
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function isENOENTError(error: unknown): boolean {
|
|
235
|
-
return (
|
|
236
|
-
typeof error === 'object' &&
|
|
237
|
-
error !== null &&
|
|
238
|
-
'code' in error &&
|
|
239
|
-
error.code === 'ENOENT'
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function createMissingCredentialsError(configPath: string): Error {
|
|
244
|
-
const error = new Error(
|
|
245
|
-
`ENOENT: no such file or directory, open '${configPath}'`
|
|
246
|
-
);
|
|
247
|
-
Object.assign(error, { code: 'ENOENT' });
|
|
248
|
-
return error;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function writeCredentialsToFile(configPath: string, config: Credentials): void {
|
|
252
|
-
const directory = path.dirname(configPath);
|
|
253
|
-
const temporaryPath = path.join(
|
|
254
|
-
directory,
|
|
255
|
-
`${path.basename(configPath)}.${process.pid}.${randomUUID()}.tmp`
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
259
|
-
|
|
260
|
-
try {
|
|
261
|
-
fs.writeFileSync(temporaryPath, JSON.stringify(config, null, 2) + '\n', {
|
|
262
|
-
mode: 0o600,
|
|
263
|
-
});
|
|
264
|
-
fs.renameSync(temporaryPath, configPath);
|
|
265
|
-
} catch (error) {
|
|
266
|
-
fs.rmSync(temporaryPath, { force: true });
|
|
267
|
-
throw error;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function readCredentialsFromKeyring(configPath: string): Credentials | null {
|
|
272
|
-
const entry = createKeyringEntry(configPath);
|
|
273
|
-
const value = entry.getPassword();
|
|
274
|
-
|
|
275
|
-
if (value === null) {
|
|
276
|
-
return null;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return parseCredentials(JSON.parse(value));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function writeCredentialsToKeyring(
|
|
283
|
-
configPath: string,
|
|
284
|
-
config: Credentials
|
|
285
|
-
): void {
|
|
286
|
-
const entry = createKeyringEntry(configPath);
|
|
287
|
-
entry.setPassword(JSON.stringify(config));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
function deleteCredentialsFromKeyring(configPath: string): boolean {
|
|
291
|
-
const entry = createKeyringEntry(configPath);
|
|
292
|
-
return entry.deleteCredential();
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function deleteCredentialsFile(configPath: string): void {
|
|
296
|
-
fs.rmSync(configPath, { force: true });
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function tryDeleteCredentialsFromKeyring(configPath: string): void {
|
|
300
|
-
try {
|
|
301
|
-
deleteCredentialsFromKeyring(configPath);
|
|
302
|
-
} catch {}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
function deleteCredentialsFromKeyringIfAvailable(configPath: string): void {
|
|
306
|
-
try {
|
|
307
|
-
deleteCredentialsFromKeyring(configPath);
|
|
308
|
-
} catch (error) {
|
|
309
|
-
if (!isKeyringUnavailableError(error)) {
|
|
310
|
-
throw error;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function migrateCredentialsToFile(
|
|
316
|
-
configPath: string,
|
|
317
|
-
credentials: Credentials
|
|
318
|
-
): Credentials {
|
|
319
|
-
writeCredentialsToFile(configPath, credentials);
|
|
320
|
-
tryDeleteCredentialsFromKeyring(configPath);
|
|
321
|
-
return credentials;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
function tryReadKeyringCredentialsIntoFile(
|
|
325
|
-
configPath: string
|
|
326
|
-
): Credentials | null {
|
|
327
|
-
try {
|
|
328
|
-
const credentials = readCredentialsFromKeyring(configPath);
|
|
329
|
-
|
|
330
|
-
if (credentials === null) {
|
|
331
|
-
return null;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return migrateCredentialsToFile(configPath, credentials);
|
|
335
|
-
} catch {
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
function readFileStorageCredentials(configPath: string): Credentials {
|
|
341
|
-
try {
|
|
342
|
-
const credentials = readCredentialsFromFile(configPath);
|
|
343
|
-
|
|
344
|
-
if (hasCredentials(credentials)) {
|
|
345
|
-
return credentials;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// File mode treats keyring contents as stale-but-authoritative backup only
|
|
349
|
-
// when auth.json has no usable credentials.
|
|
350
|
-
return tryReadKeyringCredentialsIntoFile(configPath) ?? credentials;
|
|
351
|
-
} catch (error) {
|
|
352
|
-
if (!isENOENTError(error)) {
|
|
353
|
-
throw error;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const credentials = tryReadKeyringCredentialsIntoFile(configPath);
|
|
357
|
-
|
|
358
|
-
if (credentials !== null) {
|
|
359
|
-
return credentials;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
throw error;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function migrateCredentialsToKeyring(
|
|
367
|
-
configPath: string,
|
|
368
|
-
credentials: Credentials
|
|
369
|
-
): Credentials {
|
|
370
|
-
writeCredentialsToKeyring(configPath, credentials);
|
|
371
|
-
deleteCredentialsFile(configPath);
|
|
372
|
-
return credentials;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
function readKeyringStorageCredentials(configPath: string): Credentials {
|
|
376
|
-
const credentials = readCredentialsFromKeyring(configPath);
|
|
377
|
-
|
|
378
|
-
if (credentials !== null) {
|
|
379
|
-
return credentials;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
const fileCredentials = readCredentialsFromFile(configPath);
|
|
384
|
-
|
|
385
|
-
// Keyring mode eagerly migrates any remaining plaintext credentials out of
|
|
386
|
-
// auth.json after the first successful read.
|
|
387
|
-
return migrateCredentialsToKeyring(configPath, fileCredentials);
|
|
388
|
-
} catch (error) {
|
|
389
|
-
if (isENOENTError(error)) {
|
|
390
|
-
throw createMissingCredentialsError(configPath);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
throw error;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function readAutoStorageCredentials(configPath: string): Credentials {
|
|
398
|
-
try {
|
|
399
|
-
const credentials = readCredentialsFromKeyring(configPath);
|
|
400
|
-
|
|
401
|
-
if (credentials !== null) {
|
|
402
|
-
return credentials;
|
|
403
|
-
}
|
|
404
|
-
} catch {}
|
|
405
|
-
|
|
406
|
-
// Auto mode intentionally avoids read-time migration so that machines
|
|
407
|
-
// without usable keyring support can keep working off auth.json.
|
|
408
|
-
return readCredentialsFromFile(configPath);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
function writeFileStorageCredentials(
|
|
412
|
-
configPath: string,
|
|
413
|
-
credentials: Credentials
|
|
414
|
-
): CredentialsStorageLocation {
|
|
415
|
-
writeCredentialsToFile(configPath, credentials);
|
|
416
|
-
tryDeleteCredentialsFromKeyring(configPath);
|
|
417
|
-
return 'file';
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
function writeKeyringStorageCredentials(
|
|
421
|
-
configPath: string,
|
|
422
|
-
credentials: Credentials
|
|
423
|
-
): CredentialsStorageLocation {
|
|
424
|
-
writeCredentialsToKeyring(configPath, credentials);
|
|
425
|
-
deleteCredentialsFile(configPath);
|
|
426
|
-
return 'keyring';
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
function writeAutoStorageCredentials(
|
|
430
|
-
configPath: string,
|
|
431
|
-
credentials: Credentials
|
|
432
|
-
): CredentialsStorageLocation {
|
|
433
|
-
try {
|
|
434
|
-
return writeKeyringStorageCredentials(configPath, credentials);
|
|
435
|
-
} catch {
|
|
436
|
-
tryDeleteCredentialsFromKeyring(configPath);
|
|
437
|
-
return writeFileStorageCredentials(configPath, credentials);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
function deleteFileStorageCredentials(configPath: string): void {
|
|
442
|
-
deleteCredentialsFile(configPath);
|
|
443
|
-
deleteCredentialsFromKeyringIfAvailable(configPath);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function deleteKeyringStorageCredentials(configPath: string): void {
|
|
447
|
-
deleteCredentialsFromKeyring(configPath);
|
|
448
|
-
deleteCredentialsFile(configPath);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
function deleteAutoStorageCredentials(configPath: string): void {
|
|
452
|
-
try {
|
|
453
|
-
deleteCredentialsFromKeyring(configPath);
|
|
454
|
-
} catch {}
|
|
455
|
-
deleteCredentialsFile(configPath);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
export function CredentialsStore(dir: string, config: GlobalConfig = {}) {
|
|
459
|
-
const configPath = getAuthConfigFilePath(dir);
|
|
460
|
-
const tokenStorage = getAuthTokenStorage(dir, config);
|
|
461
|
-
|
|
60
|
+
export function CredentialsStore(dir: string) {
|
|
61
|
+
const configPath = path.join(getGlobalPathConfig(dir), 'auth.json');
|
|
462
62
|
return {
|
|
463
63
|
configPath,
|
|
464
64
|
get(): Credentials {
|
|
465
|
-
|
|
466
|
-
case AUTH_TOKEN_STORAGE.FILE:
|
|
467
|
-
return readFileStorageCredentials(configPath);
|
|
468
|
-
case AUTH_TOKEN_STORAGE.KEYRING:
|
|
469
|
-
return readKeyringStorageCredentials(configPath);
|
|
470
|
-
case AUTH_TOKEN_STORAGE.AUTO:
|
|
471
|
-
return readAutoStorageCredentials(configPath);
|
|
472
|
-
}
|
|
65
|
+
return Credentials.parse(JSON.parse(fs.readFileSync(configPath, 'utf8')));
|
|
473
66
|
},
|
|
474
67
|
/** Update the credentials store. If `skipWrite` is set, the update will be skipped. */
|
|
475
|
-
update(config: Partial<Credentials>):
|
|
68
|
+
update(config: Partial<Credentials>): void {
|
|
476
69
|
if (config.skipWrite) return;
|
|
477
|
-
const parsedConfig =
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return writeAutoStorageCredentials(configPath, parsedConfig);
|
|
485
|
-
}
|
|
486
|
-
},
|
|
487
|
-
delete(): void {
|
|
488
|
-
switch (tokenStorage) {
|
|
489
|
-
case AUTH_TOKEN_STORAGE.FILE:
|
|
490
|
-
deleteFileStorageCredentials(configPath);
|
|
491
|
-
break;
|
|
492
|
-
case AUTH_TOKEN_STORAGE.KEYRING:
|
|
493
|
-
deleteKeyringStorageCredentials(configPath);
|
|
494
|
-
break;
|
|
495
|
-
case AUTH_TOKEN_STORAGE.AUTO:
|
|
496
|
-
deleteAutoStorageCredentials(configPath);
|
|
497
|
-
break;
|
|
498
|
-
}
|
|
70
|
+
const parsedConfig = Credentials.parse(config);
|
|
71
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
72
|
+
fs.writeFileSync(
|
|
73
|
+
configPath,
|
|
74
|
+
JSON.stringify(parsedConfig, null, 2) + '\n',
|
|
75
|
+
{ mode: 0o600 }
|
|
76
|
+
);
|
|
499
77
|
},
|
|
500
78
|
};
|
|
501
79
|
}
|
|
502
|
-
|
|
503
|
-
export function readCredentials(dir: string, config: GlobalConfig = {}) {
|
|
504
|
-
return CredentialsStore(dir, config).get();
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
export function writeCredentials(
|
|
508
|
-
dir: string,
|
|
509
|
-
credentials: Partial<Credentials>,
|
|
510
|
-
config: GlobalConfig = {}
|
|
511
|
-
) {
|
|
512
|
-
return CredentialsStore(dir, config).update(credentials);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
export function clearCredentials(dir: string, config: GlobalConfig = {}) {
|
|
516
|
-
CredentialsStore(dir, config).delete();
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
export function clearAllCredentials(dir: string) {
|
|
520
|
-
for (const authTokenStorage of [
|
|
521
|
-
AUTH_TOKEN_STORAGE.FILE,
|
|
522
|
-
AUTH_TOKEN_STORAGE.KEYRING,
|
|
523
|
-
] as const) {
|
|
524
|
-
try {
|
|
525
|
-
clearCredentials(dir, { authTokenStorage });
|
|
526
|
-
} catch {}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
export function clearAllCredentialsStrict(dir: string) {
|
|
531
|
-
const configPath = getAuthConfigFilePath(dir);
|
|
532
|
-
|
|
533
|
-
let fileError: unknown;
|
|
534
|
-
let keyringError: unknown;
|
|
535
|
-
|
|
536
|
-
try {
|
|
537
|
-
deleteCredentialsFile(configPath);
|
|
538
|
-
} catch (error) {
|
|
539
|
-
fileError = error;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
try {
|
|
543
|
-
deleteCredentialsFromKeyring(configPath);
|
|
544
|
-
} catch (error) {
|
|
545
|
-
if (!isKeyringUnavailableError(error)) {
|
|
546
|
-
keyringError = error;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (keyringError) {
|
|
551
|
-
throw keyringError;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (fileError) {
|
|
555
|
-
throw fileError;
|
|
556
|
-
}
|
|
557
|
-
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/cli-auth",
|
|
3
3
|
"description": "Used by Vercel's CLIs to handle authentication",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"!**/*.test.ts"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@napi-rs/keyring": "1.2.0",
|
|
23
22
|
"async-listen": "3.0.0",
|
|
24
23
|
"open": "8.4.0",
|
|
25
24
|
"xdg-app-paths": "5",
|
|
@@ -28,7 +27,6 @@
|
|
|
28
27
|
"devDependencies": {
|
|
29
28
|
"@types/node": "20.11.0",
|
|
30
29
|
"memfs": "4.14.0",
|
|
31
|
-
"typescript": "5.9.2",
|
|
32
30
|
"vite": "7.1.7",
|
|
33
31
|
"vitest": "2.1.4"
|
|
34
32
|
},
|