@cloudflare/workers-auth 0.5.5 → 0.6.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/cf/index.d.mts +3 -3
- package/dist/cf/index.mjs +6 -3
- package/dist/{chunk-PBW6773T.mjs → chunk-7AYQ2BAF.mjs} +404 -18
- package/dist/{chunk-RTFTHYPD.mjs → chunk-AEOSGWMT.mjs} +9 -3
- package/dist/{file-format-B1KgHuUR.d.mts → file-format-Dbmn5hhd.d.mts} +22 -0
- package/dist/index.d.mts +28 -4
- package/dist/index.mjs +1 -1
- package/dist/{keyring-preference-BgjU5DM9.d.mts → keyring-preference-CeP6MLyb.d.mts} +25 -2
- package/dist/metafile-esm.json +1 -1
- package/dist/wrangler/index.d.mts +2 -2
- package/dist/wrangler/index.mjs +6 -3
- package/package.json +2 -2
package/dist/cf/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as ConfigStorage, A as AuthConfigStorage, U as UserAuthConfig, b as OAuthFlowContext, k as ProfileStore } from '../file-format-
|
|
2
|
-
import { C as CliDescriptor, U as UserPreferences, A as AuthContext, a as CloudflareAuth, K as KeyringPreferenceContext, S as SetKeyringPreferenceResult } from '../keyring-preference-
|
|
3
|
-
export { b as CloudflareLoginProps } from '../keyring-preference-
|
|
1
|
+
import { a as ConfigStorage, A as AuthConfigStorage, U as UserAuthConfig, b as OAuthFlowContext, k as ProfileStore } from '../file-format-Dbmn5hhd.mjs';
|
|
2
|
+
import { C as CliDescriptor, U as UserPreferences, A as AuthContext, a as CloudflareAuth, K as KeyringPreferenceContext, S as SetKeyringPreferenceResult } from '../keyring-preference-CeP6MLyb.mjs';
|
|
3
|
+
export { b as CloudflareLoginProps } from '../keyring-preference-CeP6MLyb.mjs';
|
|
4
4
|
import '@cloudflare/workers-utils';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/cf/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createAuthConfigFileHelpers, createPreferences, createKeyringPreference, createFileStorage, createCloudflareAuth, createCloudflareProfileStore } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
import { createAuthConfigFileHelpers, createPreferences, createKeyringPreference, createFileStorage, createCloudflareAuth, createCloudflareProfileStore } from '../chunk-AEOSGWMT.mjs';
|
|
2
|
+
import '../chunk-7AYQ2BAF.mjs';
|
|
3
3
|
import { __name } from '../chunk-O6YSETKJ.mjs';
|
|
4
4
|
import { getEnvironmentVariableFactory, getGlobalConfigPath, getCloudflareApiEnvironmentFromEnv } from '@cloudflare/workers-utils';
|
|
5
5
|
import path from 'node:path';
|
|
@@ -7,6 +7,7 @@ import path from 'node:path';
|
|
|
7
7
|
// src/cf/constants.ts
|
|
8
8
|
var CF_KEYRING_SERVICE_NAME = "cloudflare";
|
|
9
9
|
var CF_CLI_NAME = "cf";
|
|
10
|
+
var CF_DISPLAY_NAME = "cf";
|
|
10
11
|
var CF_OAUTH_CALLBACK_URL = "http://localhost:8877/oauth/callback";
|
|
11
12
|
var CF_CONSENT_PAGES = {
|
|
12
13
|
granted: {
|
|
@@ -158,10 +159,12 @@ var {
|
|
|
158
159
|
// src/cf/index.ts
|
|
159
160
|
var CF_CLI = {
|
|
160
161
|
cliName: CF_CLI_NAME,
|
|
162
|
+
displayName: CF_DISPLAY_NAME,
|
|
161
163
|
commands: {
|
|
162
164
|
login: "cf auth login",
|
|
163
165
|
whoami: "cf auth whoami",
|
|
164
|
-
createProfile: "cf auth create"
|
|
166
|
+
createProfile: "cf auth create",
|
|
167
|
+
deviceLogin: "cf auth login --device"
|
|
165
168
|
},
|
|
166
169
|
keyringServiceName: CF_KEYRING_SERVICE_NAME,
|
|
167
170
|
clientId: getClientIdFromEnv,
|
|
@@ -99,6 +99,19 @@ function requireApiToken(options) {
|
|
|
99
99
|
return credentials;
|
|
100
100
|
}
|
|
101
101
|
__name(requireApiToken, "requireApiToken");
|
|
102
|
+
var ACCOUNT_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
103
|
+
function validateAccountId(accountId, source) {
|
|
104
|
+
if (!ACCOUNT_ID_PATTERN.test(accountId)) {
|
|
105
|
+
throw new UserError(
|
|
106
|
+
`Invalid account ID "${accountId}" ${source}. Account IDs may only contain alphanumeric characters, hyphens, and underscores.`,
|
|
107
|
+
{ telemetryMessage: "user account id invalid characters" }
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
return accountId;
|
|
111
|
+
}
|
|
112
|
+
__name(validateAccountId, "validateAccountId");
|
|
113
|
+
|
|
114
|
+
// src/env-vars.ts
|
|
102
115
|
var getAuthDomainFromEnv = getEnvironmentVariableFactory({
|
|
103
116
|
variableName: "WRANGLER_AUTH_DOMAIN",
|
|
104
117
|
defaultValue: /* @__PURE__ */ __name(() => getCloudflareApiEnvironmentFromEnv() === "staging" ? "dash.staging.cloudflare.com" : "dash.cloudflare.com", "defaultValue")
|
|
@@ -115,10 +128,26 @@ var getRevokeUrlFromEnv = getEnvironmentVariableFactory({
|
|
|
115
128
|
variableName: "WRANGLER_REVOKE_URL",
|
|
116
129
|
defaultValue: /* @__PURE__ */ __name(() => `https://${getAuthDomainFromEnv()}/oauth2/revoke`, "defaultValue")
|
|
117
130
|
});
|
|
118
|
-
var
|
|
131
|
+
var readCloudflareAccountIdFromEnv = getEnvironmentVariableFactory({
|
|
119
132
|
variableName: "CLOUDFLARE_ACCOUNT_ID",
|
|
120
133
|
deprecatedName: "CF_ACCOUNT_ID"
|
|
121
134
|
});
|
|
135
|
+
function getCloudflareAccountIdFromEnv() {
|
|
136
|
+
const accountId = readCloudflareAccountIdFromEnv();
|
|
137
|
+
if (!accountId) {
|
|
138
|
+
return void 0;
|
|
139
|
+
}
|
|
140
|
+
return validateAccountId(
|
|
141
|
+
accountId,
|
|
142
|
+
"set in the `CLOUDFLARE_ACCOUNT_ID` environment variable"
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
__name(getCloudflareAccountIdFromEnv, "getCloudflareAccountIdFromEnv");
|
|
146
|
+
var DEVICE_AUTH_PATH = "/oauth2/device/auth";
|
|
147
|
+
function getDeviceAuthUrl() {
|
|
148
|
+
return `https://${getAuthDomainFromEnv()}${DEVICE_AUTH_PATH}`;
|
|
149
|
+
}
|
|
150
|
+
__name(getDeviceAuthUrl, "getDeviceAuthUrl");
|
|
122
151
|
var getAccessClientIdFromEnv = getEnvironmentVariableFactory({
|
|
123
152
|
variableName: "CLOUDFLARE_ACCESS_CLIENT_ID"
|
|
124
153
|
});
|
|
@@ -296,6 +325,36 @@ async function generatePKCECodes() {
|
|
|
296
325
|
return { codeChallenge, codeVerifier };
|
|
297
326
|
}
|
|
298
327
|
__name(generatePKCECodes, "generatePKCECodes");
|
|
328
|
+
var generateVerificationUrl = /* @__PURE__ */ __name(({
|
|
329
|
+
verificationUri,
|
|
330
|
+
userCode
|
|
331
|
+
}) => {
|
|
332
|
+
const url2 = new URL(verificationUri);
|
|
333
|
+
url2.searchParams.set("user_code", userCode);
|
|
334
|
+
return url2.toString();
|
|
335
|
+
}, "generateVerificationUrl");
|
|
336
|
+
function parseUrl(value) {
|
|
337
|
+
try {
|
|
338
|
+
return new URL(value);
|
|
339
|
+
} catch {
|
|
340
|
+
return void 0;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
__name(parseUrl, "parseUrl");
|
|
344
|
+
function assertTrustedVerificationUrl(verificationUrl, options) {
|
|
345
|
+
const url2 = parseUrl(verificationUrl);
|
|
346
|
+
const expected = parseUrl(`https://${options.authDomain}`);
|
|
347
|
+
const trusted = url2 !== void 0 && expected !== void 0 && url2.protocol === "https:" && url2.username === "" && url2.password === "" && // `host` rather than `hostname` so a port in either value is significant.
|
|
348
|
+
url2.host === expected.host;
|
|
349
|
+
if (!trusted) {
|
|
350
|
+
throw new UserError(
|
|
351
|
+
`The authorization server returned an untrusted \`${options.field}\`: ${verificationUrl}
|
|
352
|
+
Expected an \`https\` URL on \`${options.authDomain}\`. Refusing to display or open it.`,
|
|
353
|
+
{ telemetryMessage: "user device-flow untrusted verification url" }
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
__name(assertTrustedVerificationUrl, "assertTrustedVerificationUrl");
|
|
299
358
|
|
|
300
359
|
// src/generate-auth-url.ts
|
|
301
360
|
var generateAuthUrl = /* @__PURE__ */ __name(({
|
|
@@ -1177,6 +1236,318 @@ If you have changed the callback host or port because you are running in a conta
|
|
|
1177
1236
|
return Promise.race([timerPromise, loginPromise]);
|
|
1178
1237
|
}
|
|
1179
1238
|
__name(getOauthToken, "getOauthToken");
|
|
1239
|
+
var DEVICE_FLOW_MAX_DURATION_SECONDS = 300;
|
|
1240
|
+
var DEVICE_FLOW_MIN_POLL_INTERVAL_SECONDS = 1;
|
|
1241
|
+
function getStringMember(body, key) {
|
|
1242
|
+
if (typeof body !== "object" || body === null) {
|
|
1243
|
+
return void 0;
|
|
1244
|
+
}
|
|
1245
|
+
const value = body[key];
|
|
1246
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
1247
|
+
}
|
|
1248
|
+
__name(getStringMember, "getStringMember");
|
|
1249
|
+
function getPositiveNumberMember(body, key) {
|
|
1250
|
+
if (typeof body !== "object" || body === null) {
|
|
1251
|
+
return void 0;
|
|
1252
|
+
}
|
|
1253
|
+
const value = body[key];
|
|
1254
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
1255
|
+
}
|
|
1256
|
+
__name(getPositiveNumberMember, "getPositiveNumberMember");
|
|
1257
|
+
function describeUnusableResponse(response, body) {
|
|
1258
|
+
const status = `HTTP ${response.status} ${response.statusText}`.trim();
|
|
1259
|
+
const description = getStringMember(body, "error_description");
|
|
1260
|
+
return description ? `${status}: ${description}` : status;
|
|
1261
|
+
}
|
|
1262
|
+
__name(describeUnusableResponse, "describeUnusableResponse");
|
|
1263
|
+
function isRetryableStatus(status) {
|
|
1264
|
+
return status >= 500 || status === 429;
|
|
1265
|
+
}
|
|
1266
|
+
__name(isRetryableStatus, "isRetryableStatus");
|
|
1267
|
+
function asDeviceAuthorizationResponse(body) {
|
|
1268
|
+
const deviceCode = getStringMember(body, "device_code");
|
|
1269
|
+
const userCode = getStringMember(body, "user_code");
|
|
1270
|
+
const verificationUri = getStringMember(body, "verification_uri");
|
|
1271
|
+
const expiresIn = getPositiveNumberMember(body, "expires_in");
|
|
1272
|
+
if (!deviceCode || !userCode || !verificationUri || expiresIn === void 0) {
|
|
1273
|
+
return void 0;
|
|
1274
|
+
}
|
|
1275
|
+
return {
|
|
1276
|
+
device_code: deviceCode,
|
|
1277
|
+
user_code: userCode,
|
|
1278
|
+
verification_uri: verificationUri,
|
|
1279
|
+
verification_uri_complete: getStringMember(
|
|
1280
|
+
body,
|
|
1281
|
+
"verification_uri_complete"
|
|
1282
|
+
),
|
|
1283
|
+
expires_in: expiresIn,
|
|
1284
|
+
interval: getPositiveNumberMember(body, "interval")
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
__name(asDeviceAuthorizationResponse, "asDeviceAuthorizationResponse");
|
|
1288
|
+
async function readJson(response, logger) {
|
|
1289
|
+
const text = await response.text();
|
|
1290
|
+
try {
|
|
1291
|
+
return JSON.parse(text);
|
|
1292
|
+
} catch (e) {
|
|
1293
|
+
if (text.match(/<!DOCTYPE html>/)) {
|
|
1294
|
+
logger.debug(
|
|
1295
|
+
"The body of the response was HTML rather than JSON. Check the debug logs to see the full body of the response."
|
|
1296
|
+
);
|
|
1297
|
+
if (text.match(/challenge-platform/)) {
|
|
1298
|
+
logger.debug(
|
|
1299
|
+
`It looks like you might have hit a bot challenge page. This may be transient but if not, please contact Cloudflare to find out what can be done. When you contact Cloudflare, please provide your Ray ID: ${response.headers.get(
|
|
1300
|
+
"cf-ray"
|
|
1301
|
+
)}`
|
|
1302
|
+
);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
logger.debug("Full body of response\n\n", text);
|
|
1306
|
+
throw new Error(
|
|
1307
|
+
`Invalid JSON in response: status: ${response.status} ${response.statusText}`,
|
|
1308
|
+
{ cause: e }
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
__name(readJson, "readJson");
|
|
1313
|
+
async function buildDeviceAuthHeaders(logger, isNonInteractiveOrCI2) {
|
|
1314
|
+
const headers = {
|
|
1315
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
1316
|
+
};
|
|
1317
|
+
if (await domainUsesAccess(getAuthDomainFromEnv(), logger)) {
|
|
1318
|
+
logger.debug(
|
|
1319
|
+
"Using Cloudflare Access to get an access token for the device authorization request"
|
|
1320
|
+
);
|
|
1321
|
+
Object.assign(
|
|
1322
|
+
headers,
|
|
1323
|
+
await getCloudflareAccessHeaders({ logger, isNonInteractiveOrCI: isNonInteractiveOrCI2 })
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
return headers;
|
|
1327
|
+
}
|
|
1328
|
+
__name(buildDeviceAuthHeaders, "buildDeviceAuthHeaders");
|
|
1329
|
+
async function requestDeviceAuthorization(scopes, clientId, logger, isNonInteractiveOrCI2) {
|
|
1330
|
+
const params = new URLSearchParams({
|
|
1331
|
+
client_id: clientId,
|
|
1332
|
+
scope: [...scopes, "offline_access"].join(" ")
|
|
1333
|
+
});
|
|
1334
|
+
const headers = await buildDeviceAuthHeaders(logger, isNonInteractiveOrCI2);
|
|
1335
|
+
const deviceAuthUrl = getDeviceAuthUrl();
|
|
1336
|
+
logger.debug("Fetching device authorization from", deviceAuthUrl);
|
|
1337
|
+
const response = await fetch(deviceAuthUrl, {
|
|
1338
|
+
method: "POST",
|
|
1339
|
+
body: params.toString(),
|
|
1340
|
+
headers
|
|
1341
|
+
});
|
|
1342
|
+
if (!response.ok) {
|
|
1343
|
+
const body2 = await readJson(response, logger).catch(() => void 0);
|
|
1344
|
+
const rawError = body2 && typeof body2 === "object" && "error" in body2 ? String(body2.error) : `HTTP ${response.status} ${response.statusText}`;
|
|
1345
|
+
throw toErrorClass(rawError);
|
|
1346
|
+
}
|
|
1347
|
+
const body = await readJson(response, logger);
|
|
1348
|
+
const deviceAuth = asDeviceAuthorizationResponse(body);
|
|
1349
|
+
if (deviceAuth === void 0) {
|
|
1350
|
+
logger.debug("Unusable device authorization response body:", body);
|
|
1351
|
+
throw new UserError(
|
|
1352
|
+
`The device authorization endpoint returned a response that could not be interpreted (${describeUnusableResponse(response, body)}).
|
|
1353
|
+
Enable debug logging to see the full response.`,
|
|
1354
|
+
{
|
|
1355
|
+
telemetryMessage: "user device-flow unusable device authorization response"
|
|
1356
|
+
}
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
return deviceAuth;
|
|
1360
|
+
}
|
|
1361
|
+
__name(requestDeviceAuthorization, "requestDeviceAuthorization");
|
|
1362
|
+
async function pollDeviceToken(deviceCode, clientId, logger, isNonInteractiveOrCI2) {
|
|
1363
|
+
const params = new URLSearchParams({
|
|
1364
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
1365
|
+
device_code: deviceCode,
|
|
1366
|
+
client_id: clientId
|
|
1367
|
+
});
|
|
1368
|
+
const response = await fetchAuthToken(params, logger, isNonInteractiveOrCI2);
|
|
1369
|
+
const body = await readJson(response, logger);
|
|
1370
|
+
const error = getStringMember(body, "error");
|
|
1371
|
+
if (error !== void 0) {
|
|
1372
|
+
return { kind: "oauth-error", error };
|
|
1373
|
+
}
|
|
1374
|
+
const accessToken = getStringMember(body, "access_token");
|
|
1375
|
+
const expiresIn = getPositiveNumberMember(body, "expires_in");
|
|
1376
|
+
if (!response.ok || accessToken === void 0 || expiresIn === void 0) {
|
|
1377
|
+
logger.debug("Unusable token response body:", body);
|
|
1378
|
+
return {
|
|
1379
|
+
kind: "unexpected",
|
|
1380
|
+
detail: describeUnusableResponse(response, body),
|
|
1381
|
+
// A 2xx that carries no usable grant is not going to become one on the
|
|
1382
|
+
// next attempt, so only the retryable statuses keep the loop alive.
|
|
1383
|
+
retryable: !response.ok && isRetryableStatus(response.status)
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
return {
|
|
1387
|
+
kind: "token",
|
|
1388
|
+
grant: {
|
|
1389
|
+
access_token: accessToken,
|
|
1390
|
+
expires_in: expiresIn,
|
|
1391
|
+
refresh_token: getStringMember(body, "refresh_token"),
|
|
1392
|
+
scope: getStringMember(body, "scope")
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
__name(pollDeviceToken, "pollDeviceToken");
|
|
1397
|
+
function sleep(seconds) {
|
|
1398
|
+
return new Promise((resolve) => setTimeout(resolve, seconds * 1e3));
|
|
1399
|
+
}
|
|
1400
|
+
__name(sleep, "sleep");
|
|
1401
|
+
async function getOauthTokenViaDeviceFlow(options, ctx) {
|
|
1402
|
+
const { logger, openInBrowser, isNonInteractiveOrCI: isNonInteractiveOrCI2 } = ctx;
|
|
1403
|
+
const deviceAuth = await requestDeviceAuthorization(
|
|
1404
|
+
options.scopes,
|
|
1405
|
+
options.clientId,
|
|
1406
|
+
logger,
|
|
1407
|
+
isNonInteractiveOrCI2
|
|
1408
|
+
);
|
|
1409
|
+
const authDomain = getAuthDomainFromEnv();
|
|
1410
|
+
assertTrustedVerificationUrl(deviceAuth.verification_uri, {
|
|
1411
|
+
field: "verification_uri",
|
|
1412
|
+
authDomain
|
|
1413
|
+
});
|
|
1414
|
+
if (deviceAuth.verification_uri_complete !== void 0) {
|
|
1415
|
+
assertTrustedVerificationUrl(deviceAuth.verification_uri_complete, {
|
|
1416
|
+
field: "verification_uri_complete",
|
|
1417
|
+
authDomain
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
const verificationUrl = deviceAuth.verification_uri_complete ?? generateVerificationUrl({
|
|
1421
|
+
verificationUri: deviceAuth.verification_uri,
|
|
1422
|
+
userCode: deviceAuth.user_code
|
|
1423
|
+
});
|
|
1424
|
+
const maxDurationSeconds = Math.min(
|
|
1425
|
+
deviceAuth.expires_in,
|
|
1426
|
+
DEVICE_FLOW_MAX_DURATION_SECONDS
|
|
1427
|
+
);
|
|
1428
|
+
logger.log(
|
|
1429
|
+
esm_default`
|
|
1430
|
+
To authorize ${ctx.displayName}, please visit:
|
|
1431
|
+
|
|
1432
|
+
${deviceAuth.verification_uri}
|
|
1433
|
+
|
|
1434
|
+
and enter the code:
|
|
1435
|
+
|
|
1436
|
+
${deviceAuth.user_code}
|
|
1437
|
+
|
|
1438
|
+
You have ${toHumanPeriod(maxDurationSeconds)} to approve this request.
|
|
1439
|
+
`
|
|
1440
|
+
);
|
|
1441
|
+
if (options.browser) {
|
|
1442
|
+
logger.log(`
|
|
1443
|
+
Opening a link in your default browser: ${verificationUrl}`);
|
|
1444
|
+
await openInBrowser(verificationUrl);
|
|
1445
|
+
}
|
|
1446
|
+
const deadline = Date.now() + maxDurationSeconds * 1e3;
|
|
1447
|
+
let intervalSeconds = Math.max(
|
|
1448
|
+
deviceAuth.interval ?? DEVICE_FLOW_MIN_POLL_INTERVAL_SECONDS,
|
|
1449
|
+
DEVICE_FLOW_MIN_POLL_INTERVAL_SECONDS
|
|
1450
|
+
);
|
|
1451
|
+
let firstPoll = true;
|
|
1452
|
+
let lastPollFailure;
|
|
1453
|
+
while (Date.now() < deadline) {
|
|
1454
|
+
if (!firstPoll) {
|
|
1455
|
+
await sleep(intervalSeconds);
|
|
1456
|
+
}
|
|
1457
|
+
firstPoll = false;
|
|
1458
|
+
let result;
|
|
1459
|
+
try {
|
|
1460
|
+
result = await pollDeviceToken(
|
|
1461
|
+
deviceAuth.device_code,
|
|
1462
|
+
options.clientId,
|
|
1463
|
+
logger,
|
|
1464
|
+
isNonInteractiveOrCI2
|
|
1465
|
+
);
|
|
1466
|
+
} catch (e) {
|
|
1467
|
+
logger.debug("Ignoring transient error while polling for token:", e);
|
|
1468
|
+
lastPollFailure = e instanceof Error ? e.message : String(e);
|
|
1469
|
+
continue;
|
|
1470
|
+
}
|
|
1471
|
+
if (result.kind === "unexpected") {
|
|
1472
|
+
if (!result.retryable) {
|
|
1473
|
+
throw new UserError(
|
|
1474
|
+
`The token endpoint returned a response that could not be interpreted (${result.detail}).
|
|
1475
|
+
Enable debug logging to see the full response.`,
|
|
1476
|
+
{ telemetryMessage: "user device-flow unusable token response" }
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
logger.debug(
|
|
1480
|
+
"Ignoring transient response while polling for token:",
|
|
1481
|
+
result.detail
|
|
1482
|
+
);
|
|
1483
|
+
lastPollFailure = result.detail;
|
|
1484
|
+
continue;
|
|
1485
|
+
}
|
|
1486
|
+
lastPollFailure = void 0;
|
|
1487
|
+
if (result.kind === "oauth-error") {
|
|
1488
|
+
switch (result.error) {
|
|
1489
|
+
case "authorization_pending":
|
|
1490
|
+
continue;
|
|
1491
|
+
case "slow_down":
|
|
1492
|
+
intervalSeconds += 5;
|
|
1493
|
+
continue;
|
|
1494
|
+
case "access_denied":
|
|
1495
|
+
throw new UserError(
|
|
1496
|
+
`Consent denied. You must grant consent to ${ctx.displayName} in order to login.
|
|
1497
|
+
If you don't want to do this consider passing an API token via the \`CLOUDFLARE_API_TOKEN\` environment variable.`,
|
|
1498
|
+
{ telemetryMessage: "user device-flow consent denied" }
|
|
1499
|
+
);
|
|
1500
|
+
case "expired_token":
|
|
1501
|
+
throw new UserError(
|
|
1502
|
+
`Device code expired before the request was approved. Please run \`${ctx.deviceLoginCommand}\` again to obtain a new code.`,
|
|
1503
|
+
{ telemetryMessage: "user device-flow code expired" }
|
|
1504
|
+
);
|
|
1505
|
+
default:
|
|
1506
|
+
throw toErrorClass(result.error);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
const { grant } = result;
|
|
1510
|
+
const accessToken = {
|
|
1511
|
+
value: grant.access_token,
|
|
1512
|
+
expiry: new Date(Date.now() + grant.expires_in * 1e3).toISOString()
|
|
1513
|
+
};
|
|
1514
|
+
const scopes = grant.scope ? grant.scope.split(" ") : [];
|
|
1515
|
+
return {
|
|
1516
|
+
token: accessToken,
|
|
1517
|
+
scopes,
|
|
1518
|
+
refreshToken: grant.refresh_token ? { value: grant.refresh_token } : void 0
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
if (lastPollFailure !== void 0) {
|
|
1522
|
+
throw new UserError(
|
|
1523
|
+
`Gave up waiting for device authorization: the token endpoint kept returning responses that could not be interpreted (last: ${lastPollFailure}).
|
|
1524
|
+
Enable debug logging to see the full response, then run \`${ctx.deviceLoginCommand}\` to try again.`,
|
|
1525
|
+
{ telemetryMessage: "user device-flow poll failed" }
|
|
1526
|
+
);
|
|
1527
|
+
}
|
|
1528
|
+
throw new UserError(
|
|
1529
|
+
`Device authorization timed out after ${toHumanPeriod(maxDurationSeconds)}. Please run \`${ctx.deviceLoginCommand}\` again to obtain a new code.`,
|
|
1530
|
+
{ telemetryMessage: "user device-flow authorization timeout" }
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
__name(getOauthTokenViaDeviceFlow, "getOauthTokenViaDeviceFlow");
|
|
1534
|
+
function toHumanPeriod(seconds) {
|
|
1535
|
+
if (seconds < 60) {
|
|
1536
|
+
return `${seconds} seconds`;
|
|
1537
|
+
}
|
|
1538
|
+
const minutes = Math.floor(seconds / 60);
|
|
1539
|
+
const minutesPostfix = minutes === 1 ? "minute" : "minutes";
|
|
1540
|
+
const remainingSeconds = seconds % 60;
|
|
1541
|
+
const secondsPostfix = remainingSeconds === 1 ? "second" : "seconds";
|
|
1542
|
+
if (remainingSeconds === 0) {
|
|
1543
|
+
return `${minutes} ${minutesPostfix}`;
|
|
1544
|
+
}
|
|
1545
|
+
if (remainingSeconds == 59) {
|
|
1546
|
+
return `${minutes + 1} ${minutesPostfix}`;
|
|
1547
|
+
}
|
|
1548
|
+
return `${minutes} ${minutesPostfix} and ${remainingSeconds} ${secondsPostfix}`;
|
|
1549
|
+
}
|
|
1550
|
+
__name(toHumanPeriod, "toHumanPeriod");
|
|
1180
1551
|
|
|
1181
1552
|
// src/flow.ts
|
|
1182
1553
|
function createOAuthFlow(ctx) {
|
|
@@ -1219,22 +1590,37 @@ function createOAuthFlow(ctx) {
|
|
|
1219
1590
|
}
|
|
1220
1591
|
);
|
|
1221
1592
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1593
|
+
let oauth;
|
|
1594
|
+
if (props.device) {
|
|
1595
|
+
ctx.logger.log(
|
|
1596
|
+
"Attempting to login via OAuth Device Authorization Grant..."
|
|
1597
|
+
);
|
|
1598
|
+
oauth = await getOauthTokenViaDeviceFlow(
|
|
1599
|
+
{
|
|
1600
|
+
browser: props.browser ?? true,
|
|
1601
|
+
scopes: props.scopes,
|
|
1602
|
+
clientId: getClientId()
|
|
1603
|
+
},
|
|
1604
|
+
ctx
|
|
1605
|
+
);
|
|
1606
|
+
} else {
|
|
1607
|
+
ctx.logger.log("Attempting to login via OAuth...");
|
|
1608
|
+
oauth = await getOauthToken(
|
|
1609
|
+
{
|
|
1610
|
+
browser: props.browser ?? true,
|
|
1611
|
+
scopes: props.scopes,
|
|
1612
|
+
clientId: getClientId(),
|
|
1613
|
+
redirectUri: ctx.redirectUri,
|
|
1614
|
+
denied: consent.denied,
|
|
1615
|
+
granted: consent.granted,
|
|
1616
|
+
callbackHost: props.callbackHost ?? defaultCallbackHost,
|
|
1617
|
+
callbackPort: props.callbackPort ?? defaultCallbackPort
|
|
1618
|
+
},
|
|
1619
|
+
oauthFlowState,
|
|
1620
|
+
ctx,
|
|
1621
|
+
generators
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1238
1624
|
getStorage(props.profile).write({
|
|
1239
1625
|
oauth_token: oauth.token?.value ?? "",
|
|
1240
1626
|
expiration_time: oauth.token?.expiry,
|
|
@@ -3724,4 +4110,4 @@ smol-toml/dist/index.js:
|
|
|
3724
4110
|
*)
|
|
3725
4111
|
*/
|
|
3726
4112
|
|
|
3727
|
-
export { EncryptedFileCredentialStore, FileCredentialStore, LinuxSecretToolKeyProvider, MacSecurityKeyProvider, NapiKeyringKeyProvider, PINNED_KEYRING_VERSION, PKCE_CHARSET, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, createOAuthFlow, createProfileStore, decryptString, dedent, domainUsesAccess, encryptString, findKeyringBinding, generateAuthUrl, generateKey, generateRandomState, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, parseFile, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner, stringifyFile, validateProfileName };
|
|
4113
|
+
export { EncryptedFileCredentialStore, FileCredentialStore, LinuxSecretToolKeyProvider, MacSecurityKeyProvider, NapiKeyringKeyProvider, PINNED_KEYRING_VERSION, PKCE_CHARSET, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, createOAuthFlow, createProfileStore, decryptString, dedent, domainUsesAccess, encryptString, findKeyringBinding, generateAuthUrl, generateKey, generateRandomState, generateVerificationUrl, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, parseFile, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner, stringifyFile, validateAccountId, validateProfileName };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stringifyFile, parseFile, dedent, createCredentialStorageContext, createOAuthFlow, getAuthFromEnv, createProfileStore, getCloudflareAccountIdFromEnv, getAuthConfigFilePath, getEncryptedAuthConfigFilePath, scrubEncryptedCredentials, validateProfileName, getCloudflareAuthUseKeyringFromEnv } from './chunk-
|
|
1
|
+
import { stringifyFile, parseFile, dedent, createCredentialStorageContext, createOAuthFlow, getAuthFromEnv, createProfileStore, validateAccountId, getCloudflareAccountIdFromEnv, getAuthConfigFilePath, getEncryptedAuthConfigFilePath, scrubEncryptedCredentials, validateProfileName, getCloudflareAuthUseKeyringFromEnv } from './chunk-7AYQ2BAF.mjs';
|
|
2
2
|
import { __name } from './chunk-O6YSETKJ.mjs';
|
|
3
3
|
import { existsSync, rmSync, mkdirSync, writeFileSync, chmodSync, readFileSync as readFileSync$1, readdirSync } from 'node:fs';
|
|
4
4
|
import path3 from 'node:path';
|
|
@@ -810,6 +810,8 @@ Run \`${descriptor.commands.whoami}\` to check your current authentication statu
|
|
|
810
810
|
purgeOnLoginOrLogout: configCache.purgeConfigCaches,
|
|
811
811
|
clientId: descriptor.clientId,
|
|
812
812
|
consent: descriptor.consent,
|
|
813
|
+
displayName: descriptor.displayName,
|
|
814
|
+
deviceLoginCommand: descriptor.commands.deviceLogin,
|
|
813
815
|
redirectUri: descriptor.redirectUri,
|
|
814
816
|
storageFactory: credentialStorage.storageFactory,
|
|
815
817
|
allowGlobalAuthKey,
|
|
@@ -855,7 +857,8 @@ Run \`${descriptor.commands.whoami}\` to check your current authentication statu
|
|
|
855
857
|
browser: props?.browser ?? true,
|
|
856
858
|
callbackHost: props?.callbackHost,
|
|
857
859
|
callbackPort: props?.callbackPort,
|
|
858
|
-
profile: props?.profile
|
|
860
|
+
profile: props?.profile,
|
|
861
|
+
device: props?.device
|
|
859
862
|
};
|
|
860
863
|
}
|
|
861
864
|
__name(withDefaultScopes, "withDefaultScopes");
|
|
@@ -1012,7 +1015,10 @@ Alternatively, try running \`${descriptor.commands.login}\` to re-authenticate.`
|
|
|
1012
1015
|
return temporaryAccount.account.id;
|
|
1013
1016
|
}
|
|
1014
1017
|
if (config.account_id) {
|
|
1015
|
-
return
|
|
1018
|
+
return validateAccountId(
|
|
1019
|
+
config.account_id,
|
|
1020
|
+
`set as \`account_id\` in your ${descriptor.getConfigFileLabel()} file`
|
|
1021
|
+
);
|
|
1016
1022
|
}
|
|
1017
1023
|
const envAccountId = getCloudflareAccountIdFromEnv();
|
|
1018
1024
|
if (envAccountId) {
|
|
@@ -174,6 +174,18 @@ interface OAuthFlowContext {
|
|
|
174
174
|
* or denies consent.
|
|
175
175
|
*/
|
|
176
176
|
consent: OAuthConsentPages;
|
|
177
|
+
/**
|
|
178
|
+
* The consuming CLI's branded name (e.g. `"Wrangler"`, `"cf"`), interpolated
|
|
179
|
+
* into the copy the flow prints to the user — "To authorize <name>, please
|
|
180
|
+
* visit ...". Consumer-specific, so it is required.
|
|
181
|
+
*/
|
|
182
|
+
displayName: string;
|
|
183
|
+
/**
|
|
184
|
+
* The command that restarts the device authorization flow (e.g.
|
|
185
|
+
* `"wrangler login --device"`), quoted when a device code is denied,
|
|
186
|
+
* expires, or the flow times out. Consumer-specific, so it is required.
|
|
187
|
+
*/
|
|
188
|
+
deviceLoginCommand: string;
|
|
177
189
|
/**
|
|
178
190
|
* The `redirect_uri` registered on the consumer's OAuth app
|
|
179
191
|
*/
|
|
@@ -271,6 +283,16 @@ interface LoginProps {
|
|
|
271
283
|
* Only for use by 'auth create', not exposed to the user
|
|
272
284
|
*/
|
|
273
285
|
profile?: string;
|
|
286
|
+
/**
|
|
287
|
+
* When `true`, authenticate using the OAuth 2.0 Device Authorization Grant
|
|
288
|
+
* (RFC 8628) instead of the authorization-code-with-PKCE callback flow. The
|
|
289
|
+
* device flow does not start a local callback server and works in
|
|
290
|
+
* environments where the consumer's loopback callback URL
|
|
291
|
+
* ({@link OAuthFlowContext.redirectUri}) is unreachable from the user's
|
|
292
|
+
* browser (containers, remote SSH sessions, Codespaces). `callbackHost` and
|
|
293
|
+
* `callbackPort` are ignored when this is set.
|
|
294
|
+
*/
|
|
295
|
+
device?: boolean;
|
|
274
296
|
}
|
|
275
297
|
/**
|
|
276
298
|
* Public surface returned by {@link createOAuthFlow}.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OAuthFlowLogger, U as UserAuthConfig, A as AuthConfigStorage, C as CredentialStore, F as FileFormat } from './file-format-
|
|
2
|
-
export { a as ConfigStorage, D as DeactivateDirectoryResult, i as DirectoryBindingOperations, j as DirectoryBindingsStorage, L as LoginOrRefreshFailureReason, d as LoginOrRefreshResult, e as LoginProps, b as OAuthFlowContext, P as ProfileConfigOperations, k as ProfileStore, T as TemporaryPreviewAccount, c as createOAuthFlow, h as createProfileStore, g as generateAuthUrl, f as generateRandomState, v as validateProfileName } from './file-format-
|
|
1
|
+
import { O as OAuthFlowLogger, U as UserAuthConfig, A as AuthConfigStorage, C as CredentialStore, F as FileFormat } from './file-format-Dbmn5hhd.mjs';
|
|
2
|
+
export { a as ConfigStorage, D as DeactivateDirectoryResult, i as DirectoryBindingOperations, j as DirectoryBindingsStorage, L as LoginOrRefreshFailureReason, d as LoginOrRefreshResult, e as LoginProps, b as OAuthFlowContext, P as ProfileConfigOperations, k as ProfileStore, T as TemporaryPreviewAccount, c as createOAuthFlow, h as createProfileStore, g as generateAuthUrl, f as generateRandomState, v as validateProfileName } from './file-format-Dbmn5hhd.mjs';
|
|
3
3
|
import { ApiCredentials } from '@cloudflare/workers-utils';
|
|
4
4
|
import { SpawnSyncReturns } from 'node:child_process';
|
|
5
5
|
|
|
@@ -81,8 +81,13 @@ declare const getAuthUrlFromEnv: () => string;
|
|
|
81
81
|
* This is a Cloudflare-wide variable (not wrangler-specific), so it lives in the
|
|
82
82
|
* shared core rather than a consumer layer. `CF_ACCOUNT_ID` is the deprecated
|
|
83
83
|
* spelling.
|
|
84
|
+
*
|
|
85
|
+
* Every caller feeds the result into a Cloudflare API URL path, so the value is
|
|
86
|
+
* validated here rather than at each call site. An empty string is treated as
|
|
87
|
+
* unset so callers keep falling back to the cached / interactively selected
|
|
88
|
+
* account.
|
|
84
89
|
*/
|
|
85
|
-
declare
|
|
90
|
+
declare function getCloudflareAccountIdFromEnv(): string | undefined;
|
|
86
91
|
/**
|
|
87
92
|
* `CLOUDFLARE_AUTH_USE_KEYRING` overrides where OAuth credentials are stored.
|
|
88
93
|
*
|
|
@@ -98,6 +103,25 @@ declare const getCloudflareAccountIdFromEnv: () => string | undefined;
|
|
|
98
103
|
*/
|
|
99
104
|
declare const getCloudflareAuthUseKeyringFromEnv: () => boolean | undefined;
|
|
100
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Build the URL the user should visit to approve a device authorization
|
|
108
|
+
* request, with the `user_code` embedded as a query parameter so the user
|
|
109
|
+
* does not have to type it manually.
|
|
110
|
+
*
|
|
111
|
+
* Per RFC 8628 §3.3.1, this is the "verification_uri_complete" optimization
|
|
112
|
+
* for non-textual transmission (such as QR codes). Authorization servers may
|
|
113
|
+
* return their own `verification_uri_complete` in the device authorization
|
|
114
|
+
* response — prefer that when it is provided. Use this helper as a fallback
|
|
115
|
+
* when only `verification_uri` is available.
|
|
116
|
+
*
|
|
117
|
+
* Extracted into its own module (mirroring `generate-auth-url.ts`) so that
|
|
118
|
+
* tests can mock the generated URL deterministically.
|
|
119
|
+
*/
|
|
120
|
+
declare const generateVerificationUrl: ({ verificationUri, userCode, }: {
|
|
121
|
+
verificationUri: string;
|
|
122
|
+
userCode: string;
|
|
123
|
+
}) => string;
|
|
124
|
+
|
|
101
125
|
declare const TEMPORARY_TERMS_PROMPT: string;
|
|
102
126
|
declare const TEMPORARY_TERMS_NOTICE: string;
|
|
103
127
|
|
|
@@ -785,4 +809,4 @@ declare function decryptString(envelope: EncryptedEnvelope, key: Uint8Array): st
|
|
|
785
809
|
*/
|
|
786
810
|
declare function parseEncryptedEnvelope(raw: unknown): EncryptedEnvelope | undefined;
|
|
787
811
|
|
|
788
|
-
export { AuthConfigStorage, type CredentialStorageBundle, type CredentialStorageContext, CredentialStore, type EncryptedEnvelope, EncryptedFileCredentialStore, FileCredentialStore, type KeyProvider, type KeyProviderResolution, type KeyringEntry, type KeyringEntryFactory, LinuxSecretToolKeyProvider, type LinuxSecretToolRunner, type MacSecurityCommandRunner, MacSecurityKeyProvider, NapiKeyringKeyProvider, type NpmRunner, OAuthFlowLogger, PINNED_KEYRING_VERSION, PKCE_CHARSET, type ScrubEncryptedCredentialsResult, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, UserAuthConfig, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, decryptString, domainUsesAccess, encryptString, findKeyringBinding, generateKey, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner };
|
|
812
|
+
export { AuthConfigStorage, type CredentialStorageBundle, type CredentialStorageContext, CredentialStore, type EncryptedEnvelope, EncryptedFileCredentialStore, FileCredentialStore, type KeyProvider, type KeyProviderResolution, type KeyringEntry, type KeyringEntryFactory, LinuxSecretToolKeyProvider, type LinuxSecretToolRunner, type MacSecurityCommandRunner, MacSecurityKeyProvider, NapiKeyringKeyProvider, type NpmRunner, OAuthFlowLogger, PINNED_KEYRING_VERSION, PKCE_CHARSET, type ScrubEncryptedCredentialsResult, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, UserAuthConfig, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, decryptString, domainUsesAccess, encryptString, findKeyringBinding, generateKey, generateVerificationUrl, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { EncryptedFileCredentialStore, FileCredentialStore, LinuxSecretToolKeyProvider, MacSecurityKeyProvider, NapiKeyringKeyProvider, PINNED_KEYRING_VERSION, PKCE_CHARSET, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, createOAuthFlow, createProfileStore, decryptString, domainUsesAccess, encryptString, findKeyringBinding, generateAuthUrl, generateKey, generateRandomState, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner, validateProfileName } from './chunk-
|
|
1
|
+
export { EncryptedFileCredentialStore, FileCredentialStore, LinuxSecretToolKeyProvider, MacSecurityKeyProvider, NapiKeyringKeyProvider, PINNED_KEYRING_VERSION, PKCE_CHARSET, TEMPORARY_TERMS_NOTICE, TEMPORARY_TERMS_PROMPT, clearAccessCaches, clearCredentialStorageState, createCredentialStorageContext, createOAuthFlow, createProfileStore, decryptString, domainUsesAccess, encryptString, findKeyringBinding, generateAuthUrl, generateKey, generateRandomState, generateVerificationUrl, getAccessHeaders, getAuthConfigFilePath, getAuthFromEnv, getAuthUrlFromEnv, getCloudflareAPITokenFromEnv, getCloudflareAccountIdFromEnv, getCloudflareAuthUseKeyringFromEnv, getCloudflareGlobalAuthEmailFromEnv, getCloudflareGlobalAuthKeyFromEnv, getEncryptedAuthConfigFilePath, getKeyringAccountName, getKeyringInstallDir, installKeyringBindingSync, parseEncryptedEnvelope, probeSecretTool, readStoredAuthState, resetCredentialStorageState, resolveKeyProvider, scrubEncryptedCredentials, setKeyProviderFactoryForTesting, setKeyringEntryFactory, setLinuxSecretToolRunner, setMacSecurityCommandRunner, setNpmRunner, validateProfileName } from './chunk-7AYQ2BAF.mjs';
|
|
2
2
|
import './chunk-O6YSETKJ.mjs';
|