@iamtoricool/opencool-qwen-auth 0.0.1-alpha → 0.0.2-alpha
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/lib/auth/auth.d.ts +72 -0
- package/dist/lib/auth/auth.d.ts.map +1 -0
- package/dist/lib/auth/auth.js +212 -0
- package/dist/lib/auth/auth.js.map +1 -0
- package/dist/lib/auth/browser-session.d.ts +49 -0
- package/dist/lib/auth/browser-session.d.ts.map +1 -0
- package/dist/lib/auth/browser-session.js +211 -0
- package/dist/lib/auth/browser-session.js.map +1 -0
- package/dist/lib/auth/browser.d.ts +17 -0
- package/dist/lib/auth/browser.d.ts.map +1 -0
- package/dist/lib/auth/browser.js +86 -0
- package/dist/lib/auth/browser.js.map +1 -0
- package/dist/lib/auth/server.d.ts +14 -0
- package/dist/lib/auth/server.d.ts.map +1 -0
- package/dist/lib/auth/server.js +253 -0
- package/dist/lib/auth/server.js.map +1 -0
- package/dist/lib/config.d.ts +28 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +67 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +77 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +109 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/logger.d.ts +49 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +56 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/oauth-success.html +83 -0
- package/dist/lib/request/fetch-helpers.d.ts +66 -0
- package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
- package/dist/lib/request/fetch-helpers.js +193 -0
- package/dist/lib/request/fetch-helpers.js.map +1 -0
- package/dist/lib/request/request-transformer.d.ts +27 -0
- package/dist/lib/request/request-transformer.d.ts.map +1 -0
- package/dist/lib/request/request-transformer.js +159 -0
- package/dist/lib/request/request-transformer.js.map +1 -0
- package/dist/lib/request/response-handler.d.ts +32 -0
- package/dist/lib/request/response-handler.d.ts.map +1 -0
- package/dist/lib/request/response-handler.js +176 -0
- package/dist/lib/request/response-handler.js.map +1 -0
- package/dist/lib/types.d.ts +159 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +5 -0
- package/dist/lib/types.js.map +1 -0
- package/iamtoricool-opencool-qwen-auth-0.0.1-alpha.tgz +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth authentication logic for Qwen
|
|
3
|
+
* Handles Google OAuth flow and JWT token extraction
|
|
4
|
+
*/
|
|
5
|
+
import type { AuthorizationFlow, TokenResult, ParsedAuthInput, JWTPayload } from "../types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Generate a random state value for OAuth flow
|
|
8
|
+
* @returns Random hex string
|
|
9
|
+
*/
|
|
10
|
+
export declare function createState(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Parse authorization token from URL fragment
|
|
13
|
+
* Qwen returns token in format: https://chat.qwen.ai/auth#token=JWT
|
|
14
|
+
* @param url - URL with fragment containing token
|
|
15
|
+
* @returns The JWT token or undefined
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseTokenFromFragment(url: string): string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Parse authorization input from user
|
|
20
|
+
* Handles: full URL with fragment, just fragment, or just token
|
|
21
|
+
* @param input - User input
|
|
22
|
+
* @returns Parsed authorization data
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseAuthorizationInput(input: string): ParsedAuthInput;
|
|
25
|
+
/**
|
|
26
|
+
* Create Google OAuth authorization flow for Qwen
|
|
27
|
+
* @returns Authorization flow details
|
|
28
|
+
*/
|
|
29
|
+
export declare function createAuthorizationFlow(): Promise<AuthorizationFlow>;
|
|
30
|
+
/**
|
|
31
|
+
* Exchange authorization code for access and refresh tokens
|
|
32
|
+
* For Qwen, the "code" is actually a JWT token obtained from URL fragment
|
|
33
|
+
* @param code - JWT token from Qwen auth
|
|
34
|
+
* @param _verifier - PKCE verifier (not used for Qwen but kept for interface)
|
|
35
|
+
* @param _redirectUri - OAuth redirect URI (not used but kept for interface)
|
|
36
|
+
* @returns Token result
|
|
37
|
+
*/
|
|
38
|
+
export declare function exchangeAuthorizationCode(code: string, _verifier?: string, _redirectUri?: string): Promise<TokenResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Refresh access token using refresh token
|
|
41
|
+
* For Qwen, we just check if the token is still valid
|
|
42
|
+
* @param refreshToken - Refresh token (same as access token for Qwen)
|
|
43
|
+
* @returns Token result
|
|
44
|
+
*/
|
|
45
|
+
export declare function refreshAccessToken(refreshToken: string): Promise<TokenResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Decode a JWT token to extract payload (without verification)
|
|
48
|
+
* @param token - JWT token to decode
|
|
49
|
+
* @returns Decoded payload or null if invalid
|
|
50
|
+
*/
|
|
51
|
+
export declare function decodeJWT(token: string): JWTPayload | null;
|
|
52
|
+
/**
|
|
53
|
+
* Get the Qwen OAuth login URL
|
|
54
|
+
* This is the simpler approach - open Qwen's login page directly
|
|
55
|
+
* @returns Qwen login URL
|
|
56
|
+
*/
|
|
57
|
+
export declare function getQwenLoginUrl(): string;
|
|
58
|
+
/**
|
|
59
|
+
* Build manual OAuth flow for Qwen
|
|
60
|
+
* This opens the Google OAuth directly with the Qwen callback
|
|
61
|
+
* @returns Manual OAuth flow configuration
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildManualOAuthFlow(): Promise<{
|
|
64
|
+
url: string;
|
|
65
|
+
method: "code";
|
|
66
|
+
instructions: "Token not found in URL fragment";
|
|
67
|
+
callback: (input: string) => Promise<import("../types.js").TokenSuccess | {
|
|
68
|
+
type: "failed";
|
|
69
|
+
}>;
|
|
70
|
+
}>;
|
|
71
|
+
export { extractBrowserSession, isBrowserSessionAvailable, getBrowserSessionInstructions, findFirefoxCookiePath, } from "./browser-session.js";
|
|
72
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../lib/auth/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAEV,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,UAAU,EACX,MAAM,aAAa,CAAC;AAYrB;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAwBtE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAgBtE;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAgB1E;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,CAAC,CAiCtB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAe1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB;;;;sBAOd,MAAM;;;GASjC;AAGD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth authentication logic for Qwen
|
|
3
|
+
* Handles Google OAuth flow and JWT token extraction
|
|
4
|
+
*/
|
|
5
|
+
import { generatePKCE } from "@openauthjs/openauth/pkce";
|
|
6
|
+
import { randomBytes } from "node:crypto";
|
|
7
|
+
import { GOOGLE_CLIENT_ID, GOOGLE_AUTHORIZE_URL, QWEN_OAUTH_LOGIN, QWEN_OAUTH_CALLBACK, GOOGLE_SCOPE, PLUGIN_NAME, ERROR_MESSAGES, } from "../constants.js";
|
|
8
|
+
/**
|
|
9
|
+
* Generate a random state value for OAuth flow
|
|
10
|
+
* @returns Random hex string
|
|
11
|
+
*/
|
|
12
|
+
export function createState() {
|
|
13
|
+
return randomBytes(16).toString("hex");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse authorization token from URL fragment
|
|
17
|
+
* Qwen returns token in format: https://chat.qwen.ai/auth#token=JWT
|
|
18
|
+
* @param url - URL with fragment containing token
|
|
19
|
+
* @returns The JWT token or undefined
|
|
20
|
+
*/
|
|
21
|
+
export function parseTokenFromFragment(url) {
|
|
22
|
+
try {
|
|
23
|
+
const urlObj = new URL(url);
|
|
24
|
+
const fragment = urlObj.hash;
|
|
25
|
+
if (!fragment || !fragment.startsWith("#")) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
// Remove leading # and parse as query string
|
|
29
|
+
const params = new URLSearchParams(fragment.substring(1));
|
|
30
|
+
return params.get("token") ?? undefined;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// If not a valid URL, try parsing as fragment directly
|
|
34
|
+
if (url.startsWith("#")) {
|
|
35
|
+
const params = new URLSearchParams(url.substring(1));
|
|
36
|
+
return params.get("token") ?? undefined;
|
|
37
|
+
}
|
|
38
|
+
if (url.includes("token=")) {
|
|
39
|
+
const params = new URLSearchParams(url);
|
|
40
|
+
return params.get("token") ?? undefined;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse authorization input from user
|
|
47
|
+
* Handles: full URL with fragment, just fragment, or just token
|
|
48
|
+
* @param input - User input
|
|
49
|
+
* @returns Parsed authorization data
|
|
50
|
+
*/
|
|
51
|
+
export function parseAuthorizationInput(input) {
|
|
52
|
+
const value = (input || "").trim();
|
|
53
|
+
if (!value)
|
|
54
|
+
return {};
|
|
55
|
+
// Try to extract token from URL fragment
|
|
56
|
+
const token = parseTokenFromFragment(value);
|
|
57
|
+
if (token) {
|
|
58
|
+
return { code: token }; // Use 'code' field for compatibility
|
|
59
|
+
}
|
|
60
|
+
// Handle direct token paste (if it looks like a JWT)
|
|
61
|
+
if (value.split(".").length === 3) {
|
|
62
|
+
return { code: value };
|
|
63
|
+
}
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create Google OAuth authorization flow for Qwen
|
|
68
|
+
* @returns Authorization flow details
|
|
69
|
+
*/
|
|
70
|
+
export async function createAuthorizationFlow() {
|
|
71
|
+
const pkce = (await generatePKCE());
|
|
72
|
+
const state = createState();
|
|
73
|
+
// Build Google OAuth URL with Qwen callback
|
|
74
|
+
const url = new URL(GOOGLE_AUTHORIZE_URL);
|
|
75
|
+
url.searchParams.set("response_type", "code");
|
|
76
|
+
url.searchParams.set("client_id", GOOGLE_CLIENT_ID);
|
|
77
|
+
url.searchParams.set("redirect_uri", QWEN_OAUTH_CALLBACK);
|
|
78
|
+
url.searchParams.set("scope", GOOGLE_SCOPE);
|
|
79
|
+
url.searchParams.set("state", state);
|
|
80
|
+
url.searchParams.set("code_challenge", pkce.challenge);
|
|
81
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
82
|
+
url.searchParams.set("nonce", createState());
|
|
83
|
+
return { pkce, state, url: url.toString() };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Exchange authorization code for access and refresh tokens
|
|
87
|
+
* For Qwen, the "code" is actually a JWT token obtained from URL fragment
|
|
88
|
+
* @param code - JWT token from Qwen auth
|
|
89
|
+
* @param _verifier - PKCE verifier (not used for Qwen but kept for interface)
|
|
90
|
+
* @param _redirectUri - OAuth redirect URI (not used but kept for interface)
|
|
91
|
+
* @returns Token result
|
|
92
|
+
*/
|
|
93
|
+
export async function exchangeAuthorizationCode(code, _verifier, _redirectUri) {
|
|
94
|
+
try {
|
|
95
|
+
// For Qwen, the "code" is actually a JWT token
|
|
96
|
+
// We verify it's a valid JWT and extract expiration
|
|
97
|
+
const decoded = decodeJWT(code);
|
|
98
|
+
if (!decoded) {
|
|
99
|
+
console.error(`[${PLUGIN_NAME}] Invalid JWT token provided`);
|
|
100
|
+
return { type: "failed" };
|
|
101
|
+
}
|
|
102
|
+
// Check token expiration
|
|
103
|
+
const exp = typeof decoded.exp === "number" ? decoded.exp : undefined;
|
|
104
|
+
const expiresIn = exp
|
|
105
|
+
? exp * 1000 - Date.now()
|
|
106
|
+
: 3600 * 1000; // Default 1 hour if no exp
|
|
107
|
+
if (expiresIn <= 0) {
|
|
108
|
+
console.error(`[${PLUGIN_NAME}] Token already expired`);
|
|
109
|
+
return { type: "failed" };
|
|
110
|
+
}
|
|
111
|
+
// For Qwen, the access token IS the JWT, and we use it as refresh too
|
|
112
|
+
return {
|
|
113
|
+
type: "success",
|
|
114
|
+
access: code,
|
|
115
|
+
refresh: code, // Qwen tokens are self-contained JWTs
|
|
116
|
+
expires: Date.now() + expiresIn,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
console.error(`[${PLUGIN_NAME}] Token exchange error:`, error);
|
|
121
|
+
return { type: "failed" };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Refresh access token using refresh token
|
|
126
|
+
* For Qwen, we just check if the token is still valid
|
|
127
|
+
* @param refreshToken - Refresh token (same as access token for Qwen)
|
|
128
|
+
* @returns Token result
|
|
129
|
+
*/
|
|
130
|
+
export async function refreshAccessToken(refreshToken) {
|
|
131
|
+
try {
|
|
132
|
+
// Decode and check if still valid
|
|
133
|
+
const decoded = decodeJWT(refreshToken);
|
|
134
|
+
if (!decoded) {
|
|
135
|
+
console.error(`[${PLUGIN_NAME}] Invalid refresh token`);
|
|
136
|
+
return { type: "failed" };
|
|
137
|
+
}
|
|
138
|
+
// Check expiration
|
|
139
|
+
const exp = typeof decoded.exp === "number" ? decoded.exp : undefined;
|
|
140
|
+
if (exp && exp * 1000 < Date.now()) {
|
|
141
|
+
console.error(`[${PLUGIN_NAME}] Refresh token expired`);
|
|
142
|
+
return { type: "failed" };
|
|
143
|
+
}
|
|
144
|
+
// Token is still valid, return it
|
|
145
|
+
const expiresIn = exp
|
|
146
|
+
? exp * 1000 - Date.now()
|
|
147
|
+
: 3600 * 1000;
|
|
148
|
+
return {
|
|
149
|
+
type: "success",
|
|
150
|
+
access: refreshToken,
|
|
151
|
+
refresh: refreshToken,
|
|
152
|
+
expires: Date.now() + expiresIn,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
console.error(`[${PLUGIN_NAME}] Token refresh error:`, error);
|
|
157
|
+
return { type: "failed" };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Decode a JWT token to extract payload (without verification)
|
|
162
|
+
* @param token - JWT token to decode
|
|
163
|
+
* @returns Decoded payload or null if invalid
|
|
164
|
+
*/
|
|
165
|
+
export function decodeJWT(token) {
|
|
166
|
+
try {
|
|
167
|
+
const parts = token.split(".");
|
|
168
|
+
if (parts.length !== 3)
|
|
169
|
+
return null;
|
|
170
|
+
const payload = parts[1];
|
|
171
|
+
// Add padding if needed
|
|
172
|
+
const padding = 4 - (payload.length % 4);
|
|
173
|
+
const paddedPayload = padding === 4 ? payload : payload + "=".repeat(padding);
|
|
174
|
+
const decoded = Buffer.from(paddedPayload, "base64").toString("utf-8");
|
|
175
|
+
return JSON.parse(decoded);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get the Qwen OAuth login URL
|
|
183
|
+
* This is the simpler approach - open Qwen's login page directly
|
|
184
|
+
* @returns Qwen login URL
|
|
185
|
+
*/
|
|
186
|
+
export function getQwenLoginUrl() {
|
|
187
|
+
return QWEN_OAUTH_LOGIN;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Build manual OAuth flow for Qwen
|
|
191
|
+
* This opens the Google OAuth directly with the Qwen callback
|
|
192
|
+
* @returns Manual OAuth flow configuration
|
|
193
|
+
*/
|
|
194
|
+
export async function buildManualOAuthFlow() {
|
|
195
|
+
const flow = await createAuthorizationFlow();
|
|
196
|
+
return {
|
|
197
|
+
url: flow.url,
|
|
198
|
+
method: "code",
|
|
199
|
+
instructions: ERROR_MESSAGES.TOKEN_NOT_FOUND,
|
|
200
|
+
callback: async (input) => {
|
|
201
|
+
const parsed = parseAuthorizationInput(input);
|
|
202
|
+
if (!parsed.code) {
|
|
203
|
+
return { type: "failed" };
|
|
204
|
+
}
|
|
205
|
+
const tokens = await exchangeAuthorizationCode(parsed.code);
|
|
206
|
+
return tokens?.type === "success" ? tokens : { type: "failed" };
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// Re-export browser session functions
|
|
211
|
+
export { extractBrowserSession, isBrowserSessionAvailable, getBrowserSessionInstructions, findFirefoxCookiePath, } from "./browser-session.js";
|
|
212
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../lib/auth/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser session extraction for Qwen auth
|
|
3
|
+
* Extracts auth token from browser cookies (Firefox, Chrome)
|
|
4
|
+
*/
|
|
5
|
+
interface Cookie {
|
|
6
|
+
name: string;
|
|
7
|
+
host: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Find Firefox cookie database path
|
|
12
|
+
* @returns Path to cookies.sqlite or null if not found
|
|
13
|
+
*/
|
|
14
|
+
export declare function findFirefoxCookiePath(): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Find Chrome/Chromium cookie database path
|
|
17
|
+
* @returns Path to Cookies database or null if not found
|
|
18
|
+
*/
|
|
19
|
+
export declare function findChromeCookiePath(): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* Extract cookies from Firefox SQLite database
|
|
22
|
+
* @param cookiePath Path to cookies.sqlite
|
|
23
|
+
* @returns Array of cookies or null if error
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractFirefoxCookies(cookiePath: string): Promise<Cookie[] | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Extract cookies from Chrome/Chromium SQLite database
|
|
28
|
+
* @param cookiePath Path to Cookies database
|
|
29
|
+
* @returns Array of cookies or null if error
|
|
30
|
+
*/
|
|
31
|
+
export declare function extractChromeCookies(cookiePath: string): Promise<Cookie[] | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Extract Qwen auth token from browser cookies
|
|
34
|
+
* Tries Firefox first, then Chrome
|
|
35
|
+
* @returns The auth token or null if not found
|
|
36
|
+
*/
|
|
37
|
+
export declare function extractBrowserSession(): Promise<string | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Check if browser session extraction is available
|
|
40
|
+
* @returns true if better-sqlite3 is installed
|
|
41
|
+
*/
|
|
42
|
+
export declare function isBrowserSessionAvailable(): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Get instructions for enabling browser session extraction
|
|
45
|
+
* @returns Installation instructions
|
|
46
|
+
*/
|
|
47
|
+
export declare function getBrowserSessionInstructions(): string;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=browser-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-session.d.ts","sourceRoot":"","sources":["../../../lib/auth/browser-session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAwBD;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CA0BrD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CA0BpD;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CA+BxF;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAkCvF;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyCpE;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,OAAO,CAAC,CAGlE;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAYtD"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser session extraction for Qwen auth
|
|
3
|
+
* Extracts auth token from browser cookies (Firefox, Chrome)
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, copyFileSync, readdirSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { homedir, tmpdir } from "node:os";
|
|
8
|
+
import { randomBytes } from "node:crypto";
|
|
9
|
+
import { PLUGIN_NAME } from "../constants.js";
|
|
10
|
+
// Dynamic import for better-sqlite3 (optional dependency)
|
|
11
|
+
async function loadDatabase() {
|
|
12
|
+
try {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
14
|
+
const betterSqlite3 = require("better-sqlite3");
|
|
15
|
+
const Db = betterSqlite3.default || betterSqlite3;
|
|
16
|
+
return Db;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Find Firefox cookie database path
|
|
24
|
+
* @returns Path to cookies.sqlite or null if not found
|
|
25
|
+
*/
|
|
26
|
+
export function findFirefoxCookiePath() {
|
|
27
|
+
const baseDirs = [
|
|
28
|
+
join(homedir(), ".mozilla", "firefox"),
|
|
29
|
+
join(homedir(), "snap", "firefox", "common", ".mozilla", "firefox"),
|
|
30
|
+
join(homedir(), ".var", "app", "org.mozilla.firefox", ".mozilla", "firefox"),
|
|
31
|
+
];
|
|
32
|
+
for (const baseDir of baseDirs) {
|
|
33
|
+
if (!existsSync(baseDir))
|
|
34
|
+
continue;
|
|
35
|
+
try {
|
|
36
|
+
const entries = readdirSync(baseDir, { withFileTypes: true });
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
if (entry.isDirectory() && entry.name.includes(".default")) {
|
|
39
|
+
const cookiePath = join(baseDir, entry.name, "cookies.sqlite");
|
|
40
|
+
if (existsSync(cookiePath)) {
|
|
41
|
+
return cookiePath;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Ignore errors
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Find Chrome/Chromium cookie database path
|
|
54
|
+
* @returns Path to Cookies database or null if not found
|
|
55
|
+
*/
|
|
56
|
+
export function findChromeCookiePath() {
|
|
57
|
+
const baseDirs = [
|
|
58
|
+
join(homedir(), ".config", "google-chrome"),
|
|
59
|
+
join(homedir(), ".config", "chromium"),
|
|
60
|
+
join(homedir(), ".var", "app", "com.google.Chrome", "config", "google-chrome"),
|
|
61
|
+
];
|
|
62
|
+
for (const baseDir of baseDirs) {
|
|
63
|
+
if (!existsSync(baseDir))
|
|
64
|
+
continue;
|
|
65
|
+
try {
|
|
66
|
+
const entries = readdirSync(baseDir, { withFileTypes: true });
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
if (entry.isDirectory()) {
|
|
69
|
+
const cookiePath = join(baseDir, entry.name, "Cookies");
|
|
70
|
+
if (existsSync(cookiePath)) {
|
|
71
|
+
return cookiePath;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Ignore errors
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Extract cookies from Firefox SQLite database
|
|
84
|
+
* @param cookiePath Path to cookies.sqlite
|
|
85
|
+
* @returns Array of cookies or null if error
|
|
86
|
+
*/
|
|
87
|
+
export async function extractFirefoxCookies(cookiePath) {
|
|
88
|
+
const Db = await loadDatabase();
|
|
89
|
+
if (!Db) {
|
|
90
|
+
console.warn(`[${PLUGIN_NAME}] better-sqlite3 not available, cannot read Firefox cookies`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
// Copy database to temp location (original may be locked by browser)
|
|
94
|
+
const tempPath = join(tmpdir(), `qwen_cookies_${randomBytes(8).toString("hex")}.sqlite`);
|
|
95
|
+
try {
|
|
96
|
+
copyFileSync(cookiePath, tempPath);
|
|
97
|
+
const db = new Db(tempPath);
|
|
98
|
+
// Query for Qwen-related cookies
|
|
99
|
+
const stmt = db.prepare(`
|
|
100
|
+
SELECT name, host, value
|
|
101
|
+
FROM moz_cookies
|
|
102
|
+
WHERE (host LIKE '%qwen%' OR host LIKE '%aliyun%')
|
|
103
|
+
ORDER BY host, name
|
|
104
|
+
`);
|
|
105
|
+
const cookies = stmt.all();
|
|
106
|
+
db.close();
|
|
107
|
+
return cookies;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
console.error(`[${PLUGIN_NAME}] Error reading Firefox cookies:`, error);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Extract cookies from Chrome/Chromium SQLite database
|
|
116
|
+
* @param cookiePath Path to Cookies database
|
|
117
|
+
* @returns Array of cookies or null if error
|
|
118
|
+
*/
|
|
119
|
+
export async function extractChromeCookies(cookiePath) {
|
|
120
|
+
const Db = await loadDatabase();
|
|
121
|
+
if (!Db) {
|
|
122
|
+
console.warn(`[${PLUGIN_NAME}] better-sqlite3 not available, cannot read Chrome cookies`);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
// Copy database to temp location
|
|
126
|
+
const tempPath = join(tmpdir(), `qwen_cookies_${randomBytes(8).toString("hex")}.sqlite`);
|
|
127
|
+
try {
|
|
128
|
+
copyFileSync(cookiePath, tempPath);
|
|
129
|
+
const db = new Db(tempPath);
|
|
130
|
+
// Chrome stores cookies differently - encrypted value
|
|
131
|
+
// Query for Qwen-related cookies
|
|
132
|
+
const stmt = db.prepare(`
|
|
133
|
+
SELECT name, host_key as host, encrypted_value as value
|
|
134
|
+
FROM cookies
|
|
135
|
+
WHERE (host_key LIKE '%qwen%' OR host_key LIKE '%aliyun%')
|
|
136
|
+
ORDER BY host_key, name
|
|
137
|
+
`);
|
|
138
|
+
const cookies = stmt.all();
|
|
139
|
+
db.close();
|
|
140
|
+
// Note: Chrome encrypts cookie values, we'd need to decrypt them
|
|
141
|
+
// This is more complex and may require additional dependencies
|
|
142
|
+
return cookies;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error(`[${PLUGIN_NAME}] Error reading Chrome cookies:`, error);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Extract Qwen auth token from browser cookies
|
|
151
|
+
* Tries Firefox first, then Chrome
|
|
152
|
+
* @returns The auth token or null if not found
|
|
153
|
+
*/
|
|
154
|
+
export async function extractBrowserSession() {
|
|
155
|
+
// Try Firefox first
|
|
156
|
+
const firefoxPath = findFirefoxCookiePath();
|
|
157
|
+
if (firefoxPath) {
|
|
158
|
+
console.log(`[${PLUGIN_NAME}] Found Firefox cookies at: ${firefoxPath}`);
|
|
159
|
+
const cookies = await extractFirefoxCookies(firefoxPath);
|
|
160
|
+
if (cookies) {
|
|
161
|
+
// Look for token cookie on qwen.ai domain
|
|
162
|
+
const tokenCookie = cookies.find((c) => c.name === "token" && c.host.includes("qwen"));
|
|
163
|
+
if (tokenCookie) {
|
|
164
|
+
console.log(`[${PLUGIN_NAME}] Found Qwen auth token in Firefox cookies`);
|
|
165
|
+
return tokenCookie.value;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Try Chrome
|
|
170
|
+
const chromePath = findChromeCookiePath();
|
|
171
|
+
if (chromePath) {
|
|
172
|
+
console.log(`[${PLUGIN_NAME}] Found Chrome cookies at: ${chromePath}`);
|
|
173
|
+
const cookies = await extractChromeCookies(chromePath);
|
|
174
|
+
if (cookies) {
|
|
175
|
+
const tokenCookie = cookies.find((c) => c.name === "token" && c.host.includes("qwen"));
|
|
176
|
+
if (tokenCookie) {
|
|
177
|
+
console.log(`[${PLUGIN_NAME}] Found Qwen auth token in Chrome cookies`);
|
|
178
|
+
// Note: Chrome cookies are encrypted, would need decryption
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
console.log(`[${PLUGIN_NAME}] No Qwen auth token found in browser cookies`);
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Check if browser session extraction is available
|
|
188
|
+
* @returns true if better-sqlite3 is installed
|
|
189
|
+
*/
|
|
190
|
+
export async function isBrowserSessionAvailable() {
|
|
191
|
+
const Db = await loadDatabase();
|
|
192
|
+
return Db !== undefined;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get instructions for enabling browser session extraction
|
|
196
|
+
* @returns Installation instructions
|
|
197
|
+
*/
|
|
198
|
+
export function getBrowserSessionInstructions() {
|
|
199
|
+
return `
|
|
200
|
+
To enable automatic browser session extraction, install better-sqlite3:
|
|
201
|
+
|
|
202
|
+
npm install better-sqlite3
|
|
203
|
+
|
|
204
|
+
Note: This requires Python and build tools to compile native modules.
|
|
205
|
+
|
|
206
|
+
Alternatively, you can:
|
|
207
|
+
1. Use API key authentication
|
|
208
|
+
2. Export cookies manually from your browser
|
|
209
|
+
`;
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=browser-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-session.js","sourceRoot":"","sources":["../../../lib/auth/browser-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser utilities for OAuth flow
|
|
3
|
+
* Handles platform-specific browser opening
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Gets the platform-specific command to open a URL in the default browser
|
|
7
|
+
* @returns Browser opener command for the current platform
|
|
8
|
+
*/
|
|
9
|
+
export declare function getBrowserOpener(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Opens a URL in the default browser
|
|
12
|
+
* Silently fails if browser cannot be opened (user can copy URL manually)
|
|
13
|
+
* @param url - URL to open
|
|
14
|
+
* @returns True if a browser launch was attempted
|
|
15
|
+
*/
|
|
16
|
+
export declare function openBrowserUrl(url: string): boolean;
|
|
17
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../lib/auth/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAuCD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAyBnD"}
|