oauth_nest_demo/OAuth-JWT-Integration.md

4.2 KiB
Raw Blame History

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 用户专用的方法:

  1. findUserByProvider(provider, providerId) - 根据第三方平台信息查找用户
  2. createOAuthUser(provider, providerId, providerUsername, email) - 创建 OAuth 用户

用户名生成策略

为避免用户名冲突OAuth 用户的用户名格式为:

  • 格式:{provider}_{providerUsername}
  • 示例:github_octocat, lark_zhangsan
  • 如果冲突,自动添加数字后缀:github_octocat_1

🔄 OAuth 流程

GitHub OAuth 流程

  1. 登录入口GET /github/login?redirectUri=<回调地址>
  2. OAuth 回调GET /github/callback?code=<授权码>
  3. 处理流程
    授权码 → GitHub Access Token → 用户信息 → 查找/创建本地用户 → 生成 JWT Token
    

飞书 OAuth 流程

  1. 登录入口GET /lark/login?redirectUri=<回调地址>
  2. OAuth 回调GET /lark/callback?code=<授权码>
  3. 处理流程
    授权码 → 飞书 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
}

🛡️ 安全特性

  1. 用户隔离 - OAuth 用户和本地用户完全分离
  2. 唯一标识 - 使用 provider + providerId 作为唯一标识
  3. JWT 安全 - 使用项目统一的 JWT 密钥和过期策略
  4. 缓存机制 - 第三方 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}`
  }
});

📋 优势

  1. 统一认证 - 所有用户最终都使用项目的 JWT Token
  2. 类型安全 - 完整的 TypeScript 类型定义
  3. 扩展性强 - 易于添加新的 OAuth 提供商
  4. 数据一致性 - 统一的用户数据模型
  5. 安全可靠 - 遵循 OAuth 2.0 和 JWT 最佳实践