opencode-qwen-oauth 1.1.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/logger.js CHANGED
@@ -4,6 +4,14 @@
4
4
  import { appendFileSync, mkdirSync, existsSync } from "node:fs";
5
5
  import { join } from "node:path";
6
6
  import { homedir } from "node:os";
7
+ import { sanitizeLogData } from "./validation.js";
8
+ export var LogLevel;
9
+ (function (LogLevel) {
10
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
11
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
12
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
13
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
14
+ })(LogLevel || (LogLevel = {}));
7
15
  function getLogDir() {
8
16
  const xdgConfig = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
9
17
  return join(xdgConfig, "opencode", "logs");
@@ -17,11 +25,37 @@ function ensureLogDir() {
17
25
  mkdirSync(logDir, { recursive: true, mode: 0o700 });
18
26
  }
19
27
  }
20
- function writeLog(message) {
28
+ function getCurrentLogLevel() {
29
+ const level = process.env.QWEN_OAUTH_LOG_LEVEL?.toUpperCase();
30
+ switch (level) {
31
+ case "ERROR":
32
+ return LogLevel.ERROR;
33
+ case "WARN":
34
+ return LogLevel.WARN;
35
+ case "INFO":
36
+ return LogLevel.INFO;
37
+ case "DEBUG":
38
+ return LogLevel.DEBUG;
39
+ default:
40
+ // Default to INFO, unless DEBUG env var is set
41
+ return process.env.QWEN_OAUTH_DEBUG === "true"
42
+ ? LogLevel.DEBUG
43
+ : LogLevel.INFO;
44
+ }
45
+ }
46
+ function writeLog(level, message, data) {
21
47
  try {
48
+ const currentLevel = getCurrentLogLevel();
49
+ if (level < currentLevel) {
50
+ return; // Skip logs below current level
51
+ }
22
52
  ensureLogDir();
23
53
  const timestamp = new Date().toISOString();
24
- const logLine = `[${timestamp}] ${message}\n`;
54
+ const levelName = LogLevel[level];
55
+ // Sanitize sensitive data
56
+ const sanitizedData = data ? sanitizeLogData(data) : undefined;
57
+ const dataStr = sanitizedData ? ` ${JSON.stringify(sanitizedData)}` : "";
58
+ const logLine = `[${timestamp}] [${levelName}] ${message}${dataStr}\n`;
25
59
  appendFileSync(getLogFilePath(), logLine, { encoding: "utf-8" });
26
60
  }
27
61
  catch {
@@ -31,7 +65,15 @@ function writeLog(message) {
31
65
  export const DEBUG = process.env.QWEN_OAUTH_DEBUG === "true" ||
32
66
  process.env.QWEN_OAUTH_DEBUG === "1";
33
67
  export function debugLog(message, data) {
34
- const logMessage = data ? `${message} ${JSON.stringify(data)}` : message;
35
- writeLog(logMessage);
68
+ writeLog(LogLevel.DEBUG, message, data);
69
+ }
70
+ export function infoLog(message, data) {
71
+ writeLog(LogLevel.INFO, message, data);
72
+ }
73
+ export function warnLog(message, data) {
74
+ writeLog(LogLevel.WARN, message, data);
75
+ }
76
+ export function errorLog(message, data) {
77
+ writeLog(LogLevel.ERROR, message, data);
36
78
  }
37
79
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,SAAS,SAAS;IAChB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY;IACnB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,OAAe;IAC/B,IAAI,CAAC;QACH,YAAY,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC;QAC9C,cAAc,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,MAAM;IACvC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,GAAG,CAAC;AAEvC,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,IAA8B;IACtE,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACzE,QAAQ,CAAC,UAAU,CAAC,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Simple mutex implementation for preventing race conditions
3
+ */
4
+ export declare class Mutex {
5
+ private locked;
6
+ private queue;
7
+ acquire(): Promise<void>;
8
+ release(): void;
9
+ runExclusive<T>(fn: () => Promise<T>): Promise<T>;
10
+ isLocked(): boolean;
11
+ }
12
+ /**
13
+ * Rate limiter to prevent rapid successive calls
14
+ */
15
+ export declare class RateLimiter {
16
+ private lastCall;
17
+ private minInterval;
18
+ constructor(minIntervalMs?: number);
19
+ throttle(): Promise<void>;
20
+ }
21
+ /**
22
+ * Debouncer to prevent rapid repeated calls
23
+ */
24
+ export declare class Debouncer {
25
+ private timeoutId;
26
+ private lastCallTime;
27
+ debounce<T extends (...args: any[]) => any>(fn: T, delayMs?: number): (...args: Parameters<T>) => Promise<ReturnType<T>>;
28
+ getLastCallTime(): number;
29
+ }
30
+ //# sourceMappingURL=mutex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutex.d.ts","sourceRoot":"","sources":["../src/mutex.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAyB;IAEhC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,OAAO,IAAI,IAAI;IAST,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASvD,QAAQ,IAAI,OAAO;CAGpB;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,WAAW,CAAS;gBAEhB,aAAa,GAAE,MAAa;IAIlC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAYhC;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,YAAY,CAAa;IAEjC,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxC,EAAE,EAAE,CAAC,EACL,OAAO,GAAE,MAAY,GACpB,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAoBrD,eAAe,IAAI,MAAM;CAG1B"}
package/dist/mutex.js ADDED
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Simple mutex implementation for preventing race conditions
3
+ */
4
+ import { debugLog } from "./logger.js";
5
+ export class Mutex {
6
+ locked = false;
7
+ queue = [];
8
+ async acquire() {
9
+ return new Promise((resolve) => {
10
+ if (!this.locked) {
11
+ this.locked = true;
12
+ resolve();
13
+ }
14
+ else {
15
+ this.queue.push(resolve);
16
+ }
17
+ });
18
+ }
19
+ release() {
20
+ if (this.queue.length > 0) {
21
+ const resolve = this.queue.shift();
22
+ resolve();
23
+ }
24
+ else {
25
+ this.locked = false;
26
+ }
27
+ }
28
+ async runExclusive(fn) {
29
+ await this.acquire();
30
+ try {
31
+ return await fn();
32
+ }
33
+ finally {
34
+ this.release();
35
+ }
36
+ }
37
+ isLocked() {
38
+ return this.locked;
39
+ }
40
+ }
41
+ /**
42
+ * Rate limiter to prevent rapid successive calls
43
+ */
44
+ export class RateLimiter {
45
+ lastCall = 0;
46
+ minInterval;
47
+ constructor(minIntervalMs = 1000) {
48
+ this.minInterval = minIntervalMs;
49
+ }
50
+ async throttle() {
51
+ const now = Date.now();
52
+ const timeSinceLastCall = now - this.lastCall;
53
+ if (timeSinceLastCall < this.minInterval) {
54
+ const waitTime = this.minInterval - timeSinceLastCall;
55
+ debugLog(`Rate limiting: waiting ${waitTime}ms`);
56
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
57
+ }
58
+ this.lastCall = Date.now();
59
+ }
60
+ }
61
+ /**
62
+ * Debouncer to prevent rapid repeated calls
63
+ */
64
+ export class Debouncer {
65
+ timeoutId = null;
66
+ lastCallTime = 0;
67
+ debounce(fn, delayMs = 500) {
68
+ return (...args) => {
69
+ return new Promise((resolve, reject) => {
70
+ if (this.timeoutId) {
71
+ clearTimeout(this.timeoutId);
72
+ }
73
+ this.timeoutId = setTimeout(async () => {
74
+ try {
75
+ const result = await fn(...args);
76
+ this.lastCallTime = Date.now();
77
+ resolve(result);
78
+ }
79
+ catch (error) {
80
+ reject(error);
81
+ }
82
+ }, delayMs);
83
+ });
84
+ };
85
+ }
86
+ getLastCallTime() {
87
+ return this.lastCallTime;
88
+ }
89
+ }
90
+ //# sourceMappingURL=mutex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutex.js","sourceRoot":"","sources":["../src/mutex.ts"],"names":[],"mappings":"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"}
package/dist/oauth.d.ts CHANGED
@@ -18,4 +18,16 @@ export declare function pollForToken(deviceCode: string, codeVerifier: string, i
18
18
  expires_in?: number;
19
19
  error?: string;
20
20
  }>;
21
+ /**
22
+ * Refresh an expired access token using a refresh token
23
+ * Uses mutex to prevent race conditions when multiple requests
24
+ * try to refresh the token simultaneously
25
+ */
26
+ export declare function refreshAccessToken(refreshToken: string): Promise<{
27
+ success: boolean;
28
+ access_token?: string;
29
+ refresh_token?: string;
30
+ expires_in?: number;
31
+ error?: string;
32
+ }>;
21
33
  //# sourceMappingURL=oauth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yBAAyB,EAAE,MAAM,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiBD,wBAAsB,eAAe,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAiCpE;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA4ED"}
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqCH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yBAAyB,EAAE,MAAM,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAmBD,wBAAsB,eAAe,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAwEpE;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAgKD;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAyGD"}
package/dist/oauth.js CHANGED
@@ -3,8 +3,18 @@
3
3
  */
4
4
  import { QWEN_OAUTH_BASE_URL, QWEN_DEVICE_CODE_ENDPOINT, QWEN_TOKEN_ENDPOINT, QWEN_CLIENT_ID, QWEN_SCOPES, } from "./constants.js";
5
5
  import { createPkcePair } from "./pkce.js";
6
- import { debugLog } from "./logger.js";
6
+ import { debugLog, warnLog } from "./logger.js";
7
+ import { fetchWithRetry } from "./retry.js";
8
+ import { DeviceFlowError, NetworkError, } from "./errors.js";
9
+ import { validateDeviceCode, validateUserCode, validateToken, validateTokenType, validateExpiresIn, validateInterval, validateQwenUrl, validateOAuthError, } from "./validation.js";
10
+ import { getConfig } from "./config.js";
11
+ import { Mutex } from "./mutex.js";
12
+ // Global mutex for token refresh to prevent race conditions
13
+ const tokenRefreshMutex = new Mutex();
14
+ // Track active polling operations
15
+ const activePollingOperations = new Set();
7
16
  export async function authorizeDevice() {
17
+ const config = getConfig();
8
18
  const { verifier, challenge } = createPkcePair();
9
19
  const params = new URLSearchParams({
10
20
  client_id: QWEN_CLIENT_ID,
@@ -12,80 +22,284 @@ export async function authorizeDevice() {
12
22
  code_challenge: challenge,
13
23
  code_challenge_method: "S256",
14
24
  });
15
- const response = await fetch(`${QWEN_OAUTH_BASE_URL}${QWEN_DEVICE_CODE_ENDPOINT}`, {
16
- method: "POST",
17
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
18
- body: params.toString(),
19
- });
20
- if (!response.ok) {
21
- throw new Error(`Failed to start device flow: ${response.statusText}`);
25
+ try {
26
+ const url = `${QWEN_OAUTH_BASE_URL}${QWEN_DEVICE_CODE_ENDPOINT}`;
27
+ debugLog("Requesting device authorization", { url });
28
+ const response = await fetchWithRetry(url, {
29
+ method: "POST",
30
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
31
+ body: params.toString(),
32
+ }, {
33
+ maxRetries: config.maxRetries,
34
+ baseDelay: config.baseRetryDelay,
35
+ maxDelay: config.maxRetryDelay,
36
+ timeout: config.timeout,
37
+ });
38
+ const data = (await response.json());
39
+ // Validate response data
40
+ validateDeviceCode(data.device_code);
41
+ validateUserCode(data.user_code);
42
+ validateExpiresIn(data.expires_in);
43
+ const interval = data.interval || 5;
44
+ validateInterval(interval);
45
+ // Validate URLs
46
+ if (!validateQwenUrl(data.verification_uri)) {
47
+ throw new DeviceFlowError("Invalid verification URI received from server");
48
+ }
49
+ debugLog("Device authorization successful", {
50
+ user_code: data.user_code,
51
+ expires_in: data.expires_in,
52
+ });
53
+ return {
54
+ device_code: data.device_code,
55
+ user_code: data.user_code,
56
+ verification_uri: data.verification_uri,
57
+ verification_uri_complete: data.verification_uri_complete,
58
+ expires_in: data.expires_in,
59
+ interval,
60
+ verifier,
61
+ };
62
+ }
63
+ catch (error) {
64
+ debugLog("Device authorization failed", { error: String(error) });
65
+ if (error instanceof DeviceFlowError || error instanceof NetworkError) {
66
+ throw error;
67
+ }
68
+ throw new DeviceFlowError(`Failed to start device flow: ${error instanceof Error ? error.message : String(error)}`);
22
69
  }
23
- const data = (await response.json());
24
- return {
25
- device_code: data.device_code,
26
- user_code: data.user_code,
27
- verification_uri: data.verification_uri,
28
- verification_uri_complete: data.verification_uri_complete,
29
- expires_in: data.expires_in,
30
- interval: data.interval || 5,
31
- verifier,
32
- };
33
70
  }
34
71
  export async function pollForToken(deviceCode, codeVerifier, intervalSeconds, expiresIn) {
72
+ // Validate inputs
73
+ try {
74
+ validateDeviceCode(deviceCode);
75
+ validateInterval(intervalSeconds);
76
+ validateExpiresIn(expiresIn);
77
+ }
78
+ catch (error) {
79
+ debugLog("Invalid polling parameters", { error: String(error) });
80
+ return {
81
+ success: false,
82
+ error: error instanceof Error ? error.message : "Invalid parameters",
83
+ };
84
+ }
85
+ // Prevent multiple concurrent polling for same device code
86
+ if (activePollingOperations.has(deviceCode)) {
87
+ warnLog("Polling already in progress for this device code", { deviceCode });
88
+ return {
89
+ success: false,
90
+ error: "Authorization already in progress",
91
+ };
92
+ }
93
+ // Register this polling operation
94
+ activePollingOperations.add(deviceCode);
35
95
  const timeoutMs = expiresIn * 1000;
36
96
  const startTime = Date.now();
37
97
  let currentInterval = intervalSeconds * 1000;
98
+ let pollAttempts = 0;
38
99
  debugLog("Starting token polling", { timeoutMs, interval: currentInterval });
100
+ // Ensure cleanup on exit
101
+ const cleanup = () => {
102
+ activePollingOperations.delete(deviceCode);
103
+ };
39
104
  while (Date.now() - startTime < timeoutMs) {
40
105
  await new Promise((resolve) => setTimeout(resolve, currentInterval));
106
+ pollAttempts++;
41
107
  const params = new URLSearchParams({
42
108
  client_id: QWEN_CLIENT_ID,
43
109
  grant_type: "urn:ietf:params:oauth:grant-type:device_code",
44
110
  device_code: deviceCode,
45
111
  code_verifier: codeVerifier,
46
112
  });
47
- debugLog("Polling for token...");
48
- const response = await fetch(`${QWEN_OAUTH_BASE_URL}${QWEN_TOKEN_ENDPOINT}`, {
49
- method: "POST",
50
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
51
- body: params.toString(),
52
- });
53
- if (response.ok) {
113
+ debugLog(`Polling attempt ${pollAttempts}...`);
114
+ try {
115
+ const response = await fetch(`${QWEN_OAUTH_BASE_URL}${QWEN_TOKEN_ENDPOINT}`, {
116
+ method: "POST",
117
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
118
+ body: params.toString(),
119
+ });
120
+ if (response.ok) {
121
+ const data = (await response.json());
122
+ // Validate token response
123
+ try {
124
+ validateToken(data.access_token);
125
+ // For device flow, refresh_token is required on initial auth
126
+ if (!data.refresh_token) {
127
+ throw new Error("No refresh token returned");
128
+ }
129
+ validateToken(data.refresh_token);
130
+ validateExpiresIn(data.expires_in);
131
+ // Validate token_type if provided (optional for compatibility)
132
+ if (data.token_type) {
133
+ validateTokenType(data.token_type);
134
+ }
135
+ }
136
+ catch (validationError) {
137
+ debugLog("Invalid token response", {
138
+ error: String(validationError),
139
+ });
140
+ cleanup();
141
+ return {
142
+ success: false,
143
+ error: "Received invalid token from server",
144
+ };
145
+ }
146
+ debugLog("Token received successfully", { pollAttempts });
147
+ cleanup();
148
+ return {
149
+ success: true,
150
+ access_token: data.access_token,
151
+ refresh_token: data.refresh_token,
152
+ expires_in: data.expires_in,
153
+ };
154
+ }
155
+ // Handle error responses
156
+ const errorData = await response.json().catch(() => ({}));
157
+ const oauthError = validateOAuthError(errorData);
158
+ if (oauthError.error === "authorization_pending") {
159
+ debugLog("Authorization pending, retrying...");
160
+ continue;
161
+ }
162
+ if (oauthError.error === "slow_down") {
163
+ currentInterval += 5000;
164
+ debugLog("Server requested slow down", {
165
+ newInterval: currentInterval,
166
+ });
167
+ continue;
168
+ }
169
+ if (oauthError.error === "expired_token") {
170
+ debugLog("Device code expired");
171
+ cleanup();
172
+ return {
173
+ success: false,
174
+ error: "Device code expired. Please try again.",
175
+ };
176
+ }
177
+ if (oauthError.error === "access_denied") {
178
+ debugLog("User denied authorization");
179
+ cleanup();
180
+ return {
181
+ success: false,
182
+ error: "Authorization was denied",
183
+ };
184
+ }
185
+ debugLog(`Token polling failed: ${oauthError.error}`, {
186
+ description: oauthError.error_description,
187
+ });
188
+ cleanup();
189
+ return {
190
+ success: false,
191
+ error: oauthError.error_description || oauthError.error,
192
+ };
193
+ }
194
+ catch (error) {
195
+ debugLog("Network error during polling", { error: String(error) });
196
+ // Continue polling on network errors
197
+ if (Date.now() - startTime < timeoutMs) {
198
+ continue;
199
+ }
200
+ cleanup();
201
+ return {
202
+ success: false,
203
+ error: "Network error occurred during authentication",
204
+ };
205
+ }
206
+ }
207
+ debugLog("Polling timeout exceeded", { attempts: pollAttempts });
208
+ cleanup();
209
+ return { success: false, error: "Polling timeout - device code expired" };
210
+ }
211
+ /**
212
+ * Refresh an expired access token using a refresh token
213
+ * Uses mutex to prevent race conditions when multiple requests
214
+ * try to refresh the token simultaneously
215
+ */
216
+ export async function refreshAccessToken(refreshToken) {
217
+ // Use mutex to ensure only one refresh happens at a time
218
+ return tokenRefreshMutex.runExclusive(async () => {
219
+ try {
220
+ validateToken(refreshToken);
221
+ }
222
+ catch (error) {
223
+ return {
224
+ success: false,
225
+ error: "Invalid refresh token",
226
+ };
227
+ }
228
+ // Check if a refresh is already in progress
229
+ if (tokenRefreshMutex.isLocked()) {
230
+ debugLog("Token refresh already in progress, waiting...");
231
+ }
232
+ const config = getConfig();
233
+ try {
234
+ const params = new URLSearchParams({
235
+ client_id: QWEN_CLIENT_ID,
236
+ grant_type: "refresh_token",
237
+ refresh_token: refreshToken,
238
+ });
239
+ debugLog("Refreshing access token");
240
+ const response = await fetchWithRetry(`${QWEN_OAUTH_BASE_URL}${QWEN_TOKEN_ENDPOINT}`, {
241
+ method: "POST",
242
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
243
+ body: params.toString(),
244
+ }, {
245
+ maxRetries: config.maxRetries,
246
+ timeout: config.timeout,
247
+ });
248
+ // Check for OAuth error responses
249
+ if (!response.ok) {
250
+ const errorData = await response.json().catch(() => ({}));
251
+ const oauthError = validateOAuthError(errorData);
252
+ debugLog("OAuth error during token refresh", {
253
+ error: oauthError.error,
254
+ description: oauthError.error_description,
255
+ });
256
+ // Handle specific OAuth errors
257
+ if (oauthError.error === "invalid_grant") {
258
+ return {
259
+ success: false,
260
+ error: "Invalid refresh token or client_id",
261
+ };
262
+ }
263
+ if (oauthError.error === "invalid_client") {
264
+ return {
265
+ success: false,
266
+ error: "Invalid client_id",
267
+ };
268
+ }
269
+ return {
270
+ success: false,
271
+ error: oauthError.error_description || oauthError.error || "Token refresh failed",
272
+ };
273
+ }
54
274
  const data = (await response.json());
55
- debugLog("Token received successfully");
275
+ // Validate new tokens
276
+ validateToken(data.access_token);
277
+ validateExpiresIn(data.expires_in);
278
+ // Validate token_type if provided (optional for compatibility)
279
+ if (data.token_type) {
280
+ validateTokenType(data.token_type);
281
+ }
282
+ // Per RFC 6749: refresh_token is optional in refresh response
283
+ // If not provided, continue using the old refresh token
284
+ const newRefreshToken = data.refresh_token || refreshToken;
285
+ validateToken(newRefreshToken);
286
+ debugLog("Token refresh successful", {
287
+ new_refresh_token: !!data.refresh_token,
288
+ });
56
289
  return {
57
290
  success: true,
58
291
  access_token: data.access_token,
59
- refresh_token: data.refresh_token,
292
+ refresh_token: newRefreshToken,
60
293
  expires_in: data.expires_in,
61
294
  };
62
295
  }
63
- const error = (await response.json().catch(() => ({})));
64
- if (error.error === "authorization_pending") {
65
- debugLog("Authorization pending, retrying...");
66
- continue;
67
- }
68
- if (error.error === "slow_down") {
69
- currentInterval += 5000;
70
- debugLog("Server requested slow down, new interval:", {
71
- interval: currentInterval,
72
- });
73
- continue;
74
- }
75
- if (error.error === "expired_token") {
76
- debugLog("Device code expired");
296
+ catch (error) {
297
+ debugLog("Token refresh failed", { error: String(error) });
77
298
  return {
78
299
  success: false,
79
- error: "Device code expired. Please try again.",
300
+ error: error instanceof Error ? error.message : "Token refresh failed",
80
301
  };
81
302
  }
82
- debugLog(`Token polling failed: ${error.error_description || "unknown error"}`);
83
- return {
84
- success: false,
85
- error: error.error_description || "Authentication failed",
86
- };
87
- }
88
- debugLog("Polling timeout exceeded");
89
- return { success: false, error: "Polling timeout - device code expired" };
303
+ });
90
304
  }
91
305
  //# sourceMappingURL=oauth.js.map
package/dist/oauth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Retry logic with exponential backoff for network requests
3
+ */
4
+ export interface RetryOptions {
5
+ maxRetries?: number;
6
+ baseDelay?: number;
7
+ maxDelay?: number;
8
+ timeout?: number;
9
+ }
10
+ /**
11
+ * Retry a function with exponential backoff
12
+ */
13
+ export declare function retryWithBackoff<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
14
+ /**
15
+ * Retry fetch with exponential backoff
16
+ */
17
+ export declare function fetchWithRetry(url: string, init?: RequestInit, options?: RetryOptions): Promise<Response>;
18
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AASD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,CAAC,CAqDZ;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,WAAW,EAClB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,QAAQ,CAAC,CAwBnB"}