SurfSense/_bmad-output/implementation-artifacts/1-0-authentication-system.md
API Test Bot f60ba3d01f update
2026-03-11 19:32:08 +07:00

8.2 KiB

Story 1.0: Hệ thống Xác thực (Authentication System)

Status: ready-for-dev

Story

Là một SurfSense user, Tôi muốn đăng nhập vào extension với tài khoản SurfSense của tôi, Để extension có thể đồng bộ settings, lịch sử chat, và truy cập backend APIs.

Acceptance Criteria

AC 1.0.1: User Login Flow

  • Given user chưa đăng nhập vào extension
  • When user click nút "Login" trong side panel header
  • Then Chrome Identity API popup mở ra với tùy chọn Google OAuth
  • And user hoàn tất quy trình OAuth
  • Then extension nhận JWT token từ backend
  • And extension chuyển hướng về side panel
  • And avatar/email của user hiển thị trong header

Error Scenario:

  • Given user đang trong quy trình OAuth
  • When OAuth thất bại (user hủy hoặc lỗi mạng)
  • Then extension hiển thị error toast "Login failed. Please try again."
  • And user vẫn ở trạng thái chưa xác thực

AC 1.0.2: JWT Token Management

  • Given backend trả về JWT token (hết hạn sau 24 giờ - theo config hiện tại)
  • When extension nhận được token
  • Then extension lưu encrypted JWT trong Plasmo Storage
  • And thời gian hết hạn của token được lưu

Auto-Refresh:

  • Given JWT token còn < 1 giờ là hết hạn
  • When extension kiểm tra token expiry (mỗi 30 phút)
  • Then extension gọi API /auth/jwt/refresh
  • And extension cập nhật token đã lưu

Logout:

  • Given user click "Logout" trong settings dropdown
  • When hành động logout được kích hoạt
  • Then extension xóa JWT khỏi Plasmo Storage
  • And user chuyển hướng về màn hình welcome/login

AC 1.0.3: Authenticated API Requests

  • Given user đã đăng nhập (JWT đã lưu)
  • When extension thực hiện API request
  • Then request bao gồm header Authorization: Bearer {JWT}
  • And backend xác thực JWT
  • And request thành công với status 200

Expired Token:

  • Given JWT token đã hết hạn
  • When extension thực hiện API request
  • Then backend trả về lỗi 401 Unauthorized
  • And extension cố gắng auto-refresh
  • And nếu refresh thành công, thử lại request ban đầu
  • And nếu refresh thất bại, chuyển hướng user đến trang login

AC 1.0.4: Offline Handling

  • Given user đã đăng nhập trước đó
  • And user mất kết nối internet
  • When extension cố gắng kết nối backend
  • Then extension hiển thị chỉ báo "Offline" trong header
  • And extension cache trạng thái auth gần nhất

Tasks / Subtasks

  • Task 1: Chrome Identity API Integration (AC: 1.0.1)

    • 1.1 Tạo lib/auth/chrome-identity.ts - wrapper cho Chrome Identity API
    • 1.2 Implement launchWebAuthFlow với backend OAuth URL
    • 1.3 Handle OAuth callback và extract JWT từ redirect URL
    • 1.4 Xử lý các error cases (user cancel, network error)
  • Task 2: JWT Token Manager (AC: 1.0.2)

    • 2.1 Tạo lib/auth/jwt-manager.ts - quản lý JWT storage
    • 2.2 Implement token encryption/decryption với Plasmo Storage
    • 2.3 Implement token expiry checking và auto-refresh logic
    • 2.4 Implement logout và clear token
  • Task 3: Authenticated API Client (AC: 1.0.3)

    • 3.1 Tạo lib/auth/api-client.ts - HTTP client với auth headers
    • 3.2 Implement request interceptor để inject Bearer token
    • 3.3 Implement 401 response handler với auto-retry
    • 3.4 Implement offline detection và caching
  • Task 4: Auth UI Components (AC: 1.0.1, 1.0.4)

    • 4.1 Tạo sidepanel/auth/LoginButton.tsx - nút đăng nhập
    • 4.2 Tạo sidepanel/auth/UserProfile.tsx - hiển thị avatar/email
    • 4.3 Tạo sidepanel/auth/AuthProvider.tsx - React context cho auth state
    • 4.4 Update sidepanel/chat/ChatHeader.tsx để integrate auth UI
  • Task 5: Integration Testing

    • 5.1 Test OAuth flow end-to-end
    • 5.2 Test token refresh mechanism
    • 5.3 Test offline mode behavior
    • 5.4 Test logout flow

Dev Notes

Backend Authentication (ALREADY EXISTS)

Backend đã có đầy đủ authentication system sử dụng fastapi-users:

Existing Endpoints:

POST /auth/jwt/login          - Email/password login
POST /auth/jwt/logout         - Logout
GET  /auth/google/authorize   - Google OAuth initiation
GET  /auth/google/callback    - Google OAuth callback
POST /auth/register           - User registration
GET  /verify-token            - Verify JWT validity
GET  /users/me                - Get current user info

JWT Configuration (từ surfsense_backend/app/users.py):

  • Secret: config.SECRET_KEY
  • Lifetime: 24 giờ (3600 * 24 seconds)
  • Transport: Bearer token
  • OAuth redirect: {NEXT_FRONTEND_URL}/auth/callback?token={token}

Extension Architecture Pattern

Plasmo Storage (đã có trong project):

import { Storage } from "@plasmohq/storage";
const storage = new Storage({ area: "local" });

Chrome Identity API:

chrome.identity.launchWebAuthFlow({
  url: `${BACKEND_URL}/auth/google/authorize`,
  interactive: true,
}, (redirectUrl) => {
  // Extract JWT from redirect URL
  const url = new URL(redirectUrl);
  const token = url.searchParams.get('token');
});

Critical Implementation Details

1. OAuth Flow cho Extension:

  • Backend hiện redirect về {NEXT_FRONTEND_URL}/auth/callback?token={token}
  • Extension cần sử dụng Chrome Identity API với custom redirect
  • Có thể cần thêm endpoint mới hoặc config cho extension redirect

2. Token Storage Security:

  • KHÔNG lưu plaintext JWT
  • Sử dụng encryption trước khi lưu vào Plasmo Storage
  • Xem xét sử dụng chrome.storage.session cho sensitive data

3. CORS Configuration: Backend đã có CORS cho localhost, cần thêm extension origin:

# surfsense_backend/app/app.py - line 74-81
allowed_origins.extend([
    "chrome-extension://*",  # Cần thêm
])

Project Structure Notes

Files cần tạo mới:

surfsense_browser_extension/
├── lib/
│   └── auth/
│       ├── chrome-identity.ts    # Chrome Identity API wrapper
│       ├── jwt-manager.ts        # JWT storage & refresh
│       └── api-client.ts         # Authenticated HTTP client
└── sidepanel/
    └── auth/
        ├── LoginButton.tsx       # Login UI component
        ├── UserProfile.tsx       # User avatar/menu
        └── AuthProvider.tsx      # Auth context provider

Files cần modify:

  • sidepanel/chat/ChatHeader.tsx - Thêm auth UI
  • sidepanel/index.tsx - Wrap với AuthProvider
  • background/index.ts - Handle auth messages (nếu cần)

Dependencies

Existing (không cần cài thêm):

  • @plasmohq/storage - Đã có
  • react, react-dom - Đã có
  • lucide-react - Đã có (cho icons)

Backend Dependencies (đã có):

  • fastapi-users - Authentication framework
  • httpx-oauth - Google OAuth client
  • python-jose - JWT handling

Security Considerations

  1. KHÔNG lưu API keys trong extension code
  2. Mã hóa JWT trước khi lưu vào storage
  3. Sử dụng HTTPS cho tất cả API calls
  4. Validate JWT signature trên backend (đã có)
  5. Implement CSRF protection cho OAuth flow

References

  • [Source: surfsense_backend/app/users.py] - JWT strategy, OAuth config
  • [Source: surfsense_backend/app/app.py#L91-160] - Auth routes registration
  • [Source: _bmad-epics/epic-1-ai-powered-crypto-assistant.md#Story-1.0] - Full requirements
  • [Source: _bmad-output/architecture-extension.md] - Extension architecture
  • [Source: _bmad-output/architecture-backend.md] - Backend auth flow

Dev Agent Record

Agent Model Used

{{agent_model_name_version}}

Completion Notes List

  • Story created: 2026-02-04
  • Backend auth system already exists and is fully functional
  • Extension needs new auth layer to integrate with existing backend
  • P0 BLOCKER - This story blocks all sync features (Settings, Chat, Capture)

Debug Log References

(To be filled during implementation)

File List

(To be filled during implementation)