fix(kiro-auth): check refresh token instead of access token expiration

This commit is contained in:
Jaime Abril 2026-01-26 23:21:44 +01:00
parent 7064c2fc7e
commit 540d06068a
No known key found for this signature in database
2 changed files with 33 additions and 24 deletions

View File

@ -172,26 +172,14 @@ const DEFAULT_EXPIRATION_BUFFER_MS = 5 * 60 * 1000;
/** /**
* Checks if a token is expired or about to expire. * Checks if a token is expired or about to expire.
* *
* A token is considered expired if the current time plus the buffer * Note: This checks the access_token expiration. Even if the access token
* is greater than or equal to the expiration time. This ensures we * is expired, kiro-cli can still work if the refresh_token is valid.
* don't attempt to use a token that will expire during an operation. * We use this primarily for informational purposes - kiro-cli handles
* the actual token refresh internally.
* *
* @param token The token to check * @param token The token to check
* @param bufferMs Buffer time before expiration (default: 5 minutes / 300000ms) * @param bufferMs Buffer time before expiration (default: 5 minutes / 300000ms)
* @returns true if token is expired or expires within buffer * @returns true if token is expired or expires within buffer
*
* @example
* ```ts
* const token = extractKiroCliToken();
* if (token && isTokenExpired(token)) {
* console.log("Token expired, please re-authenticate");
* }
*
* // With custom buffer (1 minute)
* if (token && isTokenExpired(token, 60000)) {
* console.log("Token expires within 1 minute");
* }
* ```
*/ */
export function isTokenExpired( export function isTokenExpired(
token: KiroCliToken, token: KiroCliToken,
@ -200,6 +188,24 @@ export function isTokenExpired(
const expirationTime = new Date(token.expires_at).getTime(); const expirationTime = new Date(token.expires_at).getTime();
const currentTime = Date.now(); const currentTime = Date.now();
// Handle invalid date parsing (NaN)
if (Number.isNaN(expirationTime)) {
// If we can't parse the expiration, assume token is valid
// and let kiro-cli handle the actual validation
return false;
}
// Token is expired if current time + buffer >= expiration time // Token is expired if current time + buffer >= expiration time
return currentTime + bufferMs >= expirationTime; return currentTime + bufferMs >= expirationTime;
} }
/**
* Checks if a token has a valid refresh token that kiro-cli can use.
* Even if the access token is expired, kiro-cli can refresh it.
*
* @param token The token to check
* @returns true if the token has a refresh token
*/
export function hasValidRefreshToken(token: KiroCliToken): boolean {
return Boolean(token.refresh_token && token.refresh_token.length > 0);
}

View File

@ -1,6 +1,9 @@
import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk"; import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
import { extractKiroCliToken, isTokenExpired } from "./cli-credentials.js"; import {
extractKiroCliToken,
hasValidRefreshToken,
} from "./cli-credentials.js";
import { findKiroCli } from "./cli-detector.js"; import { findKiroCli } from "./cli-detector.js";
const PROVIDER_ID = "kiro-cli"; const PROVIDER_ID = "kiro-cli";
@ -60,16 +63,16 @@ const kiroPlugin = {
); );
} }
// Check token not expired // Check we have a refresh token (kiro-cli handles access token refresh)
if (isTokenExpired(token)) { if (!hasValidRefreshToken(token)) {
spin.stop("Token expired"); spin.stop("Invalid credentials");
await ctx.prompter.note( await ctx.prompter.note(
"Your kiro-cli token has expired.\n" + "Your kiro-cli credentials are incomplete.\n" +
"Run `kiro-cli chat` to re-authenticate.", "Run `kiro-cli chat` to re-authenticate.",
"Re-authentication required", "Re-authentication required",
); );
throw new Error( throw new Error(
"kiro-cli token expired. Run `kiro-cli chat` to refresh.", "kiro-cli credentials incomplete. Run `kiro-cli chat` to refresh.",
); );
} }
@ -101,9 +104,9 @@ const kiroPlugin = {
refreshOAuth: async (cred) => { refreshOAuth: async (cred) => {
// Re-read token from SQLite - kiro-cli handles the actual OAuth refresh // Re-read token from SQLite - kiro-cli handles the actual OAuth refresh
const token = extractKiroCliToken(); const token = extractKiroCliToken();
if (!token || isTokenExpired(token)) { if (!token || !hasValidRefreshToken(token)) {
throw new Error( throw new Error(
"kiro-cli token expired. Run `kiro-cli chat` to refresh.", "kiro-cli credentials invalid. Run `kiro-cli chat` to refresh.",
); );
} }
return { return {