From 1c0aa7e65f5d7cc0f7d1e802053cc255d95ce7f1 Mon Sep 17 00:00:00 2001 From: wood chen Date: Fri, 21 Feb 2025 17:43:21 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=20SSO=20?= =?UTF-8?q?=E5=92=8C=20OAuth=20=E9=87=8D=E5=AE=9A=E5=90=91=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=EF=BC=8C=E6=94=B9=E8=BF=9B=E5=8F=82=E6=95=B0=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=92=8C=E5=9B=9E=E8=B0=83=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 +++++++++++++++++ src/actions/user-authorize.ts | 23 ++++++++++++----------- src/app/api/auth/q58/route.ts | 20 +++++++++++++++----- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c69ccf1..a9e49c0 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,23 @@ > shadcn安装组件的命令,举例: npx shadcn@latest add button +本项目是一个中间项目, 用于允许用户通过oauth2.0认证的方式接入本项目, 但是实际用户信息是本项目通过SSO连接到Discourse论坛获取的. + +原始项目地址: https://github.com/Tuluobo/discourse-connect + +本项目主要是进行了: + +1. 前端页面内容补充 +2. 管理员的相关管理页面和统计页面 +3. 本系统用户可以查看自己应用的统计信息 +4. Navbar的导航菜单添加 +5. 本系统用户可以限制自己应用的允许授权使用者 +6. 首页说明的优化 + +整体流程应该是这样的: + +用户登录接入应用 - 接入应用通过oauth2.0向本系统发起授权请求 - 本系统向Discourse论坛发起SSO请求 - 用户在Discourse论坛中进行登录 - Discourse论坛重定向到本系统, 并附带sso和sig参数 - 本系统通过sso和sig参数向Discourse论坛发起获取用户信息请求 - 本系统通过oauth2.0向接入应用发起回调请求, 并附带用户信息 - 接入应用通过oauth2.0向本系统发起获取用户信息请求 - 本系统通过oauth2.0向Discourse论坛发起获取用户信息请求 - 本系统返回用户信息给接入应用 + ## 项目概述 本项目提供了一个 OAuth 认证系统,允许其他应用程序使用 Discourse 论坛的用户账号进行身份验证。这样可以让用户使用他们已有的 Discourse 账号登录到您的应用程序,无需创建新的账号。 diff --git a/src/actions/user-authorize.ts b/src/actions/user-authorize.ts index c371f12..b550cd8 100644 --- a/src/actions/user-authorize.ts +++ b/src/actions/user-authorize.ts @@ -1,10 +1,11 @@ "use server"; +import { cookies } from "next/headers"; import { redirect } from "next/navigation"; import { signIn as nextSignIn } from "@/auth"; export async function signIn(data: Record) { - const { sso, sig, returnTo } = data; + const { sso, sig } = data; // 先进行 SSO 登录 await nextSignIn("credentials", { sso, sig }); @@ -13,17 +14,17 @@ export async function signIn(data: Record) { const params = new URLSearchParams(atob(sso)); const returnSsoUrl = params.get("return_sso_url"); - if (!returnSsoUrl) { - // 如果没有 return_sso_url,检查是否有 OAuth 参数 - const searchParams = new URLSearchParams(returnTo); - if (searchParams.has("client_id")) { - // 如果是 OAuth 流程,重定向到授权页面 - redirect(`/oauth/authorize${returnTo}`); + if (returnSsoUrl) { + // 解析 return_sso_url 中的参数 + const returnUrl = new URL(returnSsoUrl); + const hasOAuthParams = returnUrl.searchParams.has("client_id"); + + if (hasOAuthParams) { + // 如果 URL 中包含 OAuth 参数,直接重定向(此时应该是 /authorize 页面) + redirect(returnSsoUrl); } - // 如果都没有,重定向到仪表板 - redirect("/dashboard"); } - // 如果有 return_sso_url,重定向回 SSO 提供者 - redirect(returnSsoUrl); + // 如果没有有效的重定向 URL,默认到仪表板 + redirect("/dashboard"); } diff --git a/src/app/api/auth/q58/route.ts b/src/app/api/auth/q58/route.ts index 670bb33..499d759 100644 --- a/src/app/api/auth/q58/route.ts +++ b/src/app/api/auth/q58/route.ts @@ -15,12 +15,22 @@ export async function POST(req: Request) { const url = new URL(referer); const searchParams = url.searchParams.toString(); - // 如果是从OAuth授权页面来的,保留OAuth参数 - const return_url = searchParams - ? `${hostUrl}/q58/callback?oauth=${btoa(searchParams)}` - : `${hostUrl}/authorize`; + // 保存原始的 OAuth 参数到 cookie,用于后续重定向 + if (searchParams) { + cookies().set("oauth_params", searchParams, { + maxAge: 60 * 10, // 10分钟过期 + path: "/", + }); + } - const sso = btoa(`nonce=${nonce}&return_sso_url=${return_url}`); + // 设置 SSO 回调地址,将 OAuth 参数编码后传递 + const return_url = searchParams + ? `${hostUrl}/authorize?${searchParams}` // 直接将 OAuth 参数附加到回调 URL + : `${hostUrl}/dashboard`; // 如果没有 OAuth 参数,回到仪表板 + + const sso = btoa( + `nonce=${nonce}&return_sso_url=${encodeURIComponent(return_url)}`, + ); const sig = hmacSHA256(sso, clientSecret).toString(Hex); cookies().set(AUTH_NONCE, nonce, { maxAge: 60 * 10 });