mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-23 04:09:49 +00:00
Fixed Codex
This commit is contained in:
+76
-11
@@ -3,6 +3,43 @@
|
||||
import { Suspense, useEffect, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
const OAUTH_SESSION_KEY = "oauth_pending_auth";
|
||||
|
||||
/**
|
||||
* Direct exchange: callback page calls exchange API itself
|
||||
* when relay to opener fails (e.g. HMR reload destroyed listeners)
|
||||
*/
|
||||
async function directExchange(code, state) {
|
||||
try {
|
||||
const raw = localStorage.getItem(OAUTH_SESSION_KEY);
|
||||
if (!raw) return false;
|
||||
|
||||
const session = JSON.parse(raw);
|
||||
// Expired (5 min)
|
||||
if (Date.now() - session.timestamp > 300000) {
|
||||
localStorage.removeItem(OAUTH_SESSION_KEY);
|
||||
return false;
|
||||
}
|
||||
|
||||
const res = await fetch(`/api/oauth/${session.provider}/exchange`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
code,
|
||||
redirectUri: session.redirectUri,
|
||||
codeVerifier: session.codeVerifier,
|
||||
state,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
localStorage.removeItem(OAUTH_SESSION_KEY);
|
||||
return res.ok && data.success;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth Callback Page Content
|
||||
*/
|
||||
@@ -24,7 +61,7 @@ function CallbackContent() {
|
||||
fullUrl: window.location.href,
|
||||
};
|
||||
|
||||
let sent = false;
|
||||
let relayed = false;
|
||||
|
||||
// Check if this callback is from expected origin/port
|
||||
const expectedOrigins = [
|
||||
@@ -35,8 +72,8 @@ function CallbackContent() {
|
||||
// Method 1: postMessage to opener (popup mode)
|
||||
if (window.opener) {
|
||||
try {
|
||||
window.opener.postMessage({ type: "oauth_callback", data: callbackData }, "*"); // Allow any origin for local dev
|
||||
sent = true;
|
||||
window.opener.postMessage({ type: "oauth_callback", data: callbackData }, "*");
|
||||
relayed = true;
|
||||
} catch (e) {
|
||||
console.log("postMessage failed:", e);
|
||||
}
|
||||
@@ -47,7 +84,7 @@ function CallbackContent() {
|
||||
const channel = new BroadcastChannel("oauth_callback");
|
||||
channel.postMessage(callbackData);
|
||||
channel.close();
|
||||
sent = true;
|
||||
relayed = true;
|
||||
} catch (e) {
|
||||
console.log("BroadcastChannel failed:", e);
|
||||
}
|
||||
@@ -55,25 +92,53 @@ function CallbackContent() {
|
||||
// Method 3: localStorage event (fallback)
|
||||
try {
|
||||
localStorage.setItem("oauth_callback", JSON.stringify({ ...callbackData, timestamp: Date.now() }));
|
||||
sent = true;
|
||||
relayed = true;
|
||||
} catch (e) {
|
||||
console.log("localStorage failed:", e);
|
||||
}
|
||||
|
||||
if (sent && (code || error)) {
|
||||
// Use setTimeout to avoid synchronous setState in effect
|
||||
if (!(code || error)) {
|
||||
setTimeout(() => setStatus("manual"), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
setTimeout(() => {
|
||||
setStatus("success");
|
||||
// Auto close after 1.5 seconds
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
// If can't close (not a popup), show success message
|
||||
setTimeout(() => setStatus("done"), 500);
|
||||
}, 1500);
|
||||
}, 0);
|
||||
} else {
|
||||
setTimeout(() => setStatus("manual"), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try direct exchange FIRST (before relay may be lost to HMR)
|
||||
// Then relay as backup for normal flow
|
||||
const handleExchange = async () => {
|
||||
const pending = localStorage.getItem(OAUTH_SESSION_KEY);
|
||||
if (pending) {
|
||||
// Direct exchange - works even if opener was destroyed by HMR
|
||||
const ok = await directExchange(code, state);
|
||||
if (ok) {
|
||||
setStatus("success");
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
setTimeout(() => setStatus("done"), 500);
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: relay succeeded and OAuthModal handled it
|
||||
setStatus("success");
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
setTimeout(() => setStatus("done"), 500);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
handleExchange();
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user