knowledge-base/AUTH_SETUP.md
2025-10-23 22:22:07 +05:30

245 lines
7.4 KiB
Markdown

# 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.