mirror of
https://github.com/woodchen-ink/Q58Connect.git
synced 2025-07-18 14:01:55 +08:00
refactor: 改进 OAuth 参数处理和错误处理机制
This commit is contained in:
parent
1c0aa7e65f
commit
e193568ee8
@ -14,17 +14,23 @@ export async function signIn(data: Record<string, any>) {
|
|||||||
const params = new URLSearchParams(atob(sso));
|
const params = new URLSearchParams(atob(sso));
|
||||||
const returnSsoUrl = params.get("return_sso_url");
|
const returnSsoUrl = params.get("return_sso_url");
|
||||||
|
|
||||||
if (returnSsoUrl) {
|
if (!returnSsoUrl) {
|
||||||
// 解析 return_sso_url 中的参数
|
redirect("/dashboard");
|
||||||
const returnUrl = new URL(returnSsoUrl);
|
|
||||||
const hasOAuthParams = returnUrl.searchParams.has("client_id");
|
|
||||||
|
|
||||||
if (hasOAuthParams) {
|
|
||||||
// 如果 URL 中包含 OAuth 参数,直接重定向(此时应该是 /authorize 页面)
|
|
||||||
redirect(returnSsoUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有有效的重定向 URL,默认到仪表板
|
// 检查是否是 OAuth 流程
|
||||||
|
try {
|
||||||
|
const returnUrl = new URL(returnSsoUrl);
|
||||||
|
const isOAuthFlow = returnUrl.pathname.startsWith("/oauth/authorize");
|
||||||
|
|
||||||
|
if (isOAuthFlow) {
|
||||||
|
// 如果是 OAuth 流程,继续授权流程
|
||||||
|
redirect(returnSsoUrl);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Invalid return URL:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认重定向到仪表板
|
||||||
redirect("/dashboard");
|
redirect("/dashboard");
|
||||||
}
|
}
|
||||||
|
@ -11,22 +11,27 @@ 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 nonce = WordArray.random(16).toString();
|
||||||
const referer = headers().get("referer") || "";
|
|
||||||
const url = new URL(referer);
|
|
||||||
const searchParams = url.searchParams.toString();
|
|
||||||
|
|
||||||
// 保存原始的 OAuth 参数到 cookie,用于后续重定向
|
// 尝试从请求体中获取 OAuth 参数
|
||||||
if (searchParams) {
|
let oauthParams = "";
|
||||||
cookies().set("oauth_params", searchParams, {
|
try {
|
||||||
maxAge: 60 * 10, // 10分钟过期
|
const body = await req.json();
|
||||||
path: "/",
|
if (body.oauth_params) {
|
||||||
});
|
oauthParams = body.oauth_params;
|
||||||
|
// 保存 OAuth 参数到 cookie
|
||||||
|
cookies().set("oauth_params", oauthParams, {
|
||||||
|
maxAge: 60 * 10, // 10分钟过期
|
||||||
|
path: "/",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to parse request body:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 SSO 回调地址,将 OAuth 参数编码后传递
|
// 设置回调地址
|
||||||
const return_url = searchParams
|
const return_url = oauthParams
|
||||||
? `${hostUrl}/authorize?${searchParams}` // 直接将 OAuth 参数附加到回调 URL
|
? `${hostUrl}/authorize?${oauthParams}` // OAuth流程:回到授权页面
|
||||||
: `${hostUrl}/dashboard`; // 如果没有 OAuth 参数,回到仪表板
|
: `${hostUrl}/dashboard`; // 普通登录:直接到仪表板
|
||||||
|
|
||||||
const sso = btoa(
|
const sso = btoa(
|
||||||
`nonce=${nonce}&return_sso_url=${encodeURIComponent(return_url)}`,
|
`nonce=${nonce}&return_sso_url=${encodeURIComponent(return_url)}`,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import { Loader2, MessageCircleCode } from "lucide-react";
|
import { Loader2, MessageCircleCode } from "lucide-react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@ -19,20 +19,38 @@ export function UserAuthForm({
|
|||||||
const [isLoading, setIsLoading] = React.useState<boolean>(false);
|
const [isLoading, setIsLoading] = React.useState<boolean>(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
const signIn = () => {
|
const signIn = () => {
|
||||||
React.startTransition(async () => {
|
React.startTransition(async () => {
|
||||||
const response = await fetch("/api/auth/q58", { method: "POST" });
|
try {
|
||||||
if (!response.ok || response.status !== 200) {
|
// 构建请求体,包含 OAuth 参数
|
||||||
|
const body: Record<string, any> = {};
|
||||||
|
if (searchParams?.toString()) {
|
||||||
|
body.oauth_params = searchParams.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch("/api/auth/q58", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(response.statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data: DiscourseData = await response.json();
|
||||||
|
router.push(data.sso_url);
|
||||||
|
} catch (error) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "内部服务异常",
|
title: "内部服务异常",
|
||||||
description: response.statusText,
|
description: error instanceof Error ? error.message : "未知错误",
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
let data: DiscourseData = await response.json();
|
|
||||||
router.push(data.sso_url);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user