refactor: Rename Q58 OAuth callback to Discourse OAuth

This commit is contained in:
wood chen 2025-02-23 02:35:29 +08:00
parent 569ba4c186
commit 42036544bf
5 changed files with 19 additions and 85 deletions

View File

@ -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<string, string> {
export interface DiscourseCallbackParams extends Record<string, string> {
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);

View File

@ -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;
},
}),

View File

@ -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

View File

@ -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;
}

View File

@ -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;
});