ai_api / src /lib /providers /webCookieAuth.ts
Yogesh
initial deploy
cd8bd0a
Raw
History Blame Contribute Delete
4.37 kB
export function stripCookieInputPrefix(rawValue: string): string {
const trimmed = (rawValue || "").trim();
if (!trimmed) return "";
const withoutBearer = trimmed.replace(/^bearer\s+/i, "");
return withoutBearer.replace(/^cookie:/i, "").trim();
}
export function normalizeSessionCookieHeader(rawValue: string, defaultCookieName: string): string {
const normalized = stripCookieInputPrefix(rawValue);
if (!normalized) return "";
if (normalized.includes("=")) {
return normalized;
}
return `${defaultCookieName}=${normalized}`;
}
/**
* Extract a single cookie's value from whatever the user pasted. Handles:
* - bare value: "eyJ0eXAi..." β†’ "eyJ0eXAi..."
* - single pair: "sso=eyJ0eXAi..." β†’ "eyJ0eXAi..."
* - full DevTools cookie blob: "foo=1; sso=eyJ...; bar=2" β†’ "eyJ..."
* Returns "" if a blob is given that does not contain the named cookie.
*/
export function extractCookieValue(rawValue: string, cookieName: string): string {
const trimmed = stripCookieInputPrefix(rawValue);
if (!trimmed) return "";
if (trimmed.includes(";")) {
const escaped = cookieName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const match = trimmed.match(new RegExp("(?:^|;\\s*)" + escaped + "=([^;\\s]+)"));
return match ? match[1] : "";
}
const prefix = `${cookieName}=`;
if (trimmed.startsWith(prefix)) return trimmed.slice(prefix.length);
return trimmed;
}
/**
* Build the `Cookie` header value for grok.com from whatever the user pasted.
*
* Always emits `sso=<value>`. When the pasted blob also carries the paired
* `sso-rw` write cookie, it is forwarded too β€” Grok's anti-bot now rejects
* requests that send `sso` without `sso-rw` (error code 7, #3063). `sso-rw` is
* only appended when it appears as a real cookie pair in the input, so a bare
* `sso` value (no `;`/`=`) is never mistaken for an `sso-rw` value.
*
* Returns "" when no `sso` value can be extracted.
*/
export function buildGrokCookieHeader(rawValue: string): string {
const sso = extractCookieValue(rawValue, "sso");
if (!sso) return "";
const parts = [`sso=${sso}`];
if (/(?:^|;\s*)sso-rw=/.test(rawValue)) {
const ssoRw = extractCookieValue(rawValue, "sso-rw");
if (ssoRw) parts.push(`sso-rw=${ssoRw}`);
}
return parts.join("; ");
}
/**
* Build the `Cookie` header value for chat.qwen.ai (Qwen Web / Tongyi).
*
* The Qwen v2 API sits behind Alibaba's "baxia" WAF, which requires the full
* browser cookie jar from a real logged-in session (`cna`, `ssxmod_itna`,
* `ssxmod_itna2`, `token`, `_bl_uid`, `x-ap`, ...). Unlike grok we cannot
* reconstruct a canonical subset, so we forward the whole pasted/captured blob
* verbatim (minus a leading `Cookie:`/`bearer ` prefix).
*
* A bare token (no cookie pairs, i.e. no `=`) yields "" β€” there is no jar to
* replay, only a bearer credential (handled by {@link extractQwenToken}).
*/
export function buildQwenCookieHeader(rawValue: string): string {
const trimmed = stripCookieInputPrefix(rawValue);
if (!trimmed || !trimmed.includes("=")) return "";
return trimmed;
}
/**
* Extract the Qwen bearer token from whatever the user pasted/captured.
*
* Qwen stores its auth JWT in localStorage as `token`, and chat.qwen.ai also
* mirrors it into a `token` cookie. So:
* - full cookie blob with `token=...` β†’ that value
* - bare token (no cookie pairs) β†’ the value itself
* - cookie blob without a `token` pair β†’ "" (token must come from elsewhere)
*/
export function extractQwenToken(rawValue: string): string {
const trimmed = stripCookieInputPrefix(rawValue);
if (!trimmed) return "";
if (!trimmed.includes("=")) return trimmed;
const match = trimmed.match(/(?:^|;\s*)token=([^;\s]+)/);
return match ? match[1] : "";
}
export function normalizeSessionCookieHeaders(
rawValues: Array<string | null | undefined>,
defaultCookieName: string
): string[] {
const seen = new Set<string>();
const normalizedHeaders: string[] = [];
for (const rawValue of rawValues) {
if (typeof rawValue !== "string") continue;
const normalized = normalizeSessionCookieHeader(rawValue, defaultCookieName);
if (!normalized || seen.has(normalized)) continue;
seen.add(normalized);
normalizedHeaders.push(normalized);
}
return normalizedHeaders;
}