# Authentication Setup - Mem0 Memory Server ## โœ… Implementation Complete A simple but effective API key-based authentication layer has been added to ensure users can only access their own memories. ## ๐Ÿ” How It Works ### 1. **API Key to User Mapping** API keys are mapped to user IDs in the `.env` file: ```bash API_KEYS='{"sk-alice-test-key-12345": "alice", "sk-bob-test-key-67890": "bob", "sk-carol-test-key-abcdef": "carol"}' ``` ### 2. **Authentication Flow** 1. Client sends request with `X-API-Key` header 2. Backend validates API key against configured mapping 3. Backend extracts authenticated user_id 4. Backend verifies user can only access their own data 5. Request proceeds or 401/403 error returned ### 3. **Protected Endpoints** All memory-related endpoints now require authentication: | Endpoint | Method | Auth Required | User Isolation | |----------|--------|---------------|----------------| | `/chat` | POST | โœ… | โœ… User can only chat as themselves | | `/memories` | POST | โœ… | โœ… User can only add to own memories | | `/memories/search` | POST | โœ… | โœ… User can only search own memories | | `/memories/{user_id}` | GET | โœ… | โœ… User can only view own memories | | `/memories` | PUT | โœ… | โœ… User can only update own memories | | `/memories/{memory_id}` | DELETE | โœ… | โœ… User can only delete own memories | | `/memories/user/{user_id}` | DELETE | โœ… | โœ… User can only delete own memories | | `/graph/relationships/{user_id}` | GET | โœ… | โœ… User can only view own relationships | | `/stats/{user_id}` | GET | โœ… | โœ… User can only view own stats | | `/health` | GET | โŒ | N/A (Public) | | `/stats` | GET | โŒ | N/A (Global stats) | | `/models` | GET | โŒ | N/A (Public) | ## ๐Ÿ“ Configuration ### Environment Setup **1. Update `.env` file:** ```bash # Add API key mapping API_KEYS='{"api_key_1": "user1", "api_key_2": "user2"}' ``` **2. Generate Secure API Keys (Production):** ```bash # Generate a random 32-character API key openssl rand -hex 32 # Example output: sk-a1b2c3d4e5f6... ``` **3. Restart Services:** ```bash docker-compose down docker-compose up -d ``` ## ๐Ÿงช Testing Authentication ### Test 1: No API Key (Should Fail - 403) ```bash curl -X POST "http://localhost:8000/memories" \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"Test"}],"user_id":"alice"}' # Response: {"detail":"Not authenticated"} ``` ### Test 2: Invalid API Key (Should Fail - 401) ```bash curl -X POST "http://localhost:8000/memories" \ -H "Content-Type: application/json" \ -H "X-API-Key: invalid-key" \ -d '{"messages":[{"role":"user","content":"Test"}],"user_id":"alice"}' # Response: {"detail":"Invalid API key"} ``` ### Test 3: Valid API Key (Should Succeed - 200) ```bash curl -X POST "http://localhost:8000/memories" \ -H "Content-Type: application/json" \ -H "X-API-Key: sk-alice-test-key-12345" \ -d '{"messages":[{"role":"user","content":"My name is Alice"}],"user_id":"alice"}' # Response: {"added_memories":[...], "message":"Memories added successfully"} ``` ### Test 4: Cross-User Access (Should Fail - 403) ```bash # Alice trying to access Bob's data curl -X POST "http://localhost:8000/memories" \ -H "Content-Type: application/json" \ -H "X-API-Key: sk-alice-test-key-12345" \ -d '{"messages":[{"role":"user","content":"Test"}],"user_id":"bob"}' # Response: {"detail":"Access denied: You can only add memories for yourself (authenticated as 'alice')"} ``` ### Test 5: Authenticated Chat ```bash curl -X POST "http://localhost:8000/chat" \ -H "Content-Type: application/json" \ -H "X-API-Key: sk-alice-test-key-12345" \ -d '{"message":"What do you know about me?","user_id":"alice"}' # Response: {"response":"Based on your memories...", "memories_used":5, ...} ``` ### Test 6: Authenticated Search ```bash curl -X POST "http://localhost:8000/memories/search" \ -H "Content-Type: application/json" \ -H "X-API-Key: sk-bob-test-key-67890" \ -d '{"query":"tennis","user_id":"bob"}' # Response: {"memories":[...], "total_count":4} ``` ## ๐Ÿ”ง Implementation Details ### Files Modified/Created: 1. **`backend/auth.py`** (NEW) - `AuthService` class for API key validation - `get_current_user()` FastAPI dependency - `verify_user_access()` for cross-user protection 2. **`backend/config.py`** (UPDATED) - Added `api_keys` field using proper Pydantic V2 syntax - Added `api_key_mapping` property to parse JSON - Uses `validation_alias` with `AliasChoices` for env var mapping 3. **`backend/main.py`** (UPDATED) - All protected endpoints now use `authenticated_user = Depends(get_current_user)` - Added user isolation checks in each endpoint 4. **`docker-compose.yml`** (UPDATED) - Added `API_KEYS` environment variable mapping 5. **`.env`** (UPDATED) - Added `API_KEYS` configuration 6. **`.env.example`** (UPDATED) - Added `API_KEYS` template with security notes ## ๐ŸŽฏ Security Features Implemented โœ… **API Key Authentication**: Every protected request requires valid API key โœ… **User Isolation**: Users can only access their own data โœ… **Cross-User Protection**: Prevents user A from accessing user B's memories โœ… **Structured Logging**: All auth events logged with correlation IDs โœ… **Environment-Based Config**: API keys stored in `.env` (not hardcoded) โœ… **Clear Error Messages**: Informative 401/403 responses ## ๐Ÿ”’ Production Recommendations ### Current Setup (โœ… Completed) - โœ… API key authentication - โœ… User isolation - โœ… Environment-based configuration - โœ… Cross-user access protection ### Future Enhancements (Optional) - [ ] Move API keys to secrets manager (AWS Secrets Manager, HashiCorp Vault) - [ ] Add API key rotation mechanism - [ ] Add rate limiting per API key - [ ] Add API key expiration - [ ] Add audit logging for security events - [ ] Add API key scopes/permissions - [ ] Add HTTPS enforcement - [ ] Add request signing for extra security ## ๐Ÿ“Š Test Results All authentication tests **PASSED** โœ… | Test | Result | HTTP Status | |------|--------|-------------| | No API key | โœ… Blocked | 403 | | Invalid API key | โœ… Blocked | 401 | | Valid API key | โœ… Allowed | 200 | | Cross-user access | โœ… Blocked | 403 | | Authenticated chat | โœ… Works | 200 | | Authenticated search | โœ… Works | 200 | | Stats isolation | โœ… Blocked | 403 | ## ๐Ÿ’ก Usage Example ```python import requests # Configure API key API_KEY = "sk-alice-test-key-12345" BASE_URL = "http://localhost:8000" headers = { "Content-Type": "application/json", "X-API-Key": API_KEY } # Add memory response = requests.post( f"{BASE_URL}/memories", headers=headers, json={ "messages": [{"role": "user", "content": "I love Python programming"}], "user_id": "alice" } ) print(response.json()) # {"added_memories": [...], "message": "Memories added successfully"} # Chat with memory response = requests.post( f"{BASE_URL}/chat", headers=headers, json={ "message": "What do I love?", "user_id": "alice" } ) print(response.json()["response"]) # "Based on your memories, you love Python programming" ``` ## ๐Ÿš€ Ready for Production The authentication layer is now **production-ready** for basic deployment with: - โœ… Simple API key authentication - โœ… User data isolation - โœ… Proper error handling - โœ… Environment-based configuration - โœ… Comprehensive testing For enterprise deployment, consider implementing the optional enhancements listed above.