Skip to content

feat: add multi-tenant authentication and user isolation#1127

Open
knight0940 wants to merge 17 commits intobytedance:mainfrom
knight0940:feat/multi-tenant-auth
Open

feat: add multi-tenant authentication and user isolation#1127
knight0940 wants to merge 17 commits intobytedance:mainfrom
knight0940:feat/multi-tenant-auth

Conversation

@knight0940
Copy link
Copy Markdown

This PR implements multi-tenant authentication with user data isolation, allowing DeerFlow to support multiple users while maintaining backward compatibility for single-tenant deployments. See #1062

Features:

  • JWT-based authentication with register/login/logout endpoints
  • Per-user memory storage and isolation
  • Per-user thread directory isolation for workspace/uploads/outputs
  • Quota management system (threads, sandboxes, storage)
  • User store with JSON file backend and atomic writes
  • Sandbox state store with file-based persistence
  • Verification scripts for testing user isolation

Security:

  • PBKDF2-HMAC-SHA256 password hashing with 100k iterations
  • Constant-time password comparison to prevent timing attacks
  • Optional authentication for backward compatibility (default user)

Configuration:

  • New config sections: multi_tenant, state_store, user_quotas
  • Environment variable fallback for JWT secret
  • Default user ID for unauthenticated requests

Backward Compatibility:

  • Unauthenticated requests use user_id="default"
  • Single-tenant deployments work without changes
  • Optional authentication via get_optional_user()

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 13, 2026

CLA assistant check
All committers have signed the CLA.

@WillemJiang
Copy link
Copy Markdown
Collaborator

@knight0940 thanks for your contribution, we are planing to implement this kind feature at the same time. It's could better if we can sync up the design first. Please drop an email to willem.jiang AT gmail.com, so we can get touch with each other.

knight0940 and others added 2 commits March 16, 2026 14:52
This commit migrates the multi-tenant authentication feature from the
old backend/src/* structure to the new harness/app split architecture.

**Changes:**
- Created `packages/harness/deerflow/config/multi_tenant_config.py` for multi-tenant configuration
- Created `packages/harness/deerflow/utils/file_helpers.py` for atomic file operations
- Created `app/gateway/auth/` module with JWT authentication utilities
  - `models.py`: TokenData, User, UserRole, AuthenticationError
  - `jwt.py`: JWT token creation/validation, password hashing
  - `__init__.py`: Public API exports
- Created `app/gateway/users/` module with JSON file-backed user store
  - `store.py`: UserStore with atomic writes and thread safety
  - `__init__.py`: Public API exports
- Created `app/gateway/routers/auth.py` with authentication endpoints
  - POST /api/auth/register: User registration
  - POST /api/auth/login: User login
  - GET /api/auth/me: Get current user info
  - POST /api/auth/logout: User logout
- Updated `app/gateway/app.py` to include auth router
- Updated `packages/harness/deerflow/config/app_config.py` to load multi_tenant config

**Features:**
- JWT-based authentication with configurable secret and expiration
- Optional authentication mode for backward compatibility (default user)
- Role-based access control (USER, ADMIN)
- Password hashing with PBKDF2-HMAC-SHA256
- User management with JSON file persistence
- Configurable quota limits per role

**Configuration:**
Add to config.yaml:
```yaml
multi_tenant:
  enabled: true
  jwt_secret: "your-secret-key"  # or set DEER_FLOW_JWT_SECRET env var
  token_expire_minutes: 1440  # 24 hours
  algorithm: "HS256"
  default_user_id: "default"
```

All lint checks pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tation

This commit brings the multi-tenant authentication module to 100% RFC-001 compliance:

Core Features:
- UUID primary keys for users (User.user_id: UUID)
- 7-day JWT token expiration (10080 minutes)
- HttpOnly Cookie mechanism with secure=True for JWT storage
- LangGraph Metadata isolation for thread-level user separation
- API versioning (/api/v1/auth/*)

Security Improvements:
- Migrated from custom PBKDF2-HMAC-SHA256 to passlib[bcrypt] for password hashing
- Cookie secure flag set to True (RFC-001 compliant, requires HTTPS)
- UserContextMiddleware for automatic user_id injection from JWT cookies

New Files:
- backend/packages/harness/deerflow/agents/thread_metadata.py - LangGraph metadata utilities
- backend/app/gateway/middleware/user_context.py - User context injection middleware
- backend/tests/test_thread_metadata.py - 8 tests for metadata utilities
- backend/tests/test_user_context_middleware.py - 6 tests for middleware

Modified Files:
- backend/app/gateway/auth/models.py - UUID support for user_id
- backend/app/gateway/auth/jwt.py - passlib[bcrypt] integration, 7-day expiration
- backend/app/gateway/users/store.py - UUID support in UserStore
- backend/app/gateway/routers/auth.py - HttpOnly cookies, API versioning, UUID
- backend/app/gateway/app.py - UserContextMiddleware integration
- backend/packages/harness/deerflow/config/multi_tenant_config.py - 7-day expiration
- backend/pyproject.toml - Added passlib[bcrypt] dependency

Test Results:
- All 506 tests passing (excluding 1 unrelated checkpointer test)
- 14 new tests added and passing
- All lint checks passed

This implementation fully complies with RFC-001 specification while maintaining
the "core simplicity, open interfaces" design philosophy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@knight0940 knight0940 closed this Mar 16, 2026
@knight0940 knight0940 reopened this Mar 17, 2026
@knight0940 knight0940 marked this pull request as draft March 17, 2026 07:24
- Add thread metadata injection in ChannelManager._create_thread()
- Add thread metadata injection in /new command handler
- Fix integration test _wait_for to use async/await instead of blocking sleep
- Add memory system user isolation support
- Add MemoryMiddleware user_id extraction from thread metadata
- Add per-user memory storage paths

All 513 backend tests passing.
@knight0940 knight0940 force-pushed the feat/multi-tenant-auth branch from c412a3b to 2bd6308 Compare March 17, 2026 12:04
@knight0940 knight0940 marked this pull request as ready for review March 17, 2026 12:13
Resolved conflicts:
- memory/updater.py: Keep both _fact_content_key function and user_id parameter
- config/app_config.py: Keep both multi_tenant and tool_search fields
TitleMiddleware only had async version aafter_model(), causing failures
when DeerFlowClient.stream() calls sync agent.stream().

Added:
- _generate_title_sync() - sync version using model.invoke()
- after_model() - sync middleware hook

Resolves 9 failing live tests.
@knight0940
Copy link
Copy Markdown
Author

@knight0940 thanks for your contribution, we are planing to implement this kind feature at the same time. It's could better if we can sync up the design first. Please drop an email to willem.jiang AT gmail.com, so we can get touch with each other.

你好,我这条 PR 对应的 unit-tests-1127 有点问题,想请帮忙看下。
这条 unit-tests-1127 是我这条 PR 自己的检查,不是别的 PR 的。但现在它总是被跳过/取消,导致整体的 PR 状态一直是黄色 pending,unit-tests 这项检查始终没有真正跑完。能否帮忙帮我这条 PR 重新跑一下 unit-tests。

@WillemJiang
Copy link
Copy Markdown
Collaborator

@knight0940 There is a merge conflict need to be addressed.

Fixes ImportError when running tests that import app.gateway.routers.auth,
which uses Pydantic EmailStr type for user registration.

Resolves CI unit test failures.
Accepts main branch's improved TitleMiddleware fix which refactors
sync/async logic into _generate_title_result and _agenerate_title_result.

Also adds email-validator dependency to pyproject.toml to fix
CI unit test failures with EmailStr type.
@knight0940
Copy link
Copy Markdown
Author

@knight0940 There is a merge conflict need to be addressed.

Hi, I have just merged the main branch into my branch, and the previous commits have already passed the unit tests.

knight0940 and others added 6 commits March 23, 2026 13:46
Merges upstream main branch improvements into feat/multi-tenant-auth:

**Preserved RFC-001 Features**:
- user_id parameter support in all memory functions
- Per-user memory file paths (.deer-flow/memory/user_{user_id}/memory.json)
- Tuple-based cache keys (agent_name, user_id)

**Added Upstream Improvements** (bytedance#1215):
- _extract_text() helper for structured LLM content handling
- Logging infrastructure (replaces print statements)
- Defensive text extraction in update_memory()

This ensures memory updates work correctly with modern LLMs that
return structured content (list of content blocks) instead of plain strings.

All 603 unit tests passing.
Merges upstream main branch improvements (bytedance#1239) into feat/multi-tenant-auth:

**Preserved RFC-001 Features**:
- MultiTenantConfig field in AppConfig
- Multi-tenant config loading from config.yaml
- All multi-tenant authentication configuration options

**Added Upstream Improvements**:
- Automatic config reload when file mtime changes
- Config path tracking with _app_config_path
- Modification time detection with _get_config_mtime()
- Custom config flag _app_config_is_custom for testing
- Detailed logging when config is reloaded

This allows the application to detect and reload config.yaml changes
automatically without restart, while maintaining full multi-tenant
authentication capabilities.

All 603 unit tests passing.
Resolves merge conflicts by preserving RFC-001 multi-tenant features
while incorporating upstream improvements:

**Merged Upstream Features**:
- Token usage tracking per conversation turn (bytedance#1218)
- Config auto-reload on file mtime changes (bytedance#1239)
- Structured LLM content handling in memory updater (bytedance#1215)
- Channel-based streaming capability check (bytedance#1214)
- Japanese README (bytedance#1209)
- Thread data middleware improvements (bytedance#1237)
- Various bug fixes and enhancements

**Preserved Multi-Tenant Features**:
- Per-user memory isolation with user_id support
- Thread metadata injection for tenant isolation
- MultiTenantConfig in app configuration
- All authentication and user context features

All 663 unit tests passing.
…edance#1230)

* feat(frontend): add Cmd+K command palette and keyboard shortcuts

Wire up the existing shadcn/ui Command component as a global command
palette. Adds a useGlobalShortcuts hook for Cmd+K (palette), Cmd+Shift+N
(new chat), Cmd+, (settings), and Cmd+/ (shortcuts help overlay).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(frontend): address Copilot review feedback on command palette

- Normalize event.key with toLowerCase() for reliable Shift+key matching
- Replace dead deerflow:open-settings event with router.push navigation
- Use platform-appropriate Shift label (Shift+ on Windows/Linux, glyph on Mac)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants