4.2 KiB
4.2 KiB
OAuth JWT 集成实现文档
🎯 实现目标
将飞书和 GitHub 的第三方 OAuth access_token 转换为项目自己的 JWT Token,实现统一的认证体系。
🏗️ 架构设计
用户数据模型扩展
扩展了 User 实体以支持多种登录方式:
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
username: string;
@Column({ nullable: true }) // OAuth 用户不需要密码
password: string;
@Column()
email: string;
@Column({ default: true })
isActive: boolean;
// OAuth 相关字段
@Column({ nullable: true })
provider: string; // 'local', 'github', 'lark'
@Column({ nullable: true })
providerId: string; // 第三方平台的用户ID
@Column({ nullable: true })
providerUsername: string; // 第三方平台的用户名
// JWT 相关字段
@Column({ nullable: true })
refreshToken: string;
@Column({ nullable: true })
refreshTokenExpires: Date;
}
UserService 扩展
添加了 OAuth 用户专用的方法:
findUserByProvider(provider, providerId)- 根据第三方平台信息查找用户createOAuthUser(provider, providerId, providerUsername, email)- 创建 OAuth 用户
用户名生成策略
为避免用户名冲突,OAuth 用户的用户名格式为:
- 格式:
{provider}_{providerUsername} - 示例:
github_octocat,lark_zhangsan - 如果冲突,自动添加数字后缀:
github_octocat_1
🔄 OAuth 流程
GitHub OAuth 流程
- 登录入口:
GET /github/login?redirectUri=<回调地址> - OAuth 回调:
GET /github/callback?code=<授权码> - 处理流程:
授权码 → GitHub Access Token → 用户信息 → 查找/创建本地用户 → 生成 JWT Token
飞书 OAuth 流程
- 登录入口:
GET /lark/login?redirectUri=<回调地址> - OAuth 回调:
GET /lark/callback?code=<授权码> - 处理流程:
授权码 → 飞书 Access Token → 用户信息 → 查找/创建本地用户 → 生成 JWT Token
📝 API 响应格式
成功响应
{
"message": "GitHub login successful",
"user": {
"id": 1,
"username": "github_octocat",
"email": "octocat@github.com",
"provider": "github",
"providerUsername": "octocat"
},
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 3600,
"expires_at": 1703123456789,
"refresh_token_expires_in": 604800,
"refresh_token_expires_at": 1703728256789
}
🛡️ 安全特性
- 用户隔离 - OAuth 用户和本地用户完全分离
- 唯一标识 - 使用
provider + providerId作为唯一标识 - JWT 安全 - 使用项目统一的 JWT 密钥和过期策略
- 缓存机制 - 第三方 token 和用户信息缓存,减少 API 调用
🔧 配置要求
环境变量
# GitHub OAuth
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
GITHUB_CALLBACK_URL=http://localhost:3030/auth/github/callback
# 飞书 OAuth
FEISHU_APP_ID=your_feishu_app_id
FEISHU_APP_SECRET=your_feishu_app_secret
# JWT
JWT_SECRET=your_jwt_secret
🧪 测试
访问测试页面:http://localhost:8000/test-github-sso.html
支持的登录方式:
- GitHub OAuth
- 飞书 OAuth
- Passport GitHub 策略(用于重定向场景)
🚀 使用示例
前端调用
// GitHub 登录
window.location.href = 'http://localhost:3030/github/login?redirectUri=' +
encodeURIComponent(window.location.origin + '/callback');
// 飞书登录
window.location.href = 'http://localhost:3030/lark/login?redirectUri=' +
encodeURIComponent(window.location.origin + '/callback');
使用 JWT Token
// 在后续请求中使用 JWT Token
fetch('/api/protected', {
headers: {
'Authorization': `Bearer ${access_token}`
}
});
📋 优势
- 统一认证 - 所有用户最终都使用项目的 JWT Token
- 类型安全 - 完整的 TypeScript 类型定义
- 扩展性强 - 易于添加新的 OAuth 提供商
- 数据一致性 - 统一的用户数据模型
- 安全可靠 - 遵循 OAuth 2.0 和 JWT 最佳实践