fix: intercept Grok sign-in routes in iframe
This commit is contained in:
@@ -31,8 +31,9 @@ not inject provider HTML or replace the native iframe view.
|
||||
Open `chrome://extensions`, enable Developer mode, choose **Load unpacked**, and select this directory.
|
||||
|
||||
Grok authentication is intentionally completed in a top-level browser tab because
|
||||
`accounts.x.ai` does not permit login inside an iframe. Use **登录 ↗** in the Grok
|
||||
panel, finish signing in, return to the workspace, and reload the Grok panel.
|
||||
`accounts.x.ai` does not permit login inside an iframe. Grok `/sign-in` links are
|
||||
redirected to a top-level tab automatically; alternatively use **登录 ↗** in the
|
||||
Grok panel. Finish signing in, return to the workspace, and reload the Grok panel.
|
||||
|
||||
## Security boundary
|
||||
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
(() => {
|
||||
const { createProviderAdapter } = globalThis.AIParallelProviderCore;
|
||||
createProviderAdapter({
|
||||
|
||||
function isExternalAuthUrl(value) {
|
||||
let targetUrl;
|
||||
try {
|
||||
targetUrl = new URL(value, "https://grok.com/");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (targetUrl.hostname === "accounts.x.ai") return true;
|
||||
return ["grok.com", "www.grok.com"].includes(targetUrl.hostname)
|
||||
&& /^\/(?:sign-in|login)(?:\/|$)/.test(targetUrl.pathname);
|
||||
}
|
||||
|
||||
const adapter = createProviderAdapter({
|
||||
id: "grok",
|
||||
hosts: ["grok.com"],
|
||||
isExternalAuthUrl,
|
||||
editorSelectors: [
|
||||
"textarea[aria-label='Ask Grok anything']",
|
||||
"textarea[placeholder*='Ask']",
|
||||
@@ -33,6 +47,7 @@
|
||||
});
|
||||
|
||||
if (typeof document === "undefined" || typeof chrome === "undefined") return;
|
||||
if (window.top === window) return;
|
||||
|
||||
document.addEventListener("click", (event) => {
|
||||
const link = event.target?.closest?.("a[href]");
|
||||
@@ -44,10 +59,15 @@
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
if (targetUrl.hostname !== "accounts.x.ai") return;
|
||||
if (!adapter.isExternalAuthUrl(targetUrl.href)) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
window.parent.postMessage({
|
||||
context: "ai-parallel-workspace",
|
||||
providerId: "grok",
|
||||
type: "AI_PARALLEL_AUTH_REQUIRED"
|
||||
}, new URL(chrome.runtime.getURL("/")).origin);
|
||||
chrome.runtime.sendMessage({
|
||||
type: "OPEN_PROVIDER_AUTH",
|
||||
providerId: "grok",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "AI Parallel",
|
||||
"version": "2.1.2",
|
||||
"version": "2.1.3",
|
||||
"description": "Compare multiple AI web chats side by side in one live workspace.",
|
||||
"minimum_chrome_version": "120",
|
||||
"permissions": [
|
||||
|
||||
@@ -221,6 +221,11 @@ window.addEventListener("message", (event) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type === "AI_PARALLEL_AUTH_REQUIRED") {
|
||||
setPanelState(providerId, "已在新标签页打开登录;完成后点击 ↻", { ready: false });
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type === "AI_PARALLEL_SEND_RESULT") {
|
||||
const requestId = String(event.data.requestId || "");
|
||||
const pending = pendingRequests.get(requestId);
|
||||
|
||||
@@ -7,7 +7,7 @@ const vm = require("node:vm");
|
||||
const extensionRoot = path.join(__dirname, "..", "apps", "browser-extension");
|
||||
|
||||
function loadAdapters() {
|
||||
const context = { console, setTimeout, clearTimeout };
|
||||
const context = { console, setTimeout, clearTimeout, URL };
|
||||
context.globalThis = context;
|
||||
vm.createContext(context);
|
||||
for (const file of [
|
||||
@@ -40,3 +40,12 @@ test("all supported providers expose the adapter contract", () => {
|
||||
assert.equal(typeof adapters[id].newChat, "function");
|
||||
}
|
||||
});
|
||||
|
||||
test("Grok recognizes iframe-only authentication routes", () => {
|
||||
const grok = loadAdapters().grok;
|
||||
assert.equal(grok.isExternalAuthUrl("https://accounts.x.ai/check-login?redirect=grok-com"), true);
|
||||
assert.equal(grok.isExternalAuthUrl("https://grok.com/sign-in?return_to=%2F"), true);
|
||||
assert.equal(grok.isExternalAuthUrl("/login"), true);
|
||||
assert.equal(grok.isExternalAuthUrl("https://grok.com/"), false);
|
||||
assert.equal(grok.isExternalAuthUrl("https://example.com/sign-in"), false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user