Laravel MCP 配备 Passport OAuth 的设置指南
本指南详细记录了在使用Laravel Passport的Laravel MCP(模型上下文协议)服务器上实施OAuth认证的完整设置过程。
✅ 工作设置(或“运行环境”)
此项目已全面配置并经过测试,使用了:
- 支持PKCE的OAuth 2.0认证
- 用户使用的UUID主键
- 基于会话的网页认证
- 受保护的和公开的MCP端点
- MCP Inspector 集成
快速入门
如果这已经设置好了,只需运行:
# Start the server
php artisan serve
# In another terminal, test with MCP Inspector
php artisan mcp:inspector mcp/adminOAuth 凭据:
- 在你的数据库中查找客户端ID和密钥
oauth_clients桌子 - 测试用户:
test@example.com/password
先决条件
- Laravel 11.x
- PHP 8.1及以上版本
- MySQL 8.0及以上版本
- Composer(注:Composer在编程领域通常指一个依赖管理工具,用于PHP等语言的项目中,此处直接保留原词,不作具体翻译)
步骤1:安装Laravel Passport
php artisan install:api --passport这个命令将:
- 安装 Laravel Passport 包
- 发布并运行Passport迁移
- 为安全访问令牌生成加密密钥
步骤2:为UUID配置用户模型
更新 app/Models/User.php:
[
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport', // Changed from 'token' to 'passport'
'provider' => 'users',
],
],步骤4:修复UUID的护照迁移问题
关键的;严重的如果使用UUID,请更新Passport迁移以使用 foreignUuid 而不是 foreignId:
编辑这些迁移文件:
database/migrations/*_create_oauth_auth_codes_table.phpdatabase/migrations/*_create_oauth_access_tokens_table.phpdatabase/migrations/*_create_oauth_device_codes_table.php
变化:
$table->foreignId('user_id')->index();收件人:
$table->foreignUuid('user_id')->index();同时更新 database/migrations/*_create_users_table.php 会话表:
$table->foreignUuid('user_id')->nullable()->index();然后运行迁移:
php artisan migrate:fresh步骤5:配置CORS
跨域资源共享(CORS)对于OAuth流程至关重要,尤其是当MCP检查器或AI代理运行在不同的源时。
更新 config/cors.php:
['api/*', 'mcp/*', 'oauth/*', '.well-known/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'], // For production, specify exact origins
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true, // Required for OAuth with cookies
];CORS 配置详解
- 路径包含
oauth/*对于OAuth端点以及.well-known/*用于OAuth发现 - 允许的来源(或:允许的起源)设置为
['*']用于开发。在生产环境中,请指定确切的来源,如['https://your-domain.com'] - 支持凭据必须是
true在跨域请求中允许cookies和认证头信息 - 允许的方法:
['*']允许所有HTTP方法(GET、POST、OPTIONS等) - 允许的头部(信息):
['*']允许所有头部信息,包括Authorization以及自定义头部
生产环境CORS配置
对于生产环境,请收紧CORS设置:
'allowed_origins' => [
'https://your-production-domain.com',
'https://mcp-inspector.example.com',
],
'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
'supports_credentials' => true,步骤5:配置护照授权视图
更新 app/Providers/AppServiceProvider.php:
use Laravel\Passport\Passport;
public function boot(): void
{
Passport::authorizationView('mcp.authorize');
}步骤6:发布MCP授权视图
php artisan vendor:publish --tag=mcp-views这产生了 resources/views/mcp/authorize.blade.php。
步骤7:修复授权视图CSS加载问题
编辑 resources/views/mcp/authorize.blade.php 并替换为 @vite 使用内联样式指令以避免加载问题:
body { font-family: sans-serif; margin: 0; padding: 0; }
.bg-background { background: #f5f5f5; }
.text-foreground { color: #333; }
.bg-card { background: white; }
.text-card-foreground { color: #333; }
.border { border: 1px solid #e5e7eb; }
.rounded-lg { border-radius: 0.5rem; }
.shadow-sm { box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); }
.text-primary { color: #4f46e5; }
.bg-primary { background: #4f46e5; }
.text-primary-foreground { color: white; }
.bg-muted\/50 { background: rgba(243, 244, 246, 0.5); }
.text-muted-foreground { color: #6b7280; }
button:hover { opacity: 0.9; }
步骤8:修复授权视图状态参数
编辑 resources/views/mcp/authorize.blade.php 并更新隐藏状态输入:
改变:
收件人:
state ?? '' }}">这适用于批准和拒绝两种表单。
步骤9:配置MCP OAuth路由
更新 routes/ai.php:
middleware('auth:api');步骤10:设置网页认证
在授权OAuth客户端之前,您需要一个网页认证系统供用户登录。
选项A:简单登录(用于测试)
创建 routes/auth.php:
group(function () {
Route::get('login', [AuthenticatedSessionController::class, 'create'])->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
});
Route::middleware('auth')->group(function () {
Route::get('logout', [AuthenticatedSessionController::class, 'destroy'])->name('logout');
});创造 app/Http/Controllers/Auth/AuthenticatedSessionController.php:
authenticate();
$request->session()->regenerate();
return redirect()->intended(route('dashboard'));
}
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}创建 app/Http/Requests/Auth/LoginRequest.php:
['required', 'string', 'email'],
'password' => ['required', 'string'],
];
}
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
public function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
public function throttleKey(): string
{
return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip());
}
}创建 resources/views/auth/login.blade.php:
Login - {{ config('app.name') }}
MCP OAuth Login
Login to authorize the application
@if($errors->any())
{{ $errors->first() }}
@endif
@csrf
Email
Password
Login
选项B:使用Laravel Breeze(推荐用于生产环境)
composer require laravel/breeze --dev
php artisan breeze:install blade
php artisan migrate
npm install && npm run build步骤10:更新网页路由
更新 routes/web.php:
group(function () {
Route::get('/dashboard', function () {
return 'Dashboard - You are logged in as ' . auth()->user()->email;
})->name('dashboard');
});
require __DIR__.'/auth.php';注没有从...重定向 /authorize 到;向;朝;对于;为了 /oauth/authorize 是需要的。该 Mcp::oauthRoutes('oauth') 调用时会自动注册Passport路由于 /oauth/authorize。
步骤11:创建OAuth客户端
php artisan passport:client当被提示时:
- 输入客户端名称(例如,“MCP 管理员检查员”)
- 将重定向URI留空(按回车键)
保存生成的客户端ID和客户端密钥。
步骤12:更新客户端重定向URI
重定向URI需要存储为JSON数组。请手动更新它:
mysql -u root your_database_nameUPDATE oauth_clients
SET redirect_uris = '["http://localhost:6274/oauth/callback"]'
WHERE id = 'your-client-id';或者使用tinker:
php artisan tinker$client = \Laravel\Passport\Client::find('your-client-id');
$client->redirect = ['http://localhost:6274/oauth/callback'];
$client->save();步骤13:创建测试用户
php artisan tinker\App\Models\User::create([
'name' => 'Test User',
'email' => 'test@example.com',
'password' => bcrypt('password')
]);步骤14:测试OAuth流程
- 启动MCP检查器:
php artisan mcp:inspector mcp/admin- 在检查员仪表盘中:
- 请输入您的客户端ID - 输入您的客户端密钥 - 点击“连接”
- 浏览器将打开到授权页面:
- 使用您的测试用户凭据登录 - 点击“授权” - 浏览器重定向回检查器 - 检查员现在可以访问受保护的MCP服务器
OAuth流程图
┌─────────────┐ ┌──────────────┐
│ │ 1. Request /mcp/admin │ │
│ MCP │───────────────────────────────────>│ Laravel │
│ Inspector │ │ MCP App │
│ │ 2. 401 Unauthenticated │ │
│ │
│ │
│ 4. Not logged in → redirect to /login │
│
│ │
│ 6. Login successful → redirect to /oauth/authorize
│
│ │
│ 9. Redirect with authorization code │
│
│ │
│ 11. Return access token │
│
│ │
│ 13. Return MCP server response │
│state ?? '' }}">问题:UUID 兼容性错误 / “无效的用户ID”
解决方案:
- 关键的;严重的;危急的所有引用(的外键)
users.id必须使用foreignUuid()如果用户表使用UUIDs - 更新这些迁移:
- *_create_oauth_auth_codes_table.php - *_create_oauth_access_tokens_table.php - *_create_oauth_device_codes_table.php - *_create_users_table.php (会话表) - *_create_transactions_table.php (如果存在)
- 添加
HasUuids“trait to User model” 可以翻译为“应用于用户模型的特性”或“用户模型的特性/特质”。这里,“trait”指的是某个特定的特征或属性,“User model”指的是用户模型。根据上下文,具体翻译可能略有不同,但基本意思是指将某个特性或属性应用到或描述用户模型 - 跑
php artisan migrate:fresh
问题:授权时出现“无法获取”错误
解决方案:
- 移除
@vite来自授权视图的指令 - 使用内联CSS代替
- 如有需要,请在授权视图中禁用JavaScript
问题:浏览器控制台中的CORS错误
解决方案:
- 验证
config/cors.php包括oauth/*在路径中 - 确保
supports_credentials被设定为true - 检查一下
allowed_origins包括请求的来源 - 清除配置缓存:
php artisan config:clear
问题:预检OPTIONS请求失败
解决方案:
- 确保CORS中间件已注册在
bootstrap/app.php - 验证
allowed_methods包括OPTIONS - 检查Web服务器(nginx/Apache)是否阻止了OPTIONS请求
安全考虑事项
- 永远不要提交OAuth密钥添加到
.gitignore:
storage/oauth-*.key- 在生产环境中使用HTTPS更新
.env:
APP_URL=https://your-domain.com- 在生产环境中限制CORS来源更新
config/cors.php:
'allowed_origins' => ['https://your-domain.com'],- 定期更换密钥定期生成新的OAuth客户端
- 实现作用域为不同的访问级别定义特定权限
- 监控OAuth使用情况记录授权尝试和令牌使用情况
- 限制OAuth端点的速率防止暴力破解攻击
额外资源
摘要
现在,您已经拥有了一个功能齐全的Laravel MCP服务器,配置了OAuth认证和CORS:
- ✅ 公共MCP服务器位于
/mcp/warrior(无需认证) - ✅ 已保护MCP服务器于
/mcp/admin(需要OAuth) - ✅ 带有用户登录的OAuth授权流程
- ✅ 已为跨域请求配置了CORS(跨域资源共享)
- ✅ 基于令牌的安全API访问
现在,AI代理可以从任何来源使用标准的OAuth 2.0流程对您的受保护MCP服务器进行身份验证和访问。
