# AuthService 文档

## 概述

AuthService 是一个功能强大的认证服务，支持 JWT、OAuth2.0 和多因子认证（MFA），为 Crawlful Hub 项目提供统一的身份认证和授权管理。

## 核心功能

### 1. JWT 认证
- 生成和验证 JWT 令牌
- 支持令牌刷新
- 携带 4-tuple TraceContext（tenantId, shopId, taskId, traceId）

### 2. OAuth2.0 认证
- 客户端管理
- 授权码流程
- 访问令牌生成和刷新
- 支持多种授权类型

### 3. 多因子认证（MFA）
- 基于时间的一次性密码（TOTP）
- 支持 SMS 和 EMAIL 验证（预留接口）

## 数据库表结构

### cf_user
- id: 用户ID
- username: 用户名
- password_hash: 密码哈希
- role: 角色
- tenant_id: 租户ID
- shop_id: 店铺ID（可选）
- status: 状态（ACTIVE/DISABLED）
- created_at: 创建时间
- updated_at: 更新时间

### cf_oauth_client
- id: 客户端ID
- client_id: 客户端标识符
- client_secret: 客户端密钥哈希
- redirect_uri: 重定向URI
- grant_types: 授权类型
- scope: 权限范围
- tenant_id: 租户ID
- created_at: 创建时间
- updated_at: 更新时间

### cf_oauth_code
- id: 授权码ID
- code: 授权码
- client_id: 客户端ID
- user_id: 用户ID
- redirect_uri: 重定向URI
- scope: 权限范围
- expires_at: 过期时间
- created_at: 创建时间
- updated_at: 更新时间

### cf_oauth_token
- id: 令牌ID
- access_token: 访问令牌
- refresh_token: 刷新令牌
- client_id: 客户端ID
- user_id: 用户ID
- scope: 权限范围
- expires_at: 过期时间
- created_at: 创建时间
- updated_at: 更新时间

### cf_user_mfa
- id: MFA记录ID
- user_id: 用户ID
- method: 认证方法（TOTP/SMS/EMAIL）
- secret: 密钥
- enabled: 是否启用
- created_at: 创建时间
- updated_at: 更新时间

### cf_refresh_token
- id: 刷新令牌ID
- user_id: 用户ID
- token: 刷新令牌
- expires_at: 过期时间
- created_at: 创建时间
- updated_at: 更新时间

## API 接口

### 公开接口

#### POST /api/auth/login
- 功能：用户登录
- 请求参数：
  - username: 用户名
  - password: 密码
- 响应：
  - token: JWT令牌
  - refreshToken: 刷新令牌
  - user: 用户信息

#### POST /api/auth/refresh
- 功能：刷新令牌
- 请求参数：
  - refreshToken: 刷新令牌
- 响应：
  - token: 新的JWT令牌
  - user: 用户信息

#### POST /api/auth/register
- 功能：注册新用户
- 请求参数：
  - username: 用户名
  - password: 密码
  - role: 角色
  - tenantId: 租户ID
  - shopId: 店铺ID（可选）
- 响应：
  - user: 用户信息

#### POST /api/auth/oauth2/token
- 功能：获取OAuth2.0访问令牌
- 请求参数：
  - grant_type: 授权类型（authorization_code/refresh_token）
  - code: 授权码（当grant_type为authorization_code时）
  - refresh_token: 刷新令牌（当grant_type为refresh_token时）
  - client_id: 客户端ID
  - client_secret: 客户端密钥
  - redirect_uri: 重定向URI
- 响应：
  - access_token: 访问令牌
  - refresh_token: 刷新令牌
  - expires_in: 过期时间（秒）
  - scope: 权限范围

### 需要认证的接口

#### GET /api/auth/me
- 功能：获取当前用户信息
- 响应：
  - user: 用户信息

#### POST /api/auth/mfa/enable
- 功能：启用多因子认证
- 请求参数：
  - method: 认证方法（TOTP/SMS/EMAIL）
  - secret: 密钥
- 响应：
  - success: 是否成功

#### POST /api/auth/mfa/verify
- 功能：验证多因子认证码
- 请求参数：
  - method: 认证方法（TOTP/SMS/EMAIL）
  - code: 验证码
- 响应：
  - success: 是否成功

#### GET /api/auth/oauth2/authorize
- 功能：OAuth2.0授权
- 请求参数：
  - client_id: 客户端ID
  - redirect_uri: 重定向URI
  - scope: 权限范围
  - state: 状态参数
- 响应：
  - 重定向到redirect_uri，携带code和state参数

#### POST /api/auth/oauth2/client
- 功能：创建OAuth2.0客户端
- 请求参数：
  - clientId: 客户端ID
  - clientSecret: 客户端密钥
  - redirectUri: 重定向URI
  - grantTypes: 授权类型
  - scope: 权限范围
- 响应：
  - success: 是否成功

## 使用示例

### JWT 认证

```typescript
// 登录
const loginResponse = await fetch('/api/auth/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    username: 'admin',
    password: 'admin123'
  })
});

const { token, refreshToken, user } = await loginResponse.json();

// 使用令牌访问受保护的接口
const protectedResponse = await fetch('/api/auth/me', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

// 刷新令牌
const refreshResponse = await fetch('/api/auth/refresh', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    refreshToken
  })
});

const { token: newToken } = await refreshResponse.json();
```

### OAuth2.0 认证

```typescript
// 1. 重定向用户到授权页面
const authorizationUrl = `/api/auth/oauth2/authorize?client_id=client1&redirect_uri=http://localhost:3000/callback&scope=read%20write&state=12345`;
window.location.href = authorizationUrl;

// 2. 处理回调（在redirect_uri指定的页面）
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');

// 3. 使用授权码获取访问令牌
const tokenResponse = await fetch('/api/auth/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    code,
    client_id: 'client1',
    client_secret: 'secret1',
    redirect_uri: 'http://localhost:3000/callback'
  })
});

const { access_token, refresh_token, expires_in, scope } = await tokenResponse.json();

// 4. 使用访问令牌访问受保护的接口
const protectedResponse = await fetch('/api/protected', {
  headers: {
    'Authorization': `Bearer ${access_token}`
  }
});

// 5. 使用刷新令牌获取新的访问令牌
const refreshResponse = await fetch('/api/auth/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    grant_type: 'refresh_token',
    refresh_token,
    client_id: 'client1',
    client_secret: 'secret1'
  })
});

const { access_token: newAccessToken } = await refreshResponse.json();
```

### 多因子认证

```typescript
// 1. 生成TOTP密钥
const { secret, otpauthUrl } = AuthService.generateTOTPSecret();

// 2. 启用MFA
const enableResponse = await fetch('/api/auth/mfa/enable', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`
  },
  body: JSON.stringify({
    method: 'TOTP',
    secret
  })
});

// 3. 验证MFA码
const verifyResponse = await fetch('/api/auth/mfa/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`
  },
  body: JSON.stringify({
    method: 'TOTP',
    code: '123456' // 从认证器应用获取
  })
});

const { success } = await verifyResponse.json();
```

## 安全注意事项

1. **密码安全**：使用 bcrypt 对密码进行哈希处理，避免明文存储
2. **令牌安全**：JWT 令牌和 OAuth2.0 令牌都有过期时间，避免长期使用
3. **密钥管理**：JWT 密钥和 MFA 密钥应该妥善保管，避免泄露
4. **权限控制**：基于角色的访问控制（RBAC），确保用户只能访问授权的资源
5. **输入验证**：所有用户输入都应该进行验证，避免注入攻击
6. **HTTPS**：在生产环境中使用 HTTPS，避免数据传输过程中的窃听

## 部署配置

### 环境变量

- `JWT_SECRET`：JWT 签名密钥，生产环境中应该使用强随机字符串
- `JWT_EXPIRES_IN`：JWT 令牌过期时间，默认 24h
- `REFRESH_TOKEN_EXPIRES_IN`：刷新令牌过期时间，默认 7d
- `OAUTH2_ACCESS_TOKEN_EXPIRES_IN`：OAuth2.0 访问令牌过期时间，默认 1h
- `OAUTH2_AUTH_CODE_EXPIRES_IN`：OAuth2.0 授权码过期时间，默认 10m

### 数据库配置

- 使用 MySQL 8.0
- 所有表都以 `cf_` 为前缀
- 建立适当的索引，提高查询性能
- 使用外键约束，确保数据完整性

## 故障排查

### 常见问题

1. **令牌过期**：如果收到 401 Unauthorized 错误，检查令牌是否过期，使用刷新令牌获取新令牌
2. **密码错误**：如果登录失败，检查用户名和密码是否正确
3. **MFA 验证失败**：检查 TOTP 码是否正确，确保时间同步
4. **OAuth2.0 授权失败**：检查客户端 ID、密钥和重定向 URI 是否正确

### 日志

AuthService 会记录所有认证相关的操作和错误，日志文件位于 `logs/` 目录下，可以通过查看日志来排查问题。

## 总结

AuthService 是一个功能完整、安全可靠的认证服务，支持多种认证方式，为 Crawlful Hub 项目提供统一的身份认证和授权管理。通过合理使用 AuthService，可以确保系统的安全性和可靠性，同时为用户提供良好的认证体验。
