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
launchWebAuthFlowvớ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)
- 1.1 Tạo
-
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
- 2.1 Tạo
-
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
- 3.1 Tạo
-
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
- 4.1 Tạo
-
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 * 24seconds) - 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.sessioncho 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 UIsidepanel/index.tsx- Wrap với AuthProviderbackground/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 frameworkhttpx-oauth- Google OAuth clientpython-jose- JWT handling
Security Considerations
- KHÔNG lưu API keys trong extension code
- Mã hóa JWT trước khi lưu vào storage
- Sử dụng HTTPS cho tất cả API calls
- Validate JWT signature trên backend (đã có)
- 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)