mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
feat(providers): add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) (#7713)
This commit is contained in:
committed by
GitHub
parent
d1668a7c3c
commit
e5842c75ec
1
changelog.d/features/7567-grokweb-ua-hint.md
Normal file
1
changelog.d/features/7567-grokweb-ua-hint.md
Normal file
@@ -0,0 +1 @@
|
||||
- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567)
|
||||
@@ -4620,6 +4620,7 @@
|
||||
"blackboxWebCookiePlaceholder": "Blackbox Web Cookie Placeholder",
|
||||
"t3ChatWebCookieHint": "Open t3.chat → DevTools → Application → Local Storage → https://t3.chat, copy 'convex-session-id'. Then open DevTools → Network, copy the full Cookie header from any chat request. Paste both values in the fields below.",
|
||||
"t3ChatWebCookiePlaceholder": "convex-session-id=abc123...",
|
||||
"grokWebCookieHint": "grok.com's cf_clearance cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser where you copied it — pasting it from a different machine/IP causes a 403. Paste sso and sso-rw here, then open Advanced Settings and fill Custom User-Agent with the EXACT User-Agent string of that same browser, and use the same IP/proxy for this connection.",
|
||||
"blockClaudeExtraUsageDescription": "Hide extra Claude usage rows reported by some providers when they duplicate primary token accounting.",
|
||||
"blockClaudeExtraUsageLabel": "Block duplicate Claude usage rows",
|
||||
"disableCoolingDescription": "Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).",
|
||||
|
||||
@@ -4618,6 +4618,7 @@
|
||||
"blackboxWebCookiePlaceholder": "Cole o valor de __Secure-authjs.session-token",
|
||||
"t3ChatWebCookieHint": "Abra t3.chat → DevTools → Aplicativo → Armazenamento local → https://t3.chat, copie 'convex-session-id'. Em seguida, abra DevTools → Rede, copie o cabeçalho completo do cookie de qualquer solicitação de chat. Cole os dois valores nos campos abaixo.",
|
||||
"t3ChatWebCookiePlaceholder": "id-de-sessão-convexa=abc123...",
|
||||
"grokWebCookieHint": "O cookie cf_clearance do grok.com é vinculado ao IP, ao User-Agent e à impressão digital TLS do navegador de onde você o copiou — colá-lo de outra máquina/IP causa um erro 403. Cole sso e sso-rw aqui e depois abra Configurações Avançadas e preencha o Custom User-Agent com o valor EXATO do User-Agent desse mesmo navegador, usando o mesmo IP/proxy para esta conexão.",
|
||||
"blockClaudeExtraUsageDescription": "Quando habilitado, o OmniRoute marca esta conta do Claude Code como indisponível assim que a API de usage reporta `extra_usage.queued`, para que o fallback troque para outra conta antes de continuar com cobranças extras pay-as-you-go.",
|
||||
"blockClaudeExtraUsageLabel": "Bloquear Claude Extra Usage",
|
||||
"disableCoolingDescription": "__MISSING__:Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).",
|
||||
|
||||
@@ -45,6 +45,14 @@ export const WEB_SESSION_CREDENTIAL_REQUIREMENTS = {
|
||||
placeholder: "sso=...; sso-rw=...",
|
||||
acceptsFullCookieHeader: true,
|
||||
storageKeys: ["cookie", "sso", "sso-rw"],
|
||||
// #7567 — grok.com's cf_clearance cookie is pinned to IP + User-Agent + TLS
|
||||
// fingerprint of the browser that earned it, so pasting it from a different
|
||||
// machine/IP causes a 403 that is actually correct Cloudflare behavior. Point
|
||||
// users at the Custom User-Agent field under Advanced Settings + same IP/proxy,
|
||||
// instead of the generic (and here misleading) single-cookie hint.
|
||||
hintKey: "grokWebCookieHint",
|
||||
hintFallback:
|
||||
"grok.com's cf_clearance cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser where you copied it — pasting it from a different machine/IP causes a 403. Paste sso and sso-rw here, then open Advanced Settings and fill Custom User-Agent with the EXACT User-Agent string of that same browser, and use the same IP/proxy for this connection.",
|
||||
},
|
||||
"gemini-web": {
|
||||
kind: "cookie",
|
||||
|
||||
118
tests/unit/grokweb-cookie-ua-hint-7567.test.ts
Normal file
118
tests/unit/grokweb-cookie-ua-hint-7567.test.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import type { ProviderMessageTranslator } from "../../src/app/(dashboard)/dashboard/providers/[id]/providerCredentialText.ts";
|
||||
|
||||
// #7567 — grok-web's add-connection dialog showed the generic, uninformative
|
||||
// cookie hint ("Required cookie: sso + sso-rw. Paste the Cookie header
|
||||
// value…") even though the real failure mode (403 from a pasted cf_clearance
|
||||
// pinned to a different IP/User-Agent/TLS fingerprint) is only resolvable by
|
||||
// also filling the Custom User-Agent field under Advanced Settings and reusing
|
||||
// the same IP/proxy. A dedicated hintKey (grokWebCookieHint) now overrides the
|
||||
// generic copy on the ADD flow, following the exact #5465 (t3.chat) pattern.
|
||||
const { getWebSessionCredentialHint } = await import(
|
||||
"../../src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts"
|
||||
);
|
||||
const { WEB_SESSION_CREDENTIAL_REQUIREMENTS } = await import(
|
||||
"../../src/shared/providers/webSessionCredentials.ts"
|
||||
);
|
||||
|
||||
const GROK_HINT =
|
||||
"grok.com's cf_clearance cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser where you copied it — pasting it from a different machine/IP causes a 403. Paste sso and sso-rw here, then open Advanced Settings and fill Custom User-Agent with the EXACT User-Agent string of that same browser, and use the same IP/proxy for this connection.";
|
||||
|
||||
const GENERIC_COOKIE_HINT_TEMPLATE =
|
||||
"Required cookie: {credential}. Paste the Cookie header value from your own signed-in {provider} web session. Do not include the Cookie: prefix.";
|
||||
|
||||
/** Minimal translator stub mimicking next-intl's `t` + `t.has`. */
|
||||
function makeTranslator(messages: Record<string, string>): ProviderMessageTranslator {
|
||||
const t = ((key: string, values?: Record<string, unknown>) => {
|
||||
const raw = messages[key];
|
||||
if (raw === undefined) return key;
|
||||
return values
|
||||
? Object.entries(values).reduce(
|
||||
(acc, [name, value]) => acc.replaceAll(`{${name}}`, String(value)),
|
||||
raw
|
||||
)
|
||||
: raw;
|
||||
}) as ProviderMessageTranslator;
|
||||
t.has = (key: string) => key in messages;
|
||||
return t;
|
||||
}
|
||||
|
||||
test("grok-web requirement carries the grokWebCookieHint override (#7567)", () => {
|
||||
const req = WEB_SESSION_CREDENTIAL_REQUIREMENTS["grok-web"] as { hintKey?: string };
|
||||
assert.equal(req.hintKey, "grokWebCookieHint");
|
||||
});
|
||||
|
||||
test("grok-web add-connection hint explains cf_clearance IP/UA/TLS pinning and the Custom User-Agent fix (#7567)", () => {
|
||||
const t = makeTranslator({
|
||||
grokWebCookieHint: GROK_HINT,
|
||||
webCookieCredentialHint: GENERIC_COOKIE_HINT_TEMPLATE,
|
||||
});
|
||||
|
||||
const hint = getWebSessionCredentialHint(
|
||||
t,
|
||||
WEB_SESSION_CREDENTIAL_REQUIREMENTS["grok-web"],
|
||||
"Grok",
|
||||
false
|
||||
);
|
||||
|
||||
assert.equal(hint, GROK_HINT);
|
||||
assert.ok(hint && hint.includes("User-Agent"), "must mention User-Agent");
|
||||
assert.ok(hint && hint.includes("IP"), "must mention IP pinning");
|
||||
assert.ok(hint && hint.includes("cf_clearance"), "must mention cf_clearance");
|
||||
});
|
||||
|
||||
test("grok-web add-connection hint does not fall back to the generic circular cookie hint (#7567)", () => {
|
||||
const t = makeTranslator({
|
||||
grokWebCookieHint: GROK_HINT,
|
||||
webCookieCredentialHint: GENERIC_COOKIE_HINT_TEMPLATE,
|
||||
});
|
||||
|
||||
const hint = getWebSessionCredentialHint(
|
||||
t,
|
||||
WEB_SESSION_CREDENTIAL_REQUIREMENTS["grok-web"],
|
||||
"Grok",
|
||||
false
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
hint && !hint.includes("Required cookie: sso + sso-rw"),
|
||||
"must not fall back to the generic single-cookie template"
|
||||
);
|
||||
});
|
||||
|
||||
test("grok-web edit-connection flow is unaffected by the new hintKey (#7567 regression guard)", () => {
|
||||
const t = makeTranslator({
|
||||
grokWebCookieHint: GROK_HINT,
|
||||
webCookieEditHint: "Leave blank to keep the current session cookie. Required cookie: {credential}.",
|
||||
});
|
||||
|
||||
const hint = getWebSessionCredentialHint(
|
||||
t,
|
||||
WEB_SESSION_CREDENTIAL_REQUIREMENTS["grok-web"],
|
||||
"Grok",
|
||||
true
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
hint && hint.startsWith("Leave blank to keep the current session cookie."),
|
||||
"editing=true must keep the generic edit-flow copy, not the new hintKey"
|
||||
);
|
||||
assert.ok(hint && !hint.includes("cf_clearance"), "edit flow must not surface the new add-flow hint");
|
||||
});
|
||||
|
||||
test("grok-web hintFallback is used verbatim when the translation key is missing (#7567)", () => {
|
||||
const t = makeTranslator({
|
||||
// grokWebCookieHint intentionally absent — t.has() must return false.
|
||||
webCookieCredentialHint: GENERIC_COOKIE_HINT_TEMPLATE,
|
||||
});
|
||||
|
||||
const requirement = WEB_SESSION_CREDENTIAL_REQUIREMENTS["grok-web"] as {
|
||||
hintFallback?: string;
|
||||
};
|
||||
assert.ok(requirement.hintFallback, "grok-web must define a hintFallback");
|
||||
|
||||
const hint = getWebSessionCredentialHint(t, WEB_SESSION_CREDENTIAL_REQUIREMENTS["grok-web"], "Grok", false);
|
||||
|
||||
assert.equal(hint, requirement.hintFallback);
|
||||
});
|
||||
Reference in New Issue
Block a user