Fix unsettled refresh detection after workspace switching (#58381)

## Why

Workspace switching rewrites claims returned by `get_token_data()`, so comparing those tokens with the stored refresh generation can fail to recognize an unfinished ChatGPT refresh.

## What changed

Compare tokens from the current auth JSON with the unsettled refresh generation, preserving detection when workspace claims differ from the original ID token.

## Testing

Extend the refresh cancellation regression test to cover a workspace switch that retains the original ID and refresh tokens.

GitOrigin-RevId: 097311e4cdc22cde875589ef616daf60c6b8ef80
This commit is contained in:
jif
2026-10-30 16:16:57 +00:00
committed by copyberry
parent 1f0290c607
commit b0f977c3a9
2 changed files with 16 additions and 8 deletions
+9 -5
View File
@@ -73,14 +73,18 @@ async fn cancelled_refresh_marks_only_started_exchanges_as_unsettled() -> anyhow
let server = MockServer::start().await;
let storage = FileAuthStorage::new(home.path().to_path_buf());
let mut stored = storage.load()?.context("stored credentials")?;
stored
.tokens
.as_mut()
.context("stored tokens")?
.oauth_provenance = Some(AccountOAuthProvenance {
let tokens = stored.tokens.as_mut().context("stored tokens")?;
tokens.oauth_provenance = Some(AccountOAuthProvenance {
issuer: server.uri(),
client_id: "codex-client".into(),
});
// Workspace switching retains the original ID and refresh tokens.
tokens.account_id = Some(WORKSPACE_ID_SECOND_ALLOWED.into());
tokens.access_token = fake_jwt_for_auth_file_params(&AuthFileParams {
openai_api_key: None,
chatgpt_plan_type: Some("business".into()),
chatgpt_account_id: Some(WORKSPACE_ID_SECOND_ALLOWED.into()),
})?;
storage.save(&stored)?;
let manager = Arc::new(
AuthManager::new_from_auth_config(
+7 -3
View File
@@ -2587,9 +2587,13 @@ impl AuthManager {
.unsettled_chatgpt_refresh
.lock()
.map_err(|_| std::io::Error::other("Refresh progress is unavailable."))?;
Ok(unsettled
.as_ref()
.is_some_and(|tokens| auth.get_token_data().as_ref().ok() == Some(tokens)))
// Match the stored generation; get_token_data() rewrites workspace claims.
Ok(unsettled.as_ref().is_some_and(|tokens| {
auth.get_current_auth_json()
.and_then(|auth| auth.tokens)
.as_ref()
== Some(tokens)
}))
}
/// Current cached auth (clone). May be `None` if not logged in or load failed.