fix(cli): surface tunnel bootstrap connect URL for --try-cf-tunnel (#561)
The CLI tunnel startup generated a bootstrap token but discarded it, then built a URL with ?token=<uiPassword> which the tunnel auth system ignores. Remote users always saw 'Tunnel access required' with no way to authenticate. Capture the bootstrap token, build the /connect?t=... URL, and pass it through onTunnelReady so the CLI prints the correct one-time connect link (and QR code).
This commit is contained in:
@@ -636,10 +636,12 @@ const commands = {
|
|||||||
exitOnShutdown: true,
|
exitOnShutdown: true,
|
||||||
uiPassword: typeof effectiveUiPassword === 'string' ? effectiveUiPassword : null,
|
uiPassword: typeof effectiveUiPassword === 'string' ? effectiveUiPassword : null,
|
||||||
tryCfTunnel: options.tryCfTunnel,
|
tryCfTunnel: options.tryCfTunnel,
|
||||||
onTunnelReady: async (url) => {
|
onTunnelReady: async (url, connectUrl) => {
|
||||||
const displayUrl = buildTunnelUrl(url, effectiveUiPassword, options.tunnelPasswordUrl);
|
const displayUrl = connectUrl || buildTunnelUrl(url, effectiveUiPassword, options.tunnelPasswordUrl);
|
||||||
console.log(`\n🌐 Tunnel URL: \x1b[36m${displayUrl}\x1b[0m\n`);
|
console.log(`\n🌐 Tunnel URL: \x1b[36m${displayUrl}\x1b[0m\n`);
|
||||||
if (options.tunnelPasswordUrl && effectiveUiPassword) {
|
if (connectUrl) {
|
||||||
|
console.log('🔑 One-time connect link (expires after first use)\n');
|
||||||
|
} else if (options.tunnelPasswordUrl && effectiveUiPassword) {
|
||||||
console.log('🔑 Password is embedded in URL for auto-login\n');
|
console.log('🔑 Password is embedded in URL for auto-login\n');
|
||||||
}
|
}
|
||||||
if (options.tunnelQr) {
|
if (options.tunnelQr) {
|
||||||
|
|||||||
@@ -13371,12 +13371,16 @@ async function main(options = {}) {
|
|||||||
const bootstrapTtlMs = settings?.tunnelBootstrapTtlMs === null
|
const bootstrapTtlMs = settings?.tunnelBootstrapTtlMs === null
|
||||||
? null
|
? null
|
||||||
: normalizeTunnelBootstrapTtlMs(settings?.tunnelBootstrapTtlMs);
|
: normalizeTunnelBootstrapTtlMs(settings?.tunnelBootstrapTtlMs);
|
||||||
tunnelAuthController.issueBootstrapToken({ ttlMs: bootstrapTtlMs });
|
const bootstrapToken = tunnelAuthController.issueBootstrapToken({ ttlMs: bootstrapTtlMs });
|
||||||
}
|
const connectUrl = `${tunnelUrl.replace(/\/$/, '')}/connect?t=${encodeURIComponent(bootstrapToken.token)}`;
|
||||||
if (onTunnelReady) {
|
if (onTunnelReady) {
|
||||||
if (tunnelUrl) {
|
onTunnelReady(tunnelUrl, connectUrl);
|
||||||
onTunnelReady(tunnelUrl);
|
} else {
|
||||||
|
console.log(`\n🌐 Tunnel URL: ${connectUrl}`);
|
||||||
|
console.log('🔑 One-time connect link (expires after first use)\n');
|
||||||
}
|
}
|
||||||
|
} else if (onTunnelReady) {
|
||||||
|
onTunnelReady(tunnelUrl, null);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to start Cloudflare tunnel: ${error.message}`);
|
console.error(`Failed to start Cloudflare tunnel: ${error.message}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user