Skip to content

Commit 537639c

Browse files
kargnasclaude[bot]
andauthored
docs: Add comprehensive authentication documentation with critical security emphasis (#60)
- Added detailed authentication section after Basic Usage - Included quick start guide for Sanctum and custom API key auth - Provided advanced security configurations (IP whitelisting, RBAC, audit logging) - Added environment-specific configuration examples - Included testing instructions and security best practices - Emphasized authentication as ESSENTIAL for production with clear warnings - Added common authentication patterns for different use cases Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: Sangrak Choi <[email protected]>
1 parent fd0ba98 commit 537639c

File tree

1 file changed

+300
-0
lines changed

1 file changed

+300
-0
lines changed

README.md

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,306 @@ The MCP protocol also defines a "Streamable HTTP SSE" mode, but this package doe
279279

280280
## Basic Usage
281281

282+
### 🔐 Authentication (CRITICAL FOR PRODUCTION)
283+
284+
> **⚠️ SECURITY WARNING:** Authentication is **ESSENTIAL** for production deployments. Without proper authentication, your MCP server endpoints are publicly accessible, potentially exposing sensitive data and operations.
285+
286+
The Laravel MCP Server uses Laravel's middleware system for authentication, providing flexibility to implement various authentication strategies. **By default, NO authentication is enabled** - you MUST configure it for production use.
287+
288+
#### Quick Start: Securing Your MCP Server
289+
290+
##### 1. Enable Authentication in Configuration
291+
292+
Edit your `config/mcp-server.php` file to add authentication middleware:
293+
294+
```php
295+
// config/mcp-server.php
296+
297+
'middlewares' => [
298+
// PRODUCTION CONFIGURATION (Choose one or combine):
299+
'auth:sanctum', // For Laravel Sanctum (recommended)
300+
// 'auth:api', // For Laravel Passport
301+
// 'custom.mcp.auth', // For custom authentication
302+
'throttle:100,1', // Rate limiting (100 requests per minute)
303+
'cors', // CORS support if needed
304+
],
305+
```
306+
307+
##### 2. Option A: Laravel Sanctum (Recommended)
308+
309+
**Installation and Setup:**
310+
311+
```bash
312+
# Install Sanctum
313+
composer require laravel/sanctum
314+
315+
# Publish configuration
316+
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
317+
318+
# Run migrations
319+
php artisan migrate
320+
```
321+
322+
**Generate API Tokens for MCP Clients:**
323+
324+
```php
325+
// In your application code or tinker
326+
$user = User::find(1);
327+
$token = $user->createToken('MCP Client')->plainTextToken;
328+
329+
// Use this token in your MCP client configuration
330+
```
331+
332+
**Client Usage:**
333+
334+
```bash
335+
# Include the Bearer token in your requests
336+
curl -X POST http://your-server.com/mcp \
337+
-H "Authorization: Bearer YOUR_SANCTUM_TOKEN" \
338+
-H "Content-Type: application/json" \
339+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
340+
```
341+
342+
##### 3. Option B: Custom API Key Authentication
343+
344+
**Create Custom Middleware:**
345+
346+
```php
347+
// app/Http/Middleware/McpApiKeyAuth.php
348+
<?php
349+
350+
namespace App\Http\Middleware;
351+
352+
use Closure;
353+
use Illuminate\Http\Request;
354+
355+
class McpApiKeyAuth
356+
{
357+
public function handle(Request $request, Closure $next)
358+
{
359+
$apiKey = $request->header('X-MCP-API-Key');
360+
361+
// Validate against environment variable or database
362+
if ($apiKey !== config('mcp.api_key')) {
363+
return response()->json([
364+
'jsonrpc' => '2.0',
365+
'error' => [
366+
'code' => -32001,
367+
'message' => 'Unauthorized: Invalid API key'
368+
]
369+
], 401);
370+
}
371+
372+
return $next($request);
373+
}
374+
}
375+
```
376+
377+
**Register the Middleware:**
378+
379+
```php
380+
// app/Http/Kernel.php
381+
protected $routeMiddleware = [
382+
// ... other middleware
383+
'mcp.auth' => \App\Http\Middleware\McpApiKeyAuth::class,
384+
];
385+
```
386+
387+
**Configure in MCP Settings:**
388+
389+
```php
390+
// config/mcp-server.php
391+
'middlewares' => [
392+
'mcp.auth', // Your custom API key middleware
393+
'throttle:100,1', // Rate limiting
394+
],
395+
396+
// .env file
397+
MCP_API_KEY=your-secure-api-key-here
398+
```
399+
400+
#### Advanced Security Configurations
401+
402+
##### IP Whitelisting
403+
404+
Restrict access to specific IP addresses:
405+
406+
```php
407+
// app/Http/Middleware/McpIpWhitelist.php
408+
class McpIpWhitelist
409+
{
410+
public function handle(Request $request, Closure $next)
411+
{
412+
$allowedIps = config('mcp.allowed_ips', []);
413+
414+
if (!empty($allowedIps) && !in_array($request->ip(), $allowedIps)) {
415+
return response()->json([
416+
'jsonrpc' => '2.0',
417+
'error' => [
418+
'code' => -32004,
419+
'message' => 'Access denied from this IP address'
420+
]
421+
], 403);
422+
}
423+
424+
return $next($request);
425+
}
426+
}
427+
```
428+
429+
##### Role-Based Access Control (RBAC)
430+
431+
Control access to specific tools based on user roles:
432+
433+
```php
434+
// app/Http/Middleware/McpRoleAuth.php
435+
class McpRoleAuth
436+
{
437+
public function handle(Request $request, Closure $next, string $role)
438+
{
439+
$user = auth()->user();
440+
441+
if (!$user || !$user->hasRole($role)) {
442+
return response()->json([
443+
'jsonrpc' => '2.0',
444+
'error' => [
445+
'code' => -32003,
446+
'message' => 'Forbidden: Insufficient permissions'
447+
]
448+
], 403);
449+
}
450+
451+
return $next($request);
452+
}
453+
}
454+
```
455+
456+
##### Audit Logging
457+
458+
Track all MCP requests for security monitoring:
459+
460+
```php
461+
// app/Http/Middleware/McpAuditLog.php
462+
class McpAuditLog
463+
{
464+
public function handle(Request $request, Closure $next)
465+
{
466+
$response = $next($request);
467+
468+
Log::channel('mcp_audit')->info('MCP Request', [
469+
'method' => $request->method(),
470+
'path' => $request->path(),
471+
'ip' => $request->ip(),
472+
'user_id' => auth()->id(),
473+
'payload' => $request->json()->all(),
474+
'status' => $response->getStatusCode(),
475+
'timestamp' => now(),
476+
]);
477+
478+
return $response;
479+
}
480+
}
481+
```
482+
483+
#### Environment-Specific Configuration
484+
485+
Configure different authentication strategies per environment:
486+
487+
```php
488+
// config/mcp-server.php
489+
'middlewares' => array_filter([
490+
// Always apply rate limiting
491+
'throttle:' . env('MCP_RATE_LIMIT', '60') . ',1',
492+
493+
// Authentication only in non-local environments
494+
env('APP_ENV') !== 'local' ? 'auth:sanctum' : null,
495+
496+
// IP whitelisting for production
497+
env('APP_ENV') === 'production' ? 'mcp.ip.whitelist' : null,
498+
499+
// Audit logging for production
500+
env('APP_ENV') === 'production' ? 'mcp.audit' : null,
501+
502+
// CORS if needed
503+
env('MCP_CORS_ENABLED', false) ? 'cors' : null,
504+
]),
505+
```
506+
507+
#### Testing Authentication
508+
509+
Verify your authentication is working correctly:
510+
511+
```bash
512+
# Test without authentication (should fail)
513+
curl -X POST http://your-server.com/mcp \
514+
-H "Content-Type: application/json" \
515+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
516+
# Expected: 401 Unauthorized
517+
518+
# Test with valid authentication
519+
curl -X POST http://your-server.com/mcp \
520+
-H "Authorization: Bearer YOUR_TOKEN" \
521+
-H "Content-Type: application/json" \
522+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
523+
# Expected: 200 OK with tools list
524+
525+
# Test rate limiting (make multiple rapid requests)
526+
for i in {1..101}; do
527+
curl -X POST http://your-server.com/mcp \
528+
-H "Authorization: Bearer YOUR_TOKEN" \
529+
-H "Content-Type: application/json" \
530+
-d '{"jsonrpc":"2.0","id":'$i',"method":"ping"}'
531+
done
532+
# Expected: 429 Too Many Requests after limit exceeded
533+
```
534+
535+
#### Security Best Practices
536+
537+
1. **Never expose MCP endpoints without authentication in production**
538+
2. **Use HTTPS exclusively** - Never send authentication tokens over HTTP
539+
3. **Implement rate limiting** to prevent abuse
540+
4. **Rotate API keys/tokens regularly**
541+
5. **Monitor and audit** all MCP requests
542+
6. **Use environment variables** for sensitive configuration
543+
7. **Implement IP whitelisting** for additional security when possible
544+
8. **Consider OAuth2** for third-party integrations
545+
9. **Test your authentication** thoroughly before deployment
546+
10. **Document your authentication** method for your team
547+
548+
#### Common Authentication Patterns
549+
550+
##### Internal Services
551+
For microservices or internal tools:
552+
```php
553+
'middlewares' => [
554+
'mcp.api.key', // Simple API key
555+
'mcp.ip.whitelist', // Restrict to internal IPs
556+
'throttle:1000,1', // Higher rate limit for internal use
557+
]
558+
```
559+
560+
##### Public API with User Authentication
561+
For user-facing applications:
562+
```php
563+
'middlewares' => [
564+
'auth:sanctum', // User authentication
565+
'throttle:60,1', // Stricter rate limiting
566+
'cors', // CORS for web clients
567+
'mcp.audit', // Audit all requests
568+
]
569+
```
570+
571+
##### Partner Integration
572+
For third-party integrations:
573+
```php
574+
'middlewares' => [
575+
'auth:api', // OAuth2 via Passport
576+
'throttle:100,1', // Moderate rate limiting
577+
'mcp.partner.acl', // Partner-specific access control
578+
'mcp.audit', // Full audit trail
579+
]
580+
```
581+
282582
### Domain Restriction
283583

284584
You can restrict MCP server routes to specific domain(s) for better security and organization:

0 commit comments

Comments
 (0)