diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index 6809ad7ad..d9bf95058 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -374,7 +374,37 @@ export default function Page() { }; }, []); - // 根据组织名称启动钉钉登录(在 iframe 中打开) + const getSafeLoginCallbackUrl = () => { + if (typeof window === "undefined") return "/"; + + const callbackUrl = new URLSearchParams(window.location.search).get( + "callbackUrl", + ); + if ( + callbackUrl && + callbackUrl.startsWith("/") && + !callbackUrl.startsWith("//") + ) { + return callbackUrl; + } + + return "/"; + }; + + const buildDingTalkLoginUrl = (orgName?: string) => { + const params = new URLSearchParams(); + if (orgName) params.set("org", orgName); + + const callbackUrl = getSafeLoginCallbackUrl(); + if (callbackUrl !== "/") { + params.set("callbackUrl", callbackUrl); + } + + const query = params.toString(); + return `/api/auth/dingtalk/login${query ? `?${query}` : ""}`; + }; + + // 根据组织名称启动钉钉登录。钉钉授权页禁止第三方 iframe 嵌入,必须使用顶层跳转。 const startDingTalkLoginForOrg = (orgName: string) => { // 清除 URL 中的 token 参数,避免干扰 if ( @@ -385,14 +415,12 @@ export default function Page() { window.history.replaceState({}, "", newUrl); } - const loginUrl = `/api/auth/dingtalk/login?org=${encodeURIComponent( - orgName, - )}`; + const loginUrl = buildDingTalkLoginUrl(orgName); - console.log("[DingTalk] Opening org login:", orgName, loginUrl); - setDingTalkIframeSrc(loginUrl); + console.log("[DingTalk] Redirecting org login:", orgName, loginUrl); setShowDingTalkModal(true); setShowOrgMenu(false); + window.location.assign(loginUrl); }; // 钉钉登录 - 支持多组织 @@ -409,7 +437,6 @@ export default function Page() { return; } - // 兼容:直接使用旧的方式在 iframe 中打开 if ( typeof window === "undefined" || typeof window.location === "undefined" @@ -424,27 +451,9 @@ export default function Page() { window.history.replaceState({}, "", newUrl); } - const param = { - redirect_uri: encodeURIComponent( - window.location.origin + "/dingtalk-callback.html", - ), - client_id: dingTalkAppKey, - scope: "openid", - response_type: "code", - state: "default", - prompt: "consent", - }; - - const redirectUrl = - "https://login.dingtalk.com/oauth2/auth?" + - Object.keys(param) - .map((key) => key + "=" + (param as any)[key]) - .join("&"); - - console.log("[DingTalk] Opening OAuth URL (legacy):", redirectUrl); - - setDingTalkIframeSrc(redirectUrl); - setShowDingTalkModal(true); + const loginUrl = buildDingTalkLoginUrl(); + console.log("[DingTalk] Redirecting OAuth login:", loginUrl); + window.location.assign(loginUrl); return; } @@ -633,17 +642,7 @@ export default function Page() {