Restore interactive re-auth prompt for Google auth CLIs

This commit is contained in:
William Valentin
2026-02-17 16:19:12 -08:00
parent 9c9ab92e9d
commit 061b96fd68
5 changed files with 70 additions and 10 deletions
+13 -1
View File
@@ -135,6 +135,15 @@ async function openBrowser(url: string): Promise<boolean> {
}); });
} }
async function promptYesNo(question: string): Promise<boolean> {
const readline = await import('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
rl.close();
const normalized = answer.trim().toLowerCase();
return normalized === 'y' || normalized === 'yes';
}
/** Manual code entry via stdin. */ /** Manual code entry via stdin. */
async function promptForCode(): Promise<string> { async function promptForCode(): Promise<string> {
const readline = await import('readline'); const readline = await import('readline');
@@ -182,9 +191,12 @@ export function registerGcalAuthCommand(program: Command): void {
// 3. Check if already authenticated // 3. Check if already authenticated
if (existsSync(tokenPath)) { if (existsSync(tokenPath)) {
console.log(`Token already exists at ${tokenPath}`); console.log(`Token already exists at ${tokenPath}`);
console.log('Delete it first if you want to re-authenticate.'); const confirmed = await promptYesNo('Re-authenticate and replace it? (y/N): ');
if (!confirmed) {
console.log('Cancelled.');
process.exit(0); process.exit(0);
} }
}
const redirectUri = opts.manual const redirectUri = opts.manual
? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob') ? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob')
+13 -1
View File
@@ -138,6 +138,15 @@ async function openBrowser(url: string): Promise<boolean> {
}); });
} }
async function promptYesNo(question: string): Promise<boolean> {
const readline = await import('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
rl.close();
const normalized = answer.trim().toLowerCase();
return normalized === 'y' || normalized === 'yes';
}
/** Manual code entry via stdin. */ /** Manual code entry via stdin. */
async function promptForCode(): Promise<string> { async function promptForCode(): Promise<string> {
const readline = await import('readline'); const readline = await import('readline');
@@ -185,9 +194,12 @@ export function registerGdocsAuthCommand(program: Command): void {
// 3. Check if already authenticated // 3. Check if already authenticated
if (existsSync(tokenPath)) { if (existsSync(tokenPath)) {
console.log(`Token already exists at ${tokenPath}`); console.log(`Token already exists at ${tokenPath}`);
console.log('Delete it first if you want to re-authenticate.'); const confirmed = await promptYesNo('Re-authenticate and replace it? (y/N): ');
if (!confirmed) {
console.log('Cancelled.');
process.exit(0); process.exit(0);
} }
}
const redirectUri = opts.manual const redirectUri = opts.manual
? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob') ? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob')
+13 -1
View File
@@ -135,6 +135,15 @@ async function openBrowser(url: string): Promise<boolean> {
}); });
} }
async function promptYesNo(question: string): Promise<boolean> {
const readline = await import('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
rl.close();
const normalized = answer.trim().toLowerCase();
return normalized === 'y' || normalized === 'yes';
}
/** Manual code entry via stdin. */ /** Manual code entry via stdin. */
async function promptForCode(): Promise<string> { async function promptForCode(): Promise<string> {
const readline = await import('readline'); const readline = await import('readline');
@@ -182,9 +191,12 @@ export function registerGdriveAuthCommand(program: Command): void {
// 3. Check if already authenticated // 3. Check if already authenticated
if (existsSync(tokenPath)) { if (existsSync(tokenPath)) {
console.log(`Token already exists at ${tokenPath}`); console.log(`Token already exists at ${tokenPath}`);
console.log('Delete it first if you want to re-authenticate.'); const confirmed = await promptYesNo('Re-authenticate and replace it? (y/N): ');
if (!confirmed) {
console.log('Cancelled.');
process.exit(0); process.exit(0);
} }
}
const redirectUri = opts.manual const redirectUri = opts.manual
? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob') ? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob')
+13 -1
View File
@@ -135,6 +135,15 @@ async function openBrowser(url: string): Promise<boolean> {
}); });
} }
async function promptYesNo(question: string): Promise<boolean> {
const readline = await import('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
rl.close();
const normalized = answer.trim().toLowerCase();
return normalized === 'y' || normalized === 'yes';
}
/** Manual code entry via stdin. */ /** Manual code entry via stdin. */
async function promptForCode(): Promise<string> { async function promptForCode(): Promise<string> {
const readline = await import('readline'); const readline = await import('readline');
@@ -182,9 +191,12 @@ export function registerGmailAuthCommand(program: Command): void {
// 3. Check if already authenticated // 3. Check if already authenticated
if (existsSync(tokenPath)) { if (existsSync(tokenPath)) {
console.log(`Token already exists at ${tokenPath}`); console.log(`Token already exists at ${tokenPath}`);
console.log('Delete it first if you want to re-authenticate.'); const confirmed = await promptYesNo('Re-authenticate and replace it? (y/N): ');
if (!confirmed) {
console.log('Cancelled.');
process.exit(0); process.exit(0);
} }
}
const redirectUri = opts.manual const redirectUri = opts.manual
? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob') ? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob')
+13 -1
View File
@@ -135,6 +135,15 @@ async function openBrowser(url: string): Promise<boolean> {
}); });
} }
async function promptYesNo(question: string): Promise<boolean> {
const readline = await import('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
const answer = await new Promise<string>((resolve) => rl.question(question, resolve));
rl.close();
const normalized = answer.trim().toLowerCase();
return normalized === 'y' || normalized === 'yes';
}
/** Manual code entry via stdin. */ /** Manual code entry via stdin. */
async function promptForCode(): Promise<string> { async function promptForCode(): Promise<string> {
const readline = await import('readline'); const readline = await import('readline');
@@ -182,9 +191,12 @@ export function registerGtasksAuthCommand(program: Command): void {
// 3. Check if already authenticated // 3. Check if already authenticated
if (existsSync(tokenPath)) { if (existsSync(tokenPath)) {
console.log(`Token already exists at ${tokenPath}`); console.log(`Token already exists at ${tokenPath}`);
console.log('Delete it first if you want to re-authenticate.'); const confirmed = await promptYesNo('Re-authenticate and replace it? (y/N): ');
if (!confirmed) {
console.log('Cancelled.');
process.exit(0); process.exit(0);
} }
}
const redirectUri = opts.manual const redirectUri = opts.manual
? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob') ? (creds.redirect_uris?.[0] ?? 'urn:ietf:wg:oauth:2.0:oob')