Skip to content

Commit 14a2dfe

Browse files
committed
fix(auth): handle revocation and file removal errors properly
Warn the user when token revocation fails (network error or non-200 response) so they know the old token may still be valid server-side. Return errors when credential/cache file removal fails (ignoring NotFound) instead of silently continuing with stale files.
1 parent ec96752 commit 14a2dfe

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

src/auth_commands.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,22 +331,51 @@ async fn handle_login(args: &[String]) -> Result<(), GwsError> {
331331
let prev_set: HashSet<&str> = prev_scopes.iter().map(|s| s.as_str()).collect();
332332
let new_set: HashSet<&str> = scopes.iter().map(|s| s.as_str()).collect();
333333
if prev_set != new_set {
334-
// Best-effort revocation: load the old refresh token and revoke it.
334+
// Revoke the old refresh token so Google removes the prior consent grant.
335335
if let Ok(creds_str) = credential_store::load_encrypted() {
336336
if let Ok(creds) = serde_json::from_str::<serde_json::Value>(&creds_str) {
337337
if let Some(rt) = creds.get("refresh_token").and_then(|v| v.as_str()) {
338338
let client = reqwest::Client::new();
339-
let _ = client
339+
match client
340340
.post("https://oauth2.googleapis.com/revoke")
341341
.form(&[("token", rt)])
342342
.send()
343-
.await;
343+
.await
344+
{
345+
Ok(resp) if resp.status().is_success() => {}
346+
Ok(resp) => {
347+
eprintln!(
348+
"Warning: token revocation returned HTTP {}. \
349+
The old token may still be valid on Google's side.",
350+
resp.status()
351+
);
352+
}
353+
Err(e) => {
354+
eprintln!(
355+
"Warning: could not revoke old token ({e}). \
356+
The old token may still be valid on Google's side."
357+
);
358+
}
359+
}
344360
}
345361
}
346362
}
347-
// Clear local credential and cache files regardless of revocation result.
348-
let _ = std::fs::remove_file(credential_store::encrypted_credentials_path());
349-
let _ = std::fs::remove_file(token_cache_path());
363+
// Clear local credential and cache files to force a fresh login.
364+
let enc_path = credential_store::encrypted_credentials_path();
365+
if let Err(e) = std::fs::remove_file(&enc_path) {
366+
if e.kind() != std::io::ErrorKind::NotFound {
367+
return Err(GwsError::Auth(format!(
368+
"Failed to remove old credentials file: {e}. Please remove it manually."
369+
)));
370+
}
371+
}
372+
if let Err(e) = std::fs::remove_file(token_cache_path()) {
373+
if e.kind() != std::io::ErrorKind::NotFound {
374+
return Err(GwsError::Auth(format!(
375+
"Failed to remove old token cache: {e}. Please remove it manually."
376+
)));
377+
}
378+
}
350379
eprintln!("Scopes changed — revoked previous credentials.");
351380
}
352381
}

0 commit comments

Comments
 (0)