Detect expired Gemini OAuth tokens without refresh credentials

Avoid reporting readiness when the native OAuth client cannot refresh an expired access token.

Checks: 109 Gemini readiness tests; desktop packaging; git diff --check.
This commit is contained in:
Ryder Sun committed 2026-11-07 20:23:29 +08:00
1 parent 71bb4c6eda
commit 8c01e2d150
2 files changed
+12 -2

No files matched your search

+6 -2
View File
@@ -115,8 +115,12 @@ function geminiOAuthCredentialsPresent(filename) {
const contents = readCredentialFile(filename)
if (!contents) return false
const credentials = JSON.parse(contents)
return Boolean(credentials && typeof credentials === 'object' && !Array.isArray(credentials)
&& (credentialLiteral(credentials.access_token) || credentialLiteral(credentials.refresh_token)))
if (!credentials || typeof credentials !== 'object' || Array.isArray(credentials)) return false
if (credentialLiteral(credentials.refresh_token)) return true
if (!credentialLiteral(credentials.access_token)) return false
if (credentials.expiry_date == null || credentials.expiry_date === 0) return true
return typeof credentials.expiry_date === 'number' && Number.isFinite(credentials.expiry_date)
&& credentials.expiry_date > Date.now() + 5 * 60 * 1000
} catch { return false }
}
@@ -42,6 +42,12 @@ test('Gemini readiness checks credentials for its selected auth mode', t => {
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'unknown', source: 'unverified' })
fs.writeFileSync(path.join(root, 'oauth_creds.json'), JSON.stringify({ refresh_token: 'oauth-token' }))
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'ready', source: 'native-credential' })
fs.writeFileSync(path.join(root, 'oauth_creds.json'), JSON.stringify({ access_token: 'expired', expiry_date: Date.now() - 1000 }))
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'unknown', source: 'unverified' })
fs.writeFileSync(path.join(root, 'oauth_creds.json'), JSON.stringify({ access_token: 'fresh', expiry_date: Date.now() + 10 * 60 * 1000 }))
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'ready', source: 'native-credential' })
fs.writeFileSync(path.join(root, 'oauth_creds.json'), JSON.stringify({ access_token: 'expired', refresh_token: 'refresh', expiry_date: Date.now() - 1000 }))
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'ready', source: 'native-credential' })
env.GEMINI_CLI_AUTH_OVERRIDE = 'gemini-api-key'
assert.deepEqual(nativeCredentialState('gemini', { home, env }), { state: 'ready', source: 'native-credential' })
env.GEMINI_CLI_AUTH_OVERRIDE = 'vertex-ai'