From 1e519738eae717f075597b0bd435fca97afb61c7 Mon Sep 17 00:00:00 2001 From: wood chen Date: Fri, 21 Feb 2025 13:08:42 +0800 Subject: [PATCH] feat: Improve OAuth authorization flow and redirect handling - Update signIn action to support dynamic redirect after authentication - Modify Q58 OAuth route to handle dynamic return URL with original parameters - Refactor UserAuthorize component to support OAuth-specific redirect scenarios - Add support for preserving and processing OAuth parameters during login --- src/actions/user-authorize.ts | 5 +++- src/app/api/auth/q58/route.ts | 8 ++++-- src/components/auth/user-authorize.tsx | 39 +++++++++++++------------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/actions/user-authorize.ts b/src/actions/user-authorize.ts index 68d3f0c..4bc5874 100644 --- a/src/actions/user-authorize.ts +++ b/src/actions/user-authorize.ts @@ -1,7 +1,10 @@ "use server"; +import { redirect } from "next/navigation"; import { signIn as nextSignIn } from "@/auth"; export async function signIn(data: Record) { - return nextSignIn("credentials", data); + const { redirectTo, ...credentials } = data; + await nextSignIn("credentials", credentials); + redirect(redirectTo || "/dashboard"); } diff --git a/src/app/api/auth/q58/route.ts b/src/app/api/auth/q58/route.ts index 07eb483..93bf807 100644 --- a/src/app/api/auth/q58/route.ts +++ b/src/app/api/auth/q58/route.ts @@ -9,10 +9,12 @@ const hostUrl = process.env.NEXT_PUBLIC_HOST_URL as string; const discourseHost = process.env.DISCOURSE_HOST as string; const clientSecret = process.env.DISCOURSE_SECRET as string; -export async function POST(_req: Request) { +export async function POST(req: Request) { const nonce = WordArray.random(16).toString(); - const return_url = `${hostUrl}/authorize`; - const sso = btoa(`nonce=${nonce}&return_sso_url=${return_url}`); + const url = new URL(req.url); + const originalParams = url.searchParams.toString(); + const return_url = `${hostUrl}/q58/callback?${originalParams}`; + const sso = btoa(`nonce=${nonce}&return_sso_url=${encodeURI(return_url)}`); const sig = hmacSHA256(sso, clientSecret).toString(Hex); cookies().set(AUTH_NONCE, nonce, { maxAge: 60 * 10 }); diff --git a/src/components/auth/user-authorize.tsx b/src/components/auth/user-authorize.tsx index e2647cd..ead469a 100644 --- a/src/components/auth/user-authorize.tsx +++ b/src/components/auth/user-authorize.tsx @@ -1,8 +1,7 @@ "use client"; import { useCallback, useEffect, useState } from "react"; -import { useRouter } from "next/navigation"; -import { signIn as nextAuthSignIn, useSession } from "next-auth/react"; +import { signIn } from "@/actions/user-authorize"; interface UserAuthorizeProps extends React.HTMLAttributes { data: Record; @@ -15,8 +14,6 @@ export function UserAuthorize({ }: UserAuthorizeProps) { const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); - const { update } = useSession(); - const router = useRouter(); const signInCallback = useCallback(async () => { if (isLoading) { @@ -24,28 +21,32 @@ export function UserAuthorize({ } setIsLoading(true); try { - const result = await nextAuthSignIn("credentials", { - ...data, - redirect: false, - }); + // 检查是否有 OAuth 参数 + const searchParams = new URLSearchParams(data); + const sso = searchParams.get("sso"); + const sig = searchParams.get("sig"); + const oauth = searchParams.get("oauth"); - if (result?.error) { - setError(result.error); - } else { - // 更新 session - await update(); - // 重定向回OAuth授权页面 - router.push(`/oauth/authorize${window.location.search}`); + let redirectTo = "/dashboard"; + if (sso && sig && oauth) { + // 如果是从Q58论坛回调,使用原始的OAuth参数 + const oauthParams = new URLSearchParams(atob(oauth)); + redirectTo = `/oauth/authorize?${oauthParams.toString()}`; } + + await signIn({ ...data, redirectTo }); + setIsLoading(false); } catch (error) { setError(error); - } finally { setIsLoading(false); } - }, [data, isLoading, update, router]); + }, [data, isLoading]); useEffect(() => { - signInCallback(); + const timer = setTimeout(signInCallback, 5); + return () => { + clearTimeout(timer); + }; }, [signInCallback]); return ( @@ -53,7 +54,7 @@ export function UserAuthorize({ {error ? (

登录异常,授权失败!

) : ( -

账号信息验证中,请稍等...

+

账号信息验证中,准备跳转中,请稍等...

)} );