feat: 改进 OAuth 参数存储和重定向机制,使用 cookies 管理临时授权参数

This commit is contained in:
wood chen 2025-02-21 18:18:45 +08:00
parent 8bcaf1fd89
commit 05b8ee3c75
3 changed files with 29 additions and 13 deletions

View File

@ -1,5 +1,6 @@
"use server";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { signIn as nextSignIn } from "@/auth";
@ -10,16 +11,19 @@ export async function signIn(data: Record<string, any>) {
// 进行 SSO 登录
await nextSignIn("credentials", { sso, sig });
// 从 sso 参数中获取 return_sso_url
const params = new URLSearchParams(atob(sso));
const returnSsoUrl = params.get("return_sso_url");
// 检查是否有保存的 OAuth 参数
const cookieStore = cookies();
const oauthParams = cookieStore.get("oauth_params");
if (!returnSsoUrl) {
redirect("/dashboard");
if (oauthParams) {
// 清除 cookie
cookieStore.delete("oauth_params");
// 重定向到授权页面,带上 OAuth 参数
redirect(`/oauth/authorize?${oauthParams.value}`);
}
// 重定向到 return_sso_url
redirect(returnSsoUrl);
// 如果没有 OAuth 参数,重定向到仪表板
redirect("/dashboard");
} catch (error) {
console.error("登录失败:", error);
redirect("/sign-in?error=AuthenticationError");

View File

@ -13,8 +13,20 @@ export async function POST(req: Request) {
try {
const nonce = WordArray.random(16).toString();
// 设置基本的回调地址
// 从请求中获取 OAuth 参数
const body = await req.json().catch(() => ({}));
const oauthParams = body.oauth_params || "";
// 设置回调地址,如果有 OAuth 参数则保存
const return_url = `${hostUrl}/authorize`;
if (oauthParams) {
cookies().set("oauth_params", oauthParams, {
maxAge: 60 * 10, // 10分钟过期
path: "/",
httpOnly: true,
secure: process.env.NODE_ENV === "production",
});
}
// 构建 SSO 参数
const ssoParams = new URLSearchParams();

View File

@ -1,7 +1,7 @@
"use client";
import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useRouter, useSearchParams } from "next/navigation";
import { signIn } from "@/actions/user-authorize";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
@ -18,6 +18,7 @@ export function UserAuthorize({
const [isLoading, setIsLoading] = useState<boolean>(false);
const [error, setError] = useState<Error | unknown>(null);
const router = useRouter();
const searchParams = useSearchParams();
const signInCallback = useCallback(async () => {
if (isLoading) {
@ -26,9 +27,8 @@ export function UserAuthorize({
setIsLoading(true);
try {
// 从 URL 中获取 sso 和 sig 参数
const url = new URL(window.location.href);
const sso = url.searchParams.get("sso");
const sig = url.searchParams.get("sig");
const sso = searchParams?.get("sso");
const sig = searchParams?.get("sig");
if (!sso || !sig) {
throw new Error("缺少必要的认证参数");
@ -48,7 +48,7 @@ export function UserAuthorize({
setError(error);
setIsLoading(false);
}
}, [isLoading, router]);
}, [isLoading, router, searchParams]);
useEffect(() => {
signInCallback();