This is a Next.js project that implements OAuth authentication functionality using Discourse SSO (Single Sign-On) user system.
English | 简体中文
This project provides an OAuth authentication system that allows other applications to authenticate users using Discourse forum accounts. This enables users to log into your application using their existing Discourse accounts without creating new ones.
Key Features:
- User authentication based on Discourse SSO
- OAuth 2.0 protocol support
- Built with Next.js framework for excellent performance and developer experience
First, run the development server:
pnpm dev
# or
pnpm turboOpen http://localhost:3000 in your browser to see the result.
To use this OAuth system, you need to configure the following:
- Enable SSO functionality in your Discourse forum.
- Set environment variables:
NEXT_PUBLIC_HOST_URL: Application host URL (do not add "/" at the end)DATABASE_URL: Database connection stringNEXTAUTH_URL: Complete API endpoint route when customizingAUTH_SECRET: Next Auth secret keyDISCOURSE_HOST: Your Discourse forum URLDISCOURSE_SECRET: SSO secret set in Discourse
This project supports Docker deployment. Here are the steps to deploy using Docker Compose:
-
Ensure Docker and Docker Compose are installed on your system.
-
In the project root directory, run the following command to start services:
docker-compose up -d
This will build and start the web application and PostgreSQL database services.
-
The application will run on http://localhost:3000.
-
To stop services, run:
docker-compose down
Another simple way to deploy Next.js applications is using the Vercel Platform.
Check out our Next.js deployment documentation for more details.
This project implements an authentication system based on the OAuth 2.0 protocol. Here are the main OAuth interfaces and their usage instructions:
Endpoint: /oauth2/authorize
Method: GET
Parameters:
response_type: Must be "code"client_id: Your client IDredirect_uri: URI to redirect after authorizationscope: (Optional) Requested permission scope
Example:
/oauth2/authorize?response_type=code&client_id=your_client_id&redirect_uri=https://your-app.com/callback&scope=read:user
Endpoint: /oauth2/token
Method: POST
Parameters:
| Parameter | Required | Description |
|---|---|---|
| grant_type | Yes | Grant type, authorization_code or refresh_token |
| code | No | Authorization code, required when grant_type=authorization_code |
| redirect_uri | No | Redirect URI, required when grant_type=authorization_code |
| refresh_token | No | Refresh token, required when grant_type=refresh_token |
| client_id | Yes | Client ID |
| client_secret | No | Client secret (required for confidential clients) |
| scope | No | Permission scope, defaults to authorization scope if empty |
Response:
{
"access_token": "at_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "rt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"scope": "read:user"
}access_token: Access tokentoken_type: Type, fixed asbearerexpires_in: Validity period (seconds)refresh_token: Refresh token (if supported)scope: Actually granted permission scope
Notes:
- Refresh token validity is usually 30 days, access token validity is 1 hour
- When using refresh token to get new access token, the old access token is revoked
- If scope parameter is not passed, it defaults to original authorization; if passed, it must be a subset of original authorization scope
Endpoint: /oauth2/revoke
Method: POST
Parameters:
token: Access token or refresh token to revoketoken_type_hint: (Optional)access_tokenorrefresh_tokenclient_id: Client IDclient_secret: Client secret (required for confidential clients)
Request Example (application/x-www-form-urlencoded):
token=rt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&token_type_hint=refresh_token&client_id=your_client_id&client_secret=your_client_secret
Response:
- Returns HTTP 200 with no content on success
- Returns JSON error information on parameter errors
Notes:
- Revoking refresh token also revokes corresponding access token
- Revoking access token also revokes its associated refresh token
- Returns 200 even if token doesn't exist (complies with RFC 7009)
Endpoint: /api/user/profile
Method: GET
Request Headers:
Authorization: Bearer {access_token}
Response:
{
"id": "user_id",
"email": "user@example.com",
"username": "username",
"avatar_url": "https://example.com/avatar.jpg",
"name": "User Name"
}- Format: Scope parameter is a space-separated string, e.g.,
read:user - Supported scopes:
read:user: Read basic user information
- Validation rules:
- Only registered scopes are allowed, illegal scopes return errors
- Scope tokens only allow letters, numbers, underscores, hyphens
- If scope is empty, default permissions are used
- Redirect user to authorization page (
/oauth2/authorize) - After user authorization, your application receives an authorization code
- Use authorization code to request access token (
/oauth2/token) - Use access token to get user information (
/api/user/profile)
Note: Ensure to use HTTPS in production to protect all OAuth requests and responses.
Contributions, issue reports, and improvement suggestions are welcome.
This project is licensed under the MIT License. See the LICENSE file for details.