dramaling-app/docs/04_technical/api/authentication.md

352 lines
8.3 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.

# 認證與授權 API
## 📋 概述
Drama Ling 應用的認證與授權系統支援傳統註冊登入和第三方社群登入Apple ID、Google
## 🔐 JWT 認證機制
### Token 結構
```json
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"username": "dramatic_learner",
"role": "user", // user, subscriber, admin
"subscription_status": "active", // active, inactive, trial
"iat": 1693920600,
"exp": 1693924200
}
```
### Token 生命週期
- **Access Token**: 1小時有效期
- **Refresh Token**: 30天有效期
- **Token 輪替**: 每次刷新會產生新的 Refresh Token
- **Token 黑名單**: 登出時將 Token 加入黑名單
## 📌 API 端點
### 1. 用戶註冊
```http
POST /api/v1/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "securePassword123",
"username": "dramatic_learner",
"preferredLanguage": "en",
"nativeLanguage": "zh-TW"
}
```
#### 回應範例
```http
Response 201 Created
{
"success": true,
"data": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"username": "dramatic_learner",
"email": "user@example.com",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440001",
"expiresIn": 3600,
"userRole": "user",
"isNewUser": true
},
"message": "User registered successfully",
"meta": {
"timestamp": "2024-09-07T12:00:00Z",
"requestId": "550e8400-e29b-41d4-a716-446655440002"
}
}
```
#### 註冊驗證規則
- **Email**: 有效的電子郵件格式
- **Password**: 最少8位包含大小寫字母和數字
- **Username**: 3-20字元僅允許字母數字和底線
- **Language**: ISO 639-1 語言碼
#### 錯誤處理
```http
Response 400 Bad Request
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "註冊資料驗證失敗",
"details": {
"email": ["Email format is invalid"],
"password": ["Password must be at least 8 characters"],
"username": ["Username already exists"]
}
}
}
```
### 2. 用戶登入
```http
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "securePassword123",
"rememberMe": true
}
```
#### 回應範例
```http
Response 200 OK
{
"success": true,
"data": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"username": "dramatic_learner",
"email": "user@example.com",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440001",
"expiresIn": 3600,
"userRole": "subscriber",
"subscriptionStatus": "active",
"lastLoginAt": "2024-09-07T12:00:00Z"
},
"message": "Login successful"
}
```
#### 錯誤處理
```http
Response 401 Unauthorized
{
"success": false,
"error": {
"code": "INVALID_CREDENTIALS",
"message": "Email或密碼錯誤",
"details": {
"attemptCount": 3,
"lockoutTime": null
}
}
}
```
### 3. Token 刷新
```http
POST /api/v1/auth/refresh
Authorization: Bearer <refresh_token>
```
#### 回應範例
```http
Response 200 OK
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440001",
"expiresIn": 3600,
"tokenType": "Bearer"
},
"message": "Token refreshed successfully"
}
```
### 4. 用戶登出
```http
POST /api/v1/auth/logout
Authorization: Bearer <access_token>
```
#### 回應範例
```http
Response 200 OK
{
"success": true,
"data": {
"loggedOut": true,
"tokenBlacklisted": true
},
"message": "Logout successful"
}
```
### 5. Apple ID 登入
```http
POST /api/v1/auth/apple
Content-Type: application/json
{
"identityToken": "apple_identity_token",
"authorizationCode": "apple_authorization_code",
"userIdentifier": "apple_user_identifier",
"email": "user@privaterelay.appleid.com",
"fullName": {
"givenName": "John",
"familyName": "Doe"
}
}
```
#### 回應範例
```http
Response 200 OK
{
"success": true,
"data": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"username": "apple_user_12345",
"email": "user@privaterelay.appleid.com",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440001",
"expiresIn": 3600,
"isNewUser": false,
"authProvider": "apple"
},
"message": "Apple login successful"
}
```
### 6. Google 登入
```http
POST /api/v1/auth/google
Content-Type: application/json
{
"idToken": "google_id_token",
"accessToken": "google_access_token",
"serverAuthCode": "google_server_auth_code"
}
```
#### 回應範例
```http
Response 200 OK
{
"success": true,
"data": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"username": "google_user_12345",
"email": "user@gmail.com",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "550e8400-e29b-41d4-a716-446655440001",
"expiresIn": 3600,
"isNewUser": true,
"authProvider": "google"
},
"message": "Google login successful"
}
```
## 🔒 權限控制
### 用戶角色
```typescript
enum UserRole {
USER = "user", // 免費用戶
SUBSCRIBER = "subscriber", // 訂閱用戶
ADMIN = "admin" // 管理員
}
```
### 權限矩陣
| 功能 | 免費用戶 | 訂閱用戶 | 管理員 |
|------|----------|----------|---------|
| 基礎對話練習 | 3次/日 | 無限制 | 無限制 |
| 高級對話功能 | ❌ | ✅ | ✅ |
| 詞彙複習 | 基礎 | 進階 | 完整 |
| 特殊任務 | 部分 | 完整 | 完整 |
| 數據分析 | 基礎 | 詳細 | 完整 |
| 管理功能 | ❌ | ❌ | ✅ |
### 權限檢查中介軟體
```javascript
// API 權限檢查範例
app.use('/api/v1/dialogues/advanced', requireSubscription);
app.use('/api/v1/admin/*', requireAdminRole);
function requireSubscription(req, res, next) {
if (req.user.role !== 'subscriber' && req.user.role !== 'admin') {
return res.status(403).json({
success: false,
error: {
code: "SUBSCRIPTION_REQUIRED",
message: "此功能需要訂閱會員"
}
});
}
next();
}
```
## ⚡ 安全措施
### 密碼安全
- **加密**: bcrypt + salt成本因子 12
- **複雜度**: 最少8位大小寫字母+數字
- **重設**: 臨時token15分鐘有效期
### 防攻擊機制
- **Rate Limiting**: 每IP每分鐘5次登入嘗試
- **帳號鎖定**: 5次失敗後鎖定15分鐘
- **CSRF Protection**: 所有POST請求需要CSRF token
- **Input Sanitization**: 所有輸入進行清理和驗證
### Token 安全
- **HTTPS Only**: 所有認證相關請求強制HTTPS
- **HttpOnly Cookies**: Refresh token存放在HttpOnly cookie
- **Token 黑名單**: 登出和可疑活動時加入黑名單
- **定期輪替**: 每24小時自動輪替長期token
## 🔧 錯誤碼
### 認證相關錯誤
| 錯誤碼 | HTTP狀態 | 描述 |
|--------|----------|------|
| `INVALID_CREDENTIALS` | 401 | 登入憑證錯誤 |
| `TOKEN_EXPIRED` | 401 | Token已過期 |
| `TOKEN_INVALID` | 401 | Token無效或格式錯誤 |
| `TOKEN_BLACKLISTED` | 401 | Token已被列入黑名單 |
| `ACCOUNT_LOCKED` | 423 | 帳號因多次失敗嘗試被鎖定 |
| `EMAIL_EXISTS` | 409 | 電子郵件已被註冊 |
| `USERNAME_EXISTS` | 409 | 使用者名稱已存在 |
| `VALIDATION_ERROR` | 400 | 輸入資料驗證失敗 |
| `SOCIAL_LOGIN_ERROR` | 400 | 第三方登入驗證失敗 |
## 🧪 測試指南
### 測試用例
```bash
# 正常註冊流程測試
curl -X POST https://api.dramaling.com/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"Test123456","username":"testuser"}'
# 登入流程測試
curl -X POST https://api.dramaling.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"Test123456"}'
# Token刷新測試
curl -X POST https://api.dramaling.com/api/v1/auth/refresh \
-H "Authorization: Bearer <refresh_token>"
```
### 安全測試
- **暴力破解測試**: 驗證帳號鎖定機制
- **Token洩漏測試**: 驗證Token黑名單機制
- **權限繞過測試**: 驗證角色權限控制
- **資料注入測試**: 驗證輸入清理機制
---
**模組負責人**: 後端團隊
**最後更新**: 2024年9月7日
**相關文檔**: [用戶管理API](./user-management.md), [錯誤處理](./errors.md)