mirror of
https://github.com/woodchen-ink/Q58Connect.git
synced 2025-07-18 05:51:55 +08:00
fix: replace discourse host with env & typo, update README
This commit is contained in:
parent
b8368cfc32
commit
b8f7fcf180
@ -10,7 +10,9 @@ NEXT_PUBLIC_HOST_URL=
|
|||||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
||||||
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
|
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
|
||||||
|
|
||||||
# NextAuth.js
|
# Next Auth
|
||||||
AUTH_SECRET=
|
AUTH_SECRET=
|
||||||
|
|
||||||
DISCOUSE_SECRET=
|
# Discourse SSO
|
||||||
|
DISCOURSE_HOST=
|
||||||
|
DISCOURSE_SECRET=
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Tuluobo
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
157
README.md
157
README.md
@ -1,36 +1,153 @@
|
|||||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
# Discourse Connect
|
||||||
|
|
||||||
## Getting Started
|
这是一个基于 [Next.js](https://nextjs.org/) 的项目,实现了使用 Discourse SSO (Single Sign-On) 用户系统的 OAuth 认证功能。
|
||||||
|
|
||||||
First, run the development server:
|
## 项目概述
|
||||||
|
|
||||||
|
本项目提供了一个 OAuth 认证系统,允许其他应用程序使用 Discourse 论坛的用户账号进行身份验证。这样可以让用户使用他们已有的 Discourse 账号登录到您的应用程序,无需创建新的账号。
|
||||||
|
|
||||||
|
主要特性:
|
||||||
|
|
||||||
|
- 基于 Discourse SSO 的用户认证
|
||||||
|
- OAuth 2.0 协议支持
|
||||||
|
- 使用 Next.js 框架构建,提供良好的性能和开发体验
|
||||||
|
|
||||||
|
## 开始使用
|
||||||
|
|
||||||
|
首先,运行开发服务器:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
|
||||||
# or
|
|
||||||
yarn dev
|
|
||||||
# or
|
|
||||||
pnpm dev
|
pnpm dev
|
||||||
# or
|
# 或
|
||||||
bun dev
|
pnpm turbo
|
||||||
```
|
```
|
||||||
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
在浏览器中打开 [http://localhost:3000](http://localhost:3000) 查看结果。
|
||||||
|
|
||||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
您可以通过修改 `app/page.tsx` 来开始编辑页面。当您编辑文件时,页面会自动更新。
|
||||||
|
|
||||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
## 配置
|
||||||
|
|
||||||
## Learn More
|
要使用此 OAuth 系统,您需要进行以下配置:
|
||||||
|
|
||||||
To learn more about Next.js, take a look at the following resources:
|
1. 在您的 Discourse 论坛中启用 SSO 功能。
|
||||||
|
2. 设置环境变量:
|
||||||
|
- `NEXT_PUBLIC_HOST_URL`: 应用程序的主机 URL(不要在末尾添加 "/")
|
||||||
|
- `DATABASE_URL`: 数据库连接字符串
|
||||||
|
- `AUTH_SECRET`: Next Auth 的密钥
|
||||||
|
- `DISCOURSE_HOST`: 您的 Discourse 论坛 URL
|
||||||
|
- `DISCOURSE_SECRET`: 在 Discourse 中设置的 SSO secret
|
||||||
|
|
||||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
## 部署
|
||||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
||||||
|
|
||||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
### 使用 Docker 部署
|
||||||
|
|
||||||
## Deploy on Vercel
|
本项目支持使用 Docker 进行部署。以下是使用 Docker Compose 部署的步骤:
|
||||||
|
|
||||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
1. 确保您的系统已安装 Docker 和 Docker Compose。
|
||||||
|
|
||||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
2. 在项目根目录下,运行以下命令启动服务:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
这将构建并启动 Web 应用和 PostgreSQL 数据库服务。
|
||||||
|
|
||||||
|
3. 应用将在 http://localhost:3000 上运行。
|
||||||
|
|
||||||
|
4. 要停止服务,运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 Vercel 部署
|
||||||
|
|
||||||
|
另一种部署 Next.js 应用程序的简单方法是使用 [Vercel 平台](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme)。
|
||||||
|
|
||||||
|
查看我们的 [Next.js 部署文档](https://nextjs.org/docs/deployment) 了解更多详情。
|
||||||
|
|
||||||
|
## OAuth 2.0 接口
|
||||||
|
|
||||||
|
本项目实现了基于 OAuth 2.0 协议的认证系统。以下是主要的 OAuth 接口及其使用说明:
|
||||||
|
|
||||||
|
### 1. 授权请求
|
||||||
|
|
||||||
|
**端点:** `/oauth/authorize`
|
||||||
|
|
||||||
|
**方法:** GET
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `response_type`: 必须为 "code"
|
||||||
|
- `client_id`: 您的客户端 ID
|
||||||
|
- `redirect_uri`: 授权后重定向的 URI
|
||||||
|
- `scope`: (可选)请求的权限范围
|
||||||
|
|
||||||
|
**示例:**
|
||||||
|
|
||||||
|
```
|
||||||
|
/oauth/authorize?response_type=code&client_id=your_client_id&redirect_uri=https://your-app.com/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 获取访问令牌
|
||||||
|
|
||||||
|
**端点:** `/api/oauth/access_token`
|
||||||
|
|
||||||
|
**方法:** POST
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
|
||||||
|
- `code`: 从授权请求中获得的授权码
|
||||||
|
- `redirect_uri`: 必须与授权请求中的 redirect_uri 相同
|
||||||
|
|
||||||
|
**响应:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"access_token": "at_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"expires_in": 604800,
|
||||||
|
"token_type": "bearer"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 获取用户信息
|
||||||
|
|
||||||
|
**端点:** `/api/oauth/user`
|
||||||
|
|
||||||
|
**方法:** GET
|
||||||
|
|
||||||
|
**请求头:**
|
||||||
|
|
||||||
|
- `Authorization: Bearer {access_token}`
|
||||||
|
|
||||||
|
**响应:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "user_id",
|
||||||
|
"email": "user@example.com",
|
||||||
|
"username": "username",
|
||||||
|
"admin": false,
|
||||||
|
"avatar_url": "https://example.com/avatar.jpg",
|
||||||
|
"name": "User Name"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用流程
|
||||||
|
|
||||||
|
1. 将用户重定向到授权页面(`/oauth/authorize`)。
|
||||||
|
2. 用户授权后,您的应用将收到一个授权码。
|
||||||
|
3. 使用授权码请求访问令牌(`/api/oauth/access_token`)。
|
||||||
|
4. 使用访问令牌获取用户信息(`/api/oauth/user`)。
|
||||||
|
|
||||||
|
注意:确保在生产环境中使用 HTTPS 来保护所有的 OAuth 请求和响应。
|
||||||
|
|
||||||
|
## 贡献
|
||||||
|
|
||||||
|
欢迎贡献代码、报告问题或提出改进建议。
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
本项目采用 MIT 许可证。详情请见 [LICENSE](LICENSE) 文件。
|
||||||
|
@ -6,7 +6,7 @@ services:
|
|||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql://next:next@db:5432/next
|
DATABASE_URL: postgresql://discourse_connect:discourse_connect@db:5432/discourse_connect
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@ -19,9 +19,9 @@ services:
|
|||||||
db:
|
db:
|
||||||
image: postgres:15-alpine
|
image: postgres:15-alpine
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: next
|
POSTGRES_DB: discourse_connect
|
||||||
POSTGRES_USER: next
|
POSTGRES_USER: discourse_connect
|
||||||
POSTGRES_PASSWORD: next
|
POSTGRES_PASSWORD: discourse_connect
|
||||||
volumes:
|
volumes:
|
||||||
- next-db-data:/var/lib/postgresql/data
|
- next-db-data:/var/lib/postgresql/data
|
||||||
restart: always
|
restart: always
|
||||||
|
@ -8,7 +8,8 @@ import WordArray from "crypto-js/lib-typedarrays";
|
|||||||
import { AUTH_NONCE } from "@/lib/constants";
|
import { AUTH_NONCE } from "@/lib/constants";
|
||||||
|
|
||||||
const appHost = process.env.NEXT_PUBLIC_HOST_URL;
|
const appHost = process.env.NEXT_PUBLIC_HOST_URL;
|
||||||
const oauthSecret = process.env.DISCOUSE_SECRET || "";
|
const discourseHost = process.env.DISCOURSE_HOST;
|
||||||
|
const oauthSecret = process.env.DISCOURSE_SECRET || "";
|
||||||
|
|
||||||
export async function getDiscourseSSOUrl(searchParams: string) {
|
export async function getDiscourseSSOUrl(searchParams: string) {
|
||||||
console.log(`searchParams: ${searchParams}`);
|
console.log(`searchParams: ${searchParams}`);
|
||||||
@ -19,5 +20,5 @@ export async function getDiscourseSSOUrl(searchParams: string) {
|
|||||||
const sig = hmacSHA256(sso, oauthSecret).toString(Hex);
|
const sig = hmacSHA256(sso, oauthSecret).toString(Hex);
|
||||||
cookies().set(AUTH_NONCE, nonce, { maxAge: 60 * 10 });
|
cookies().set(AUTH_NONCE, nonce, { maxAge: 60 * 10 });
|
||||||
|
|
||||||
return `https://shuzimumin.com/session/sso_provider?sso=${sso}&sig=${sig}`;
|
return `${discourseHost}/session/sso_provider?sso=${sso}&sig=${sig}`;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@ import WordArray from "crypto-js/lib-typedarrays";
|
|||||||
import { AUTH_NONCE } from "@/lib/constants";
|
import { AUTH_NONCE } from "@/lib/constants";
|
||||||
|
|
||||||
const hostUrl = process.env.NEXT_PUBLIC_HOST_URL as string;
|
const hostUrl = process.env.NEXT_PUBLIC_HOST_URL as string;
|
||||||
const clientSecret = process.env.DISCOUSE_SECRET as string;
|
const discourseHost = process.env.DISCOURSE_HOST as string;
|
||||||
|
const clientSecret = process.env.DISCOURSE_SECRET as string;
|
||||||
|
|
||||||
export async function POST(_req: Request) {
|
export async function POST(_req: Request) {
|
||||||
const nonce = WordArray.random(16).toString();
|
const nonce = WordArray.random(16).toString();
|
||||||
@ -16,6 +17,6 @@ export async function POST(_req: Request) {
|
|||||||
|
|
||||||
cookies().set(AUTH_NONCE, nonce, { maxAge: 60 * 10 });
|
cookies().set(AUTH_NONCE, nonce, { maxAge: 60 * 10 });
|
||||||
return Response.json({
|
return Response.json({
|
||||||
sso_url: `https://shuzimumin.com/session/sso_provider?sso=${sso}&sig=${sig}`,
|
sso_url: `${discourseHost}/session/sso_provider?sso=${sso}&sig=${sig}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ 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 DISCOUSE_SECRET = process.env.DISCOUSE_SECRET as string;
|
const DISCOUSE_SECRET = process.env.DISCOURSE_SECRET as string;
|
||||||
|
|
||||||
export async function discourseCallbackVerify(sso: string, sig: string) {
|
export async function discourseCallbackVerify(sso: string, sig: string) {
|
||||||
// 校验数据正确性
|
// 校验数据正确性
|
||||||
|
Loading…
x
Reference in New Issue
Block a user