refactor: Simplify OAuth authorization page and component with direct SSO handling

This commit is contained in:
wood chen 2025-02-21 19:19:11 +08:00
parent a3e43bf9e1
commit a05bce4e38
4 changed files with 50 additions and 70 deletions

View File

@ -32,7 +32,7 @@ export default function LoginPage() {
<MessageCircleCode className="mx-auto size-12" /> <MessageCircleCode className="mx-auto size-12" />
<div className="text-2xl font-semibold tracking-tight"> <div className="text-2xl font-semibold tracking-tight">
<span>Welcome to</span>{" "} <span>Welcome to</span>{" "}
<span style={{ fontFamily: "Bahamas Bold" }}>Q58论坛 Connect</span> <span style={{ fontFamily: "Bahamas Bold" }}>Q58 Connect</span>
</div> </div>
</div> </div>
<Suspense> <Suspense>

View File

@ -6,18 +6,19 @@ import { Authorizing } from "@/components/auth/authorizing";
import { ErrorCard } from "@/components/auth/error-card"; import { ErrorCard } from "@/components/auth/error-card";
export interface AuthorizeParams { export interface AuthorizeParams {
scope?: string;
response_type: string; response_type: string;
client_id: string; client_id: string;
redirect_uri: string; redirect_uri: string;
scope?: string;
state?: string; state?: string;
} }
export default async function AuthorizePage({ export default async function OAuthAuthorization({
searchParams, searchParams,
}: { }: {
searchParams: AuthorizeParams; searchParams: AuthorizeParams;
}) { }) {
// 检查用户是否已登录
const user = await getCurrentUser(); const user = await getCurrentUser();
if (!user?.id) { if (!user?.id) {
redirect("/sign-in"); redirect("/sign-in");
@ -57,6 +58,7 @@ export default async function AuthorizePage({
); );
} }
// 验证客户端
const client = await getClientByClientId(searchParams.client_id); const client = await getClientByClientId(searchParams.client_id);
if (!client) { if (!client) {
return ( return (
@ -102,25 +104,10 @@ export default async function AuthorizePage({
); );
} }
// 构建 OAuth 参数 // 使用原始的 Authorizing 组件处理授权流程
const oauthParams = new URLSearchParams();
oauthParams.set("response_type", searchParams.response_type);
oauthParams.set("client_id", searchParams.client_id);
oauthParams.set("redirect_uri", searchParams.redirect_uri);
if (searchParams.scope) oauthParams.set("scope", searchParams.scope);
if (searchParams.state) oauthParams.set("state", searchParams.state);
// 转换参数格式
const authorizeParams = {
oauth: btoa(oauthParams.toString()),
clientId: client.id,
scope: searchParams.scope || "read_profile",
redirectUri: searchParams.redirect_uri,
};
return ( return (
<div className="flex min-h-screen items-center justify-center p-4"> <div className="flex min-h-screen items-center justify-center bg-gray-50 p-4">
<Authorizing {...authorizeParams} /> <Authorizing />
</div> </div>
); );
} }

View File

@ -1,67 +1,60 @@
"use client"; "use client";
import { useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
import { handleAuthorizeAction } from "@/actions/authorizing"; import { getDiscourseSSOUrl } from "@/actions/discourse-sso-url";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { ErrorCard } from "@/components/auth/error-card"; import { ErrorCard } from "@/components/auth/error-card";
interface AuthorizingProps { export function Authorizing() {
oauth: string; const router = useRouter();
clientId: string; const searchParams = useSearchParams();
scope: string; const [error, setError] = useState<unknown | null>(null);
redirectUri: string;
}
export function Authorizing({
oauth,
clientId,
scope,
redirectUri,
}: AuthorizingProps) {
const [error, setError] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
useEffect(() => { const signInCallback = useCallback(async () => {
const authorize = async () => {
try { try {
const result = await handleAuthorizeAction(oauth, clientId, scope); const url = await getDiscourseSSOUrl(searchParams.toString());
if (result.error) { router.push(url);
setError(result.error); } catch (error) {
} else if (result.redirectUrl) { setError(error);
const url = await result.redirectUrl;
window.location.href = url;
} else {
setError("授权响应无效");
}
} catch (err) {
console.error("授权过程出错:", err);
setError(err instanceof Error ? err.message : "授权过程发生未知错误");
} finally {
setIsLoading(false); setIsLoading(false);
} }
}; }, [router, searchParams]);
authorize(); useEffect(() => {
}, [oauth, clientId, scope]); // Delay 3s get sso url go to ...
const timer = setTimeout(signInCallback, 3);
return () => {
clearTimeout(timer);
};
}, [signInCallback]);
if (error) { if (error) {
return ( return (
<div className="flex min-h-screen items-center justify-center p-4"> <Card className="w-full">
<ErrorCard <CardHeader className="space-y-4 text-center">
title="授权失败" <div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
description={error} <div className="h-8 w-8 text-red-600"></div>
redirectUri={redirectUri}
error="access_denied"
errorDescription={error}
/>
</div> </div>
<CardTitle className="text-2xl font-semibold text-red-600">
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-center text-gray-500">
{error instanceof Error
? error.message
: "授权异常,登录失败!请稍后重试。"}
</p>
</CardContent>
</Card>
); );
} }
return ( return (
<Card className="w-full max-w-md"> <Card className="w-full">
<CardHeader className="space-y-4 text-center"> <CardHeader className="space-y-4 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-blue-100"> <div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-blue-100">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div> <div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div>

View File

@ -62,7 +62,7 @@ export function UserAuthForm({
) : ( ) : (
<MessageCircleCode className="mr-2 size-4" /> <MessageCircleCode className="mr-2 size-4" />
)}{" "} )}{" "}
Q58 Q58论坛
</button> </button>
</div> </div>
); );