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

8.3 KiB
Raw Blame History

認證與授權 API

📋 概述

Drama Ling 應用的認證與授權系統支援傳統註冊登入和第三方社群登入Apple ID、Google

🔐 JWT 認證機制

Token 結構

{
  "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. 用戶註冊

POST /api/v1/auth/register
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "securePassword123",
  "username": "dramatic_learner",
  "preferredLanguage": "en",
  "nativeLanguage": "zh-TW"
}

回應範例

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 語言碼

錯誤處理

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. 用戶登入

POST /api/v1/auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "securePassword123",
  "rememberMe": true
}

回應範例

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"
}

錯誤處理

Response 401 Unauthorized
{
  "success": false,
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Email或密碼錯誤",
    "details": {
      "attemptCount": 3,
      "lockoutTime": null
    }
  }
}

3. Token 刷新

POST /api/v1/auth/refresh
Authorization: Bearer <refresh_token>

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "550e8400-e29b-41d4-a716-446655440001",
    "expiresIn": 3600,
    "tokenType": "Bearer"
  },
  "message": "Token refreshed successfully"
}

4. 用戶登出

POST /api/v1/auth/logout
Authorization: Bearer <access_token>

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "loggedOut": true,
    "tokenBlacklisted": true
  },
  "message": "Logout successful"
}

5. Apple ID 登入

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"
  }
}

回應範例

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 登入

POST /api/v1/auth/google
Content-Type: application/json

{
  "idToken": "google_id_token",
  "accessToken": "google_access_token",
  "serverAuthCode": "google_server_auth_code"
}

回應範例

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"
}

🔒 權限控制

用戶角色

enum UserRole {
  USER = "user",           // 免費用戶
  SUBSCRIBER = "subscriber", // 訂閱用戶  
  ADMIN = "admin"          // 管理員
}

權限矩陣

功能 免費用戶 訂閱用戶 管理員
基礎對話練習 3次/日 無限制 無限制
高級對話功能
詞彙複習 基礎 進階 完整
特殊任務 部分 完整 完整
數據分析 基礎 詳細 完整
管理功能

權限檢查中介軟體

// 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 第三方登入驗證失敗

🧪 測試指南

測試用例

# 正常註冊流程測試
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, 錯誤處理