mirror of
https://github.com/woodchen-ink/Q58Connect.git
synced 2025-07-18 14:01:55 +08:00
refactor: Rename Q58 OAuth callback to Discourse OAuth
This commit is contained in:
parent
569ba4c186
commit
42036544bf
@ -1,22 +1,22 @@
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
|
import { discourseCallbackVerify } from "@/lib/discourse/verify";
|
||||||
import { findAuthorization } from "@/lib/dto/authorization";
|
import { findAuthorization } from "@/lib/dto/authorization";
|
||||||
import { getClientByClientId } from "@/lib/dto/client";
|
import { getClientByClientId } from "@/lib/dto/client";
|
||||||
import { getAuthorizeUrl } from "@/lib/oauth/authorize-url";
|
import { getAuthorizeUrl } from "@/lib/oauth/authorize-url";
|
||||||
import { q58CallbackVerify } from "@/lib/q58/verify";
|
|
||||||
import { AuthorizationCard } from "@/components/auth/authorization-card";
|
import { AuthorizationCard } from "@/components/auth/authorization-card";
|
||||||
|
|
||||||
export interface Q58CallbackParams extends Record<string, string> {
|
export interface DiscourseCallbackParams extends Record<string, string> {
|
||||||
sig: string;
|
sig: string;
|
||||||
sso: string;
|
sso: string;
|
||||||
oauth: string;
|
oauth: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Q58CallbackPage({
|
export default async function DiscourseCallbackPage({
|
||||||
searchParams,
|
searchParams,
|
||||||
}: {
|
}: {
|
||||||
searchParams: Q58CallbackParams;
|
searchParams: DiscourseCallbackParams;
|
||||||
}) {
|
}) {
|
||||||
const oauthParams = new URLSearchParams(atob(searchParams.oauth));
|
const oauthParams = new URLSearchParams(atob(searchParams.oauth));
|
||||||
// check client info
|
// check client info
|
||||||
@ -28,7 +28,10 @@ export default async function Q58CallbackPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verify discourse callback
|
// verify discourse callback
|
||||||
const user = await q58CallbackVerify(searchParams.sso, searchParams.sig);
|
const user = await discourseCallbackVerify(
|
||||||
|
searchParams.sso,
|
||||||
|
searchParams.sig,
|
||||||
|
);
|
||||||
|
|
||||||
// check authorization
|
// check authorization
|
||||||
const authorization = await findAuthorization(user.id, client.id);
|
const authorization = await findAuthorization(user.id, client.id);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { NextAuthConfig } from "next-auth";
|
import type { NextAuthConfig } from "next-auth";
|
||||||
import Credentials from "next-auth/providers/credentials";
|
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
|
// Notice this is only an object, not a full Auth.js instance
|
||||||
export default {
|
export default {
|
||||||
@ -14,7 +14,7 @@ export default {
|
|||||||
authorize: async (credentials) => {
|
authorize: async (credentials) => {
|
||||||
const sso = credentials.sso as string;
|
const sso = credentials.sso as string;
|
||||||
const sig = credentials.sig as string;
|
const sig = credentials.sig as string;
|
||||||
const user = await q58CallbackVerify(sso, sig);
|
const user = await discourseCallbackVerify(sso, sig);
|
||||||
return user;
|
return user;
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -8,11 +8,11 @@ import hmacSHA256 from "crypto-js/hmac-sha256";
|
|||||||
import { AUTH_NONCE } from "@/lib/constants";
|
import { AUTH_NONCE } from "@/lib/constants";
|
||||||
import { createUser, getUserById, updateUser } from "@/lib/dto/user";
|
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).");
|
throw new Error("Request params is invalid (code: -1001).");
|
||||||
}
|
}
|
||||||
// 校验 nonce
|
// 校验 nonce
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -1,7 +1,12 @@
|
|||||||
|
import "server-only";
|
||||||
|
|
||||||
import { cache } from "react";
|
import { cache } from "react";
|
||||||
import { auth } from "@/auth";
|
import { auth } from "@/auth";
|
||||||
|
|
||||||
export const getCurrentUser = cache(async () => {
|
export const getCurrentUser = cache(async () => {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
return session?.user;
|
if (!session?.user) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return session.user;
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user