Skip to content

Commit 8aafba5

Browse files
blvafmenezes
authored andcommitted
fix: fix token retrieval between tool calls
1 parent c5c9e88 commit 8aafba5

File tree

4 files changed

+92
-31
lines changed

4 files changed

+92
-31
lines changed

dist/auth.js

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,20 @@ export function getToken() {
107107
}
108108
function loadToken() {
109109
if (fs.existsSync(TOKEN_FILE)) {
110-
const data = JSON.parse(fs.readFileSync(TOKEN_FILE, "utf-8"));
111-
authState.token = data.token;
112-
globalState.auth = true;
113-
log("info", "Token loaded from file.");
114-
return data;
110+
try {
111+
const data = JSON.parse(fs.readFileSync(TOKEN_FILE, "utf-8"));
112+
// Extract the token property from the data object
113+
if (data && data.token) {
114+
authState.token = data.token;
115+
globalState.auth = true;
116+
log("info", "Token loaded from file.");
117+
return data;
118+
}
119+
log("info", "Token file exists but doesn't contain a valid token structure");
120+
}
121+
catch (error) {
122+
log("error", `Error parsing token file: ${error}`);
123+
}
115124
}
116125
return undefined;
117126
}
@@ -126,33 +135,54 @@ export async function isAuthenticated() {
126135
loadToken();
127136
}
128137
if (!authState.token) {
138+
log("info", "No token found after loading");
129139
return false;
130140
}
131141
// Validate the existing token
132142
try {
133-
const isValid = await validateToken(authState.token);
134-
if (isValid) {
143+
log("info", "Validating token...");
144+
if (validateToken(authState.token)) {
135145
return true;
136146
}
137147
// If the token is invalid, attempt to refresh it
138-
const refreshedToken = await refreshToken(authState.token.access_token);
148+
log("info", "Token is invalid, refreshing...");
149+
const refreshedToken = await refreshToken(authState.token.refresh_token);
139150
if (refreshedToken) {
140151
authState.token = refreshedToken;
141152
globalState.auth = true;
153+
log("info", "Token refreshed successfully.");
142154
saveToken(refreshedToken);
143155
return true;
144156
}
157+
log("error", "Failed to refresh token.");
145158
}
146159
catch (error) {
147160
log("error", `Error during token validation or refresh: ${error}`);
148161
}
149162
globalState.auth = false;
150163
return false;
151164
}
152-
async function validateToken(tokenData) {
165+
function validateToken(tokenData) {
153166
try {
154-
const expiryDate = new Date(tokenData.expiry);
155-
return expiryDate > new Date(); // Token is valid if expiry is in the future
167+
// First check if token exists and has an access token (similar to Go's Valid() function)
168+
if (!tokenData || !tokenData.access_token) {
169+
return false;
170+
}
171+
// If expiry is zero value (not set), consider token not expired (like in Go)
172+
if (!tokenData.expiry) {
173+
return true;
174+
}
175+
// Match the Go code's expiryDelta concept (10 seconds)
176+
const expiryDelta = 10 * 1000; // 10 seconds in milliseconds
177+
// Calculate if token is expired using the same logic as Go code:
178+
// return t.Expiry.Round(0).Add(-expiryDelta).Before(time.Now())
179+
const expiryWithDelta = new Date(new Date(tokenData.expiry).getTime() - expiryDelta);
180+
// Token is valid if expiry time minus delta is after current time
181+
// log to debug
182+
log("info", `Token expiry time: ${expiryWithDelta}`);
183+
log("info", `Current time: ${Date.now()}`);
184+
log("info", `Token is valid: ${expiryWithDelta.getTime() > Date.now()}`);
185+
return expiryWithDelta.getTime() > Date.now();
156186
}
157187
catch (error) {
158188
log("error", `Error validating token: ${error}`);
@@ -176,12 +206,12 @@ async function refreshToken(token) {
176206
}).toString(),
177207
});
178208
if (response.ok) {
179-
const data = (await response.json());
209+
const data = await response.json();
180210
return data;
181211
}
182212
}
183213
catch (error) {
184-
log("error", `Error refreshing token: ${error}`);
214+
log("info", `Error refreshing token: ${error}`);
185215
}
186216
return null;
187217
}

dist/tools.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export function defineTools(server, globalState) {
2020
};
2121
}
2222
try {
23-
// Step 1: Generate the device code
2423
const { verificationUri, userCode } = await authenticate();
2524
// Inform the user to authenticate
2625
const initialResponse = {

src/auth.ts

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface OAuthToken {
3131
id_token: string;
3232
token_type: string;
3333
expires_in: number;
34-
expiry: string; // ISO string representation of expiry time
34+
expiry: Date;
3535
}
3636

3737

@@ -144,11 +144,19 @@ export function getToken(): OAuthToken | undefined {
144144

145145
function loadToken(): { token?: OAuthToken } | undefined {
146146
if (fs.existsSync(TOKEN_FILE)) {
147-
const data = JSON.parse(fs.readFileSync(TOKEN_FILE, "utf-8"));
148-
authState.token = data.token;
149-
globalState.auth = true;
150-
log("info", "Token loaded from file.");
151-
return data;
147+
try {
148+
const data = JSON.parse(fs.readFileSync(TOKEN_FILE, "utf-8"));
149+
// Extract the token property from the data object
150+
if (data && data.token) {
151+
authState.token = data.token;
152+
globalState.auth = true;
153+
log("info", "Token loaded from file.");
154+
return data;
155+
}
156+
log("info", "Token file exists but doesn't contain a valid token structure");
157+
} catch (error) {
158+
log("error", `Error parsing token file: ${error}`);
159+
}
152160
}
153161
return undefined;
154162
}
@@ -166,37 +174,63 @@ export async function isAuthenticated(): Promise<boolean> {
166174
}
167175

168176
if (!authState.token) {
177+
log("info", "No token found after loading");
169178
return false;
170179
}
171180

172181
// Validate the existing token
173182
try {
174-
const isValid = await validateToken(authState.token);
175-
if (isValid) {
183+
log("info", "Validating token...");
184+
if (validateToken(authState.token)) {
176185
return true;
177186
}
178187

179188
// If the token is invalid, attempt to refresh it
180-
const refreshedToken = await refreshToken(authState.token.access_token);
189+
log("info", "Token is invalid, refreshing...");
190+
const refreshedToken = await refreshToken(authState.token.refresh_token);
181191
if (refreshedToken) {
182192
authState.token = refreshedToken;
183193
globalState.auth = true;
194+
log("info", "Token refreshed successfully.");
184195
saveToken(refreshedToken);
185196
return true;
186197
}
198+
log("error", "Failed to refresh token.");
187199
} catch (error) {
188200
log("error", `Error during token validation or refresh: ${error}`);
189201
}
190202

191-
192203
globalState.auth = false;
193204
return false;
194205
}
195206

196-
async function validateToken(tokenData: OAuthToken): Promise<boolean> {
207+
function validateToken(tokenData: OAuthToken): boolean {
197208
try {
198-
const expiryDate = new Date(tokenData.expiry);
199-
return expiryDate > new Date(); // Token is valid if expiry is in the future
209+
// First check if token exists and has an access token (similar to Go's Valid() function)
210+
if (!tokenData || !tokenData.access_token) {
211+
return false;
212+
}
213+
214+
// If expiry is zero value (not set), consider token not expired (like in Go)
215+
if (!tokenData.expiry) {
216+
return true;
217+
}
218+
219+
// Match the Go code's expiryDelta concept (10 seconds)
220+
const expiryDelta = 10 * 1000; // 10 seconds in milliseconds
221+
222+
// Calculate if token is expired using the same logic as Go code:
223+
// return t.Expiry.Round(0).Add(-expiryDelta).Before(time.Now())
224+
const expiryWithDelta = new Date(
225+
new Date(tokenData.expiry).getTime() - expiryDelta
226+
);
227+
228+
// Token is valid if expiry time minus delta is after current time
229+
// log to debug
230+
log("info", `Token expiry time: ${expiryWithDelta}`);
231+
log("info", `Current time: ${Date.now()}`);
232+
log("info", `Token is valid: ${expiryWithDelta.getTime() > Date.now()}`);
233+
return expiryWithDelta.getTime() > Date.now();
200234
} catch (error) {
201235
log("error", `Error validating token: ${error}`);
202236
return false;
@@ -221,11 +255,11 @@ async function refreshToken(token: string): Promise<OAuthToken | null> {
221255
});
222256

223257
if (response.ok) {
224-
const data = (await response.json()) as OAuthToken;
258+
const data = await response.json() as OAuthToken;
225259
return data;
226260
}
227261
} catch (error) {
228-
log("error", `Error refreshing token: ${error}`);
262+
log("info", `Error refreshing token: ${error}`);
229263
}
230264
return null;
231265
}

src/tools.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ async function ensureAuthenticated() {
1717
export function defineTools(server: any, globalState: GlobalState) {
1818
server.tool("auth", "Authenticate to Atlas", async ({}) => {
1919
const authResult = await isAuthenticated();
20-
2120
if (authResult) {
2221
log("info", "Already authenticated!");
2322
return {
@@ -26,7 +25,6 @@ export function defineTools(server: any, globalState: GlobalState) {
2625
}
2726

2827
try {
29-
// Step 1: Generate the device code
3028
const { verificationUri, userCode } = await authenticate();
3129

3230
// Inform the user to authenticate

0 commit comments

Comments
 (0)