diff --git a/src/app/(oauth)/q58/callback/page.tsx b/src/app/(oauth)/q58/callback/page.tsx index 6d9d6dd..3059649 100644 --- a/src/app/(oauth)/q58/callback/page.tsx +++ b/src/app/(oauth)/q58/callback/page.tsx @@ -1,22 +1,22 @@ import { Suspense } from "react"; import { redirect } from "next/navigation"; +import { discourseCallbackVerify } from "@/lib/discourse/verify"; import { findAuthorization } from "@/lib/dto/authorization"; import { getClientByClientId } from "@/lib/dto/client"; import { getAuthorizeUrl } from "@/lib/oauth/authorize-url"; -import { q58CallbackVerify } from "@/lib/q58/verify"; import { AuthorizationCard } from "@/components/auth/authorization-card"; -export interface Q58CallbackParams extends Record { +export interface DiscourseCallbackParams extends Record { sig: string; sso: string; oauth: string; } -export default async function Q58CallbackPage({ +export default async function DiscourseCallbackPage({ searchParams, }: { - searchParams: Q58CallbackParams; + searchParams: DiscourseCallbackParams; }) { const oauthParams = new URLSearchParams(atob(searchParams.oauth)); // check client info @@ -28,7 +28,10 @@ export default async function Q58CallbackPage({ } // verify discourse callback - const user = await q58CallbackVerify(searchParams.sso, searchParams.sig); + const user = await discourseCallbackVerify( + searchParams.sso, + searchParams.sig, + ); // check authorization const authorization = await findAuthorization(user.id, client.id); diff --git a/src/auth.config.ts b/src/auth.config.ts index 35cbbd4..b93490c 100644 --- a/src/auth.config.ts +++ b/src/auth.config.ts @@ -1,7 +1,7 @@ import type { NextAuthConfig } from "next-auth"; import Credentials from "next-auth/providers/credentials"; -import { q58CallbackVerify } from "./lib/q58/verify"; +import { discourseCallbackVerify } from "./lib/discourse/verify"; // Notice this is only an object, not a full Auth.js instance export default { @@ -14,7 +14,7 @@ export default { authorize: async (credentials) => { const sso = credentials.sso as string; const sig = credentials.sig as string; - const user = await q58CallbackVerify(sso, sig); + const user = await discourseCallbackVerify(sso, sig); return user; }, }), diff --git a/src/lib/discourse/verify.ts b/src/lib/discourse/verify.ts index 607bcad..8c36d1b 100644 --- a/src/lib/discourse/verify.ts +++ b/src/lib/discourse/verify.ts @@ -8,11 +8,11 @@ import hmacSHA256 from "crypto-js/hmac-sha256"; import { AUTH_NONCE } from "@/lib/constants"; import { createUser, getUserById, updateUser } from "@/lib/dto/user"; -const Q58_SECRET = process.env.DISCOURSE_SECRET as string; +const DISCOUSE_SECRET = process.env.DISCOURSE_SECRET as string; -export async function q58CallbackVerify(sso: string, sig: string) { +export async function discourseCallbackVerify(sso: string, sig: string) { // 校验数据正确性 - if (hmacSHA256(sso, Q58_SECRET).toString(Hex) != sig) { + if (hmacSHA256(sso, DISCOUSE_SECRET).toString(Hex) != sig) { throw new Error("Request params is invalid (code: -1001)."); } // 校验 nonce diff --git a/src/lib/q58/verify.ts b/src/lib/q58/verify.ts deleted file mode 100644 index 607bcad..0000000 --- a/src/lib/q58/verify.ts +++ /dev/null @@ -1,74 +0,0 @@ -import "server-only"; - -import { cookies } from "next/headers"; -import { UserRole } from "@prisma/client"; -import Hex from "crypto-js/enc-hex"; -import hmacSHA256 from "crypto-js/hmac-sha256"; - -import { AUTH_NONCE } from "@/lib/constants"; -import { createUser, getUserById, updateUser } from "@/lib/dto/user"; - -const Q58_SECRET = process.env.DISCOURSE_SECRET as string; - -export async function q58CallbackVerify(sso: string, sig: string) { - // 校验数据正确性 - if (hmacSHA256(sso, Q58_SECRET).toString(Hex) != sig) { - throw new Error("Request params is invalid (code: -1001)."); - } - // 校验 nonce - const cookieStore = cookies(); - let searchParams = new URLSearchParams(atob(sso as string)); - const nonce = searchParams.get("nonce"); - if (!cookieStore.has(AUTH_NONCE) || !nonce) { - throw new Error("Request params is invalid (code: -1002)."); - } - if (cookieStore.get(AUTH_NONCE)?.value != nonce) { - throw new Error("Request params is invalid (code: -1003)."); - } - // cookieStore.delete(AUTH_NONCE); - - const id = searchParams.get("external_id"); - const email = searchParams.get("email"); - const username = searchParams.get("username"); - const name = searchParams.get("name"); - const avatarUrl = searchParams.get("avatar_url"); - const isAdmin = searchParams.get("admin") == "true"; - const moderator = searchParams.get("moderator") == "true"; - const groups = searchParams.get("groups")?.split(","); - if (!id || !email || !username) { - throw new Error("User not found."); - } - - // 查数据库是否有人 - let dbUser = await getUserById(id); - if (dbUser) { - // 更新 - dbUser = await updateUser(id, { - username, - email, - name, - avatarUrl, - role: isAdmin ? UserRole.ADMIN : UserRole.USER, - moderator, - groups, - }); - } else { - // 创建 - dbUser = await createUser({ - id, - username, - email, - name, - avatarUrl, - role: isAdmin ? UserRole.ADMIN : UserRole.USER, - moderator, - groups, - }); - } - - if (!dbUser) { - throw new Error("User not create success."); - } - - return dbUser; -} diff --git a/src/lib/session.ts b/src/lib/session.ts index d61315c..eba6f94 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -1,7 +1,12 @@ +import "server-only"; + import { cache } from "react"; import { auth } from "@/auth"; export const getCurrentUser = cache(async () => { const session = await auth(); - return session?.user; + if (!session?.user) { + return undefined; + } + return session.user; });