mashrur950 commited on
Commit
fa14553
Β·
1 Parent(s): 79f305b

Enhance authentication documentation and multi-tenant isolation details in README and app.py

Browse files
Files changed (2) hide show
  1. README.md +117 -10
  2. app.py +49 -7
README.md CHANGED
@@ -626,23 +626,71 @@ Upload files directly to HF Space:
626
 
627
  ## πŸ”’ Authentication & Security
628
 
629
- FleetMind uses **API Key authentication** for secure multi-tenant access:
630
 
631
  ### How It Works
632
 
633
  1. **User generates API key** via web interface (`/generate-key`)
634
  2. **API key is hashed** (SHA-256) before storage - never stored in plaintext
635
- 3. **User adds key** to Claude Desktop config in `env.FLEETMIND_API_KEY`
636
- 4. **Server validates key** on each request
637
- 5. **Data is isolated** - each user only sees their own orders/drivers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
 
639
  ### Security Features
640
 
641
  - βœ… **One-Time Display** - API keys shown only once during generation
642
  - βœ… **Hashed Storage** - SHA-256 hashing, never stored in plaintext
643
- - βœ… **Multi-Tenant** - Complete data isolation per user
 
 
 
644
  - βœ… **Easy Revocation** - Keys can be revoked via CLI or web interface
645
- - βœ… **Development Mode** - `SKIP_AUTH=true` for local testing
 
646
 
647
  ### API Key Format
648
 
@@ -652,23 +700,82 @@ fm_LAISKBMKmQxoapDbLIhr_KqbVL69AS58wBtdpYfbQ10
652
 
653
  - Prefix: `fm_` (FleetMind)
654
  - 43 random characters (URL-safe base64)
655
- - Unique per user
 
656
 
657
  ### Managing Keys
658
 
659
  ```bash
660
  # Generate new key
661
- python generate_api_key.py --email user@example.com
662
 
663
- # List all keys
664
  python generate_api_key.py --list
665
 
666
- # Revoke a key
667
  python generate_api_key.py --revoke user@example.com
 
 
 
668
  ```
669
 
670
  Or use the web interface: `http://localhost:7860/generate-key`
671
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  ---
673
 
674
  ## πŸ“ Environment Variables
 
626
 
627
  ## πŸ”’ Authentication & Security
628
 
629
+ FleetMind uses **API Key authentication** for secure multi-tenant access with complete data isolation:
630
 
631
  ### How It Works
632
 
633
  1. **User generates API key** via web interface (`/generate-key`)
634
  2. **API key is hashed** (SHA-256) before storage - never stored in plaintext
635
+ 3. **User ID is generated** deterministically from email using MD5: `user_{MD5(email)[:12]}`
636
+ 4. **User adds key to URL** in Claude Desktop config: `?api_key=fm_...`
637
+ 5. **Server validates key** on each SSE connection and extracts user_id
638
+ 6. **Data is isolated** - all database queries filter by user_id
639
+ 7. **Multi-tenant enforcement** - each user only sees their own orders/drivers/assignments
640
+
641
+ ### Authentication Flow
642
+
643
+ ```
644
+ Claude Desktop Config
645
+ ↓
646
+ API Key: fm_3bGKV40B47NJ43zQ_4d3j-60a2gyoeLOVffoyyhRtBc
647
+ ↓
648
+ HTTP Request: GET /sse?api_key=fm_3bGKV40B47...
649
+ ↓
650
+ server.py: get_authenticated_user() extracts api_key from query params
651
+ ↓
652
+ api_keys.py: verify_api_key() hashes key and queries database
653
+ ↓
654
+ Returns: {'user_id': 'user_a85ddf4d664b', 'email': 'user@example.com', ...}
655
+ ↓
656
+ tools.py: Every tool extracts user_id from authenticated user
657
+ ↓
658
+ Database: Every query filters by user_id (WHERE user_id = 'user_a85ddf4d664b')
659
+ ↓
660
+ Result: Complete multi-tenant data isolation
661
+ ```
662
+
663
+ ### User ID Maintenance
664
+
665
+ **Generation** (deterministic from email):
666
+ ```python
667
+ user_id = f"user_{hashlib.md5(email.encode()).hexdigest()[:12]}"
668
+ # Example: "user@example.com" β†’ "user_a85ddf4d664b"
669
+ ```
670
+
671
+ **Storage** (api_keys table):
672
+ - `user_id`: `user_a85ddf4d664b` (deterministic ID)
673
+ - `email`: `user@example.com` (for lookup)
674
+ - `api_key_hash`: SHA-256 hash of actual API key
675
+ - `api_key_prefix`: First 12 chars for display (e.g., `fm_3bGKV40B4...`)
676
+
677
+ **Propagation** (every database operation):
678
+ - All `orders`, `drivers`, `assignments` tables have `user_id` column
679
+ - All `INSERT` queries include: `VALUES (..., user_id, ...)`
680
+ - All `SELECT` queries include: `WHERE user_id = %s`
681
+ - Composite indexes created: `idx_orders_user_id`, `idx_drivers_user_id`, etc.
682
 
683
  ### Security Features
684
 
685
  - βœ… **One-Time Display** - API keys shown only once during generation
686
  - βœ… **Hashed Storage** - SHA-256 hashing, never stored in plaintext
687
+ - βœ… **Multi-Tenant Isolation** - Complete data separation per user_id
688
+ - βœ… **Deterministic User IDs** - Same email always gets same user_id
689
+ - βœ… **Database-Level Enforcement** - All queries filter by user_id
690
+ - βœ… **Session Context** - user_id stored in ContextVar per request
691
  - βœ… **Easy Revocation** - Keys can be revoked via CLI or web interface
692
+ - βœ… **Development Mode** - `SKIP_AUTH=true` for local testing (ENV-protected)
693
+ - βœ… **Production Safeguards** - SKIP_AUTH blocked when ENV=production
694
 
695
  ### API Key Format
696
 
 
700
 
701
  - Prefix: `fm_` (FleetMind)
702
  - 43 random characters (URL-safe base64)
703
+ - Generated with `secrets.token_urlsafe(32)`
704
+ - Unique per user (one key per email)
705
 
706
  ### Managing Keys
707
 
708
  ```bash
709
  # Generate new key
710
+ python generate_api_key.py --email user@example.com --name "John Doe"
711
 
712
+ # List all keys (shows user_id, email, key preview)
713
  python generate_api_key.py --list
714
 
715
+ # Revoke a key (deactivates, doesn't delete)
716
  python generate_api_key.py --revoke user@example.com
717
+
718
+ # Verify a key (test authentication)
719
+ python generate_api_key.py --verify fm_your_api_key_here
720
  ```
721
 
722
  Or use the web interface: `http://localhost:7860/generate-key`
723
 
724
+ ### Database Tables with user_id
725
+
726
+ All core tables have `user_id` column for multi-tenant isolation:
727
+
728
+ ```sql
729
+ -- orders table
730
+ CREATE TABLE orders (
731
+ order_id VARCHAR(50) PRIMARY KEY,
732
+ user_id VARCHAR(100) NOT NULL, -- Multi-tenant isolation
733
+ customer_name VARCHAR(255),
734
+ ...
735
+ FOREIGN KEY (user_id) REFERENCES api_keys(user_id)
736
+ );
737
+ CREATE INDEX idx_orders_user_id ON orders(user_id);
738
+
739
+ -- drivers table
740
+ CREATE TABLE drivers (
741
+ driver_id VARCHAR(50) PRIMARY KEY,
742
+ user_id VARCHAR(100) NOT NULL, -- Multi-tenant isolation
743
+ name VARCHAR(255),
744
+ ...
745
+ FOREIGN KEY (user_id) REFERENCES api_keys(user_id)
746
+ );
747
+ CREATE INDEX idx_drivers_user_id ON drivers(user_id);
748
+
749
+ -- assignments table
750
+ CREATE TABLE assignments (
751
+ assignment_id VARCHAR(50) PRIMARY KEY,
752
+ user_id VARCHAR(100) NOT NULL, -- Multi-tenant isolation
753
+ order_id VARCHAR(50),
754
+ driver_id VARCHAR(50),
755
+ ...
756
+ FOREIGN KEY (user_id) REFERENCES api_keys(user_id)
757
+ );
758
+ CREATE INDEX idx_assignments_user_id ON assignments(user_id);
759
+ ```
760
+
761
+ ### Environment Configuration
762
+
763
+ ```bash
764
+ # Environment mode (controls SKIP_AUTH behavior)
765
+ ENV=development # Options: development, staging, production
766
+
767
+ # Authentication bypass (ONLY works when ENV != production)
768
+ SKIP_AUTH=false # Set to true ONLY for local testing
769
+
770
+ # Database connection (multi-tenant PostgreSQL)
771
+ DB_HOST=your-postgres-host.neon.tech
772
+ DB_NAME=fleetmind
773
+ DB_USER=your_user
774
+ DB_PASSWORD=your_password
775
+ ```
776
+
777
+ **Security Note**: `SKIP_AUTH=true` is automatically blocked when `ENV=production`, preventing accidental authentication bypass in production deployments.
778
+
779
  ---
780
 
781
  ## πŸ“ Environment Variables
app.py CHANGED
@@ -207,15 +207,35 @@ if __name__ == "__main__":
207
 
208
  <h2>⭐ Key Features</h2>
209
  <ul>
210
- <li><strong>πŸ”‘ API Key Authentication</strong> - Secure multi-tenant access with personal API keys</li>
 
211
  <li><strong>🧠 Gemini 2.0 Flash AI</strong> - Intelligent order assignment with detailed reasoning</li>
212
  <li><strong>🌦️ Weather-Aware Routing</strong> - Safety-first delivery planning with OpenWeatherMap</li>
213
  <li><strong>🚦 Real-Time Traffic</strong> - Google Routes API integration with live traffic data</li>
214
  <li><strong>πŸ“Š SLA Tracking</strong> - Automatic on-time performance monitoring</li>
215
- <li><strong>πŸ—„οΈ PostgreSQL Database</strong> - Production-grade data storage (Neon)</li>
216
  <li><strong>πŸš€ Multi-Client Support</strong> - Works with Claude Desktop, Continue, Cline, any MCP client</li>
217
  </ul>
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  <hr style="margin: 30px 0; border: none; border-top: 1px solid #e5e7eb;">
220
 
221
  <h2>πŸ“š Resources</h2>
@@ -262,10 +282,13 @@ if __name__ == "__main__":
262
 
263
  <div class="info">
264
  <strong>πŸ“‹ What you'll need:</strong><br>
265
- β€’ Your email address<br>
266
  β€’ Your name (optional)<br>
267
  <br>
268
- After generation, you'll get an API key to use with Claude Desktop.
 
 
 
269
  </div>
270
 
271
  <form method="POST">
@@ -329,9 +352,9 @@ if __name__ == "__main__":
329
  <strong>Your API key has been created successfully</strong>
330
  </div>
331
 
332
- <p><strong>Email:</strong> {result["email"]}</p>
333
- <p><strong>Name:</strong> {result["name"]}</p>
334
- <p><strong>User ID:</strong> {result["user_id"]}</p>
335
 
336
  <div class="warning">
337
  <strong>⚠️ SAVE THIS KEY NOW - IT WON'T BE SHOWN AGAIN!</strong>
@@ -341,6 +364,15 @@ if __name__ == "__main__":
341
  <code>{result["api_key"]}</code>
342
  <button onclick="copyKey()">πŸ“‹ Copy Key</button>
343
 
 
 
 
 
 
 
 
 
 
344
  <h2>πŸ“‹ Claude Desktop Setup:</h2>
345
  <p>Add this to your <code>claude_desktop_config.json</code>:</p>
346
  <pre>{{
@@ -366,6 +398,16 @@ if __name__ == "__main__":
366
  <li>Start using FleetMind tools!</li>
367
  </ol>
368
 
 
 
 
 
 
 
 
 
 
 
369
  <p style="text-align: center; margin-top: 30px;">
370
  <a href="/" style="color: #60a5fa; text-decoration: none;">← Back to Home</a>
371
  </p>
 
207
 
208
  <h2>⭐ Key Features</h2>
209
  <ul>
210
+ <li><strong>πŸ”‘ API Key Authentication</strong> - Secure multi-tenant access with personal API keys (URL-based)</li>
211
+ <li><strong>πŸ‘₯ Multi-Tenant Isolation</strong> - Complete data separation via user_id (deterministic from email)</li>
212
  <li><strong>🧠 Gemini 2.0 Flash AI</strong> - Intelligent order assignment with detailed reasoning</li>
213
  <li><strong>🌦️ Weather-Aware Routing</strong> - Safety-first delivery planning with OpenWeatherMap</li>
214
  <li><strong>🚦 Real-Time Traffic</strong> - Google Routes API integration with live traffic data</li>
215
  <li><strong>πŸ“Š SLA Tracking</strong> - Automatic on-time performance monitoring</li>
216
+ <li><strong>πŸ—„οΈ PostgreSQL Database</strong> - Production-grade data storage with user_id filtering (Neon)</li>
217
  <li><strong>πŸš€ Multi-Client Support</strong> - Works with Claude Desktop, Continue, Cline, any MCP client</li>
218
  </ul>
219
 
220
+ <h2>πŸ”’ Authentication & Security</h2>
221
+ <div class="feature">
222
+ <strong>How Authentication Works:</strong><br>
223
+ 1. Generate API key via <a href="/generate-key">/generate-key</a><br>
224
+ 2. API key hashed (SHA-256) before storage<br>
225
+ 3. User ID generated: <code>user_&#123;MD5(email)[:12]&#125;</code><br>
226
+ 4. Add key to URL: <code>?api_key=fm_...</code><br>
227
+ 5. Server validates on each SSE connection<br>
228
+ 6. All queries filter by user_id for isolation
229
+ </div>
230
+ <div class="feature">
231
+ <strong>Security Features:</strong><br>
232
+ βœ… One-Time Display (keys shown once)<br>
233
+ βœ… Hashed Storage (SHA-256, never plaintext)<br>
234
+ βœ… Database-Level Isolation (all tables have user_id)<br>
235
+ βœ… Deterministic User IDs (same email β†’ same user_id)<br>
236
+ βœ… Production Safeguards (ENV-based SKIP_AUTH protection)
237
+ </div>
238
+
239
  <hr style="margin: 30px 0; border: none; border-top: 1px solid #e5e7eb;">
240
 
241
  <h2>πŸ“š Resources</h2>
 
282
 
283
  <div class="info">
284
  <strong>πŸ“‹ What you'll need:</strong><br>
285
+ β€’ Your email address (used to generate your unique user_id)<br>
286
  β€’ Your name (optional)<br>
287
  <br>
288
+ <strong>πŸ” What you'll get:</strong><br>
289
+ β€’ API Key: <code>fm_xxxxx...</code> (show once, copy immediately!)<br>
290
+ β€’ User ID: <code>user_xxxxx</code> (deterministic from your email)<br>
291
+ β€’ All your data (orders/drivers/assignments) will be isolated by this user_id
292
  </div>
293
 
294
  <form method="POST">
 
352
  <strong>Your API key has been created successfully</strong>
353
  </div>
354
 
355
+ <p><strong>πŸ“§ Email:</strong> {result["email"]}</p>
356
+ <p><strong>πŸ‘€ Name:</strong> {result["name"]}</p>
357
+ <p><strong>πŸ†” User ID:</strong> <code>{result["user_id"]}</code></p>
358
 
359
  <div class="warning">
360
  <strong>⚠️ SAVE THIS KEY NOW - IT WON'T BE SHOWN AGAIN!</strong>
 
364
  <code>{result["api_key"]}</code>
365
  <button onclick="copyKey()">πŸ“‹ Copy Key</button>
366
 
367
+ <h2>πŸ‘₯ Multi-Tenant Isolation</h2>
368
+ <p style="background: #1e3a5f; padding: 15px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #3b82f6;">
369
+ <strong>Your user_id (<code>{result["user_id"]}</code>) ensures complete data isolation:</strong><br>
370
+ βœ… You will only see your own orders, drivers, and assignments<br>
371
+ βœ… All database operations automatically filter by your user_id<br>
372
+ βœ… Your user_id is deterministic - same email always gets same ID<br>
373
+ βœ… Even if you regenerate your API key, your user_id stays the same
374
+ </p>
375
+
376
  <h2>πŸ“‹ Claude Desktop Setup:</h2>
377
  <p>Add this to your <code>claude_desktop_config.json</code>:</p>
378
  <pre>{{
 
398
  <li>Start using FleetMind tools!</li>
399
  </ol>
400
 
401
+ <h2>πŸ” How Authentication Works:</h2>
402
+ <div style="background: #134e4a; padding: 15px; border-radius: 6px; margin: 10px 0; border-left: 4px solid #10b981;">
403
+ <strong>Authentication Flow:</strong><br><br>
404
+ 1️⃣ <strong>Connection:</strong> Claude Desktop connects to SSE endpoint with your API key in URL<br>
405
+ 2️⃣ <strong>Validation:</strong> Server hashes your key (SHA-256) and looks it up in database<br>
406
+ 3️⃣ <strong>User Extraction:</strong> Server retrieves your user_id: <code>{result["user_id"]}</code><br>
407
+ 4️⃣ <strong>Data Isolation:</strong> All tool calls automatically filter by your user_id<br>
408
+ 5️⃣ <strong>Security:</strong> You can only access data associated with your user_id<br>
409
+ </div>
410
+
411
  <p style="text-align: center; margin-top: 30px;">
412
  <a href="/" style="color: #60a5fa; text-decoration: none;">← Back to Home</a>
413
  </p>