fenghuo/apps/backend/README.md

286 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OIDC Provider Demo
这是一个基于 Hono 后端的 OpenID Connect (OIDC) Provider 演示应用使用了标准的OIDC架构设计。
## 功能特性
- ✅ 完整的 OIDC Provider 实现
- ✅ 支持授权码流程 (Authorization Code Flow)
- ✅ 支持 PKCE (Proof Key for Code Exchange)
- ✅ 内置认证处理器
- ✅ JWT 令牌签发和验证
- ✅ 用户信息端点
- ✅ 令牌撤销
- ✅ Redis 存储适配器
- ✅ 内置登录页面
## 标准OIDC架构
### 使用内置认证处理器(推荐)
```typescript
import { createOIDCProvider } from '@repo/oidc-provider';
// 使用内置认证处理器Provider自己处理登录
const oidcApp = createOIDCProvider({
config: oidcConfig,
useBuiltInAuth: true,
builtInAuthConfig: {
passwordValidator: validatePassword,
sessionTTL: 24 * 60 * 60, // 24小时
loginPageTitle: 'OIDC Demo 登录',
brandName: 'OIDC Demo Provider',
},
});
```
### 自定义认证处理器(高级用法)
```typescript
import { createOIDCProvider, type AuthHandler } from '@repo/oidc-provider';
class MyAuthHandler implements AuthHandler {
async getCurrentUser(c: Context): Promise<string | null> {
// 检查用户认证状态
// 例如从JWT token、session或cookie中获取用户ID
const token = c.req.header('Authorization');
return await verifyTokenAndGetUserId(token);
}
async handleAuthRequired(c: Context, authRequest: AuthorizationRequest): Promise<Response> {
// 处理未认证用户
// 例如:显示自定义登录页面或重定向到外部认证服务
return this.showCustomLoginPage(c, authRequest);
}
}
const oidcApp = createOIDCProvider({
config: oidcConfig,
authHandler: new MyAuthHandler()
});
```
## 启动服务
```bash
# 在项目根目录
cd apps/backend
bun run dev
```
服务将在 `http://localhost:8000` 启动。
## 当前配置
当前的 OIDC Provider 已配置为:
- 使用内置认证处理器Provider自己处理所有登录逻辑
- 支持标准OIDC授权码流程
- 使用 Redis 存储令牌和会话
## OIDC 端点
### 发现文档
```
GET http://localhost:8000/oidc/.well-known/openid-configuration
```
### 主要端点
- **授权端点**: `http://localhost:8000/oidc/auth`
- **令牌端点**: `http://localhost:8000/oidc/token`
- **用户信息端点**: `http://localhost:8000/oidc/userinfo`
- **JWKS端点**: `http://localhost:8000/oidc/.well-known/jwks.json`
- **撤销端点**: `http://localhost:8000/oidc/revoke`
## 测试客户端
### 机密客户端 (Confidential Client)
```
Client ID: demo-client
Client Secret: demo-client-secret
重定向URI:
- http://localhost:3000/callback
- http://localhost:8080/callback
- https://oauth.pstmn.io/v1/callback
```
### 公共客户端 (Public Client)
```
Client ID: demo-public-client
重定向URI:
- http://localhost:3000/callback
- myapp://callback
```
## 测试用户
```
用户名: demouser
密码: password
用户ID (sub): demo-user
```
## API 测试
运行测试脚本验证新API
```bash
cd apps/backend
bun run test-oidc.ts
```
## 授权流程
1. **客户端发起授权请求**: 访问 `/oidc/auth` 端点
2. **检查用户认证**: AuthHandler 检查用户是否已认证
3. **用户认证**: 如未认证,重定向到登录页面
4. **生成授权码**: 认证成功后生成授权码
5. **交换访问令牌**: 客户端使用授权码换取访问令牌
6. **访问资源**: 使用访问令牌访问用户信息等资源
## 配置说明
```typescript
import { createOIDCProvider, DefaultAuthHandler } from '@repo/oidc-provider';
const oidcConfig = {
issuer: 'http://localhost:8000/oidc',
signingKey: 'your-secret-key',
storage: redisAdapter,
findClient: async (clientId) => { /* 查找客户端 */ },
findUser: async (userId) => { /* 查找用户 */ },
// ... 其他配置
};
// 方式1: 使用内置认证处理器(推荐)
const app1 = createOIDCProvider({
config: oidcConfig,
useBuiltInAuth: true,
builtInAuthConfig: {
passwordValidator: validatePassword,
sessionTTL: 24 * 60 * 60,
loginPageTitle: 'OIDC Demo 登录',
brandName: 'OIDC Demo Provider',
},
});
// 方式2: 使用自定义处理器(高级用法)
const app2 = createOIDCProvider({
config: oidcConfig,
authHandler: new CustomAuthHandler()
});
```
## 与 Next.js Web 应用集成
1. **标准OIDC流程**: Next.js 应用使用标准 oidc-client-ts 库
2. **认证处理**: OIDC Provider 自己处理所有用户认证和登录页面
3. **令牌管理**: OIDC Provider 负责生成和管理所有令牌
4. **回调处理**: Next.js 应用只需处理OIDC回调获取令牌
## 技术架构
- **框架**: Hono.js
- **存储**: Redis (令牌存储)
- **JWT**: JOSE 库
- **PKCE**: 支持 SHA256 和 plain 方法
- **算法**: HS256 (可配置 RS256, ES256)
- **认证**: 可自定义认证处理器
## 优势
相比之前的实现新API具有以下优势
1. **简化配置**: 只需要提供配置对象和认证处理器
2. **灵活认证**: 支持任意认证方式JWT、Session、OAuth等
3. **清晰分离**: 认证逻辑与OIDC协议逻辑分离
4. **易于扩展**: 通过实现 AuthHandler 接口轻松自定义
5. **类型安全**: 完整的 TypeScript 类型支持
## 开发说明
- 修改客户端或用户数据:编辑 `src/oidc-demo.ts`
- 自定义认证逻辑:实现 `AuthHandler` 接口
- 配置调整:修改 `oidcConfig` 对象
## 快速测试
1. **Web界面测试**
访问 http://localhost:8000 查看完整的测试界面
2. **授权流程测试**
访问 http://localhost:8000/oidc/auth?response_type=code&client_id=demo-client&redirect_uri=https://oauth.pstmn.io/v1/callback&scope=openid%20profile%20email&state=test-state
3. **Postman测试**
使用以下配置在 Postman 中测试 OAuth 2.0:
```
授权URL: http://localhost:8000/oidc/auth
令牌URL: http://localhost:8000/oidc/token
回调URL: https://oauth.pstmn.io/v1/callback
Client ID: demo-client
Client Secret: demo-client-secret
作用域: openid profile email
```
## 完整的授权码流程
### 1. 授权请求
```
GET http://localhost:8000/oidc/auth?response_type=code&client_id=demo-client&redirect_uri=https://oauth.pstmn.io/v1/callback&scope=openid%20profile%20email&state=random-state
```
### 2. 用户登录
系统会自动重定向到登录页面,使用测试用户登录
### 3. 获取授权码
登录成功后会重定向到 `redirect_uri` 并携带授权码
### 4. 交换访问令牌
```bash
curl -X POST http://localhost:8000/oidc/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=YOUR_CODE&redirect_uri=https://oauth.pstmn.io/v1/callback&client_id=demo-client&client_secret=demo-client-secret"
```
### 5. 访问用户信息
```bash
curl -X GET http://localhost:8000/oidc/userinfo \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
## 支持的作用域和声明
### 作用域 (Scopes)
- `openid` - 必需的基础作用域
- `profile` - 用户基本信息
- `email` - 邮箱信息
- `phone` - 电话号码
- `address` - 地址信息
### 声明 (Claims)
- `sub` - 用户唯一标识
- `name`, `given_name`, `family_name` - 姓名信息
- `email`, `email_verified` - 邮箱信息
- `phone_number`, `phone_number_verified` - 电话信息
- `picture`, `profile`, `website` - 个人资料
- `gender`, `birthdate`, `zoneinfo`, `locale` - 基本信息
- `address` - 地址信息
- `updated_at` - 更新时间
## 安全注意事项
⚠️ **这是一个演示应用,不应用于生产环境!**
生产环境部署时需要注意:
1. 使用强密钥和安全的签名算法
2. 实现真实的用户认证和会话管理
3. 添加适当的安全头和 CSRF 保护
4. 使用 HTTPS
5. 实现客户端注册和管理
6. 添加速率限制和监控
7. 定期轮换密钥
## 开发和扩展
如需修改客户端或用户数据,编辑 `src/oidc-demo.ts` 文件中的 `demoClients``demoUsers` 数组。
如需自定义认证逻辑,修改 `src/index.ts` 中的登录处理逻辑。