laravel passport 的 /oauth/token 接口仅支持 post 请求且必须通过 form_params 提交参数,不接受 get 参数;这是由路由定义(route::post)和 oauth 2.1 规范共同决定的,旨在防止 client_secret 泄露。

直接说结论:Laravel Passport 的 /oauth/token 接口本身不接受 GET 参数传参,所有必需字段(grant_type、client_id、client_secret 等)必须通过 form_params(即 POST body)提交;用 GET 传会返回 405 Method Not Allowed 或空响应,不是配置问题,是路由定义强制限定为 POST。
为什么 /oauth/token 不吃 GET 参数
Passport 内置的 AccessTokenController@issueToken 方法只处理 application/x-www-form-urlencoded 请求体,且 Laravel 路由明确绑定为 POST。即使你手动在 URL 后拼 ?client_id=123,框架也会忽略这些参数——它压根不从 $request->query() 读取认证字段。
-
/oauth/token路由注册在Passport::routes()中,底层是Route::post(),没有 GET 版本 - OAuth 2.1 规范也明确要求
token端点必须用 POST,防止 client_secret 泄露到服务器日志或代理缓存中 - 常见错误现象:URL 里带
?code=xxx却没在 body 里传form_params→ 返回400 Bad Request或空 JSON
授权码模式下如何安全传 code 和 redirect_uri
这两个参数虽出现在授权重定向的 URL 中(如 GET /callback?code=abc&state=xyz),但它们**不能直接塞进 /oauth/token 的 GET 请求里**,必须作为 form_params 的一部分提交。
-
code来自回调 URL 的 query string,需用$request->code提取后放进 POST body -
redirect_uri必须和当初申请授权时传的一模一样(包括末尾斜杠、协议、端口),否则报invalid_request - 示例(Guzzle):
$response = $http->post('http://server.app/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 3,
'client_secret' => 'your_client_secret_here',
'redirect_uri' => 'http://client.app/callback',
'code' => $request->code,
'state' => $request->state, // 如果用了 state,必须原样回传
]
]);
容易被忽略的 client_secret 位置和权限
很多人把 client_secret 错当成前端可暴露字段,或者误以为它能从环境变量里动态读取——其实它必须是数据库 oauth_clients 表里对应客户端记录的真实 secret 值,且仅限服务端使用。
- 查表确认:
SELECT id, name, secret, password_client FROM oauth_clients WHERE id = 3;—— 确保你用的是那条password_client = 0且personal_access_client = 0的授权码客户端 - 如果
storage/oauth-private.key权限不对(比如www-data用户无法读),/oauth/token会静默失败或抛500,检查命令:ls -l storage/oauth-*.key,应为-rw-r--r-- - 别在 JS 或 Vue 组件里硬编码
client_secret,哪怕只是测试——它一旦泄露,攻击者可直接换 token
最常卡住的其实是 client_secret 拿错行,或者 redirect_uri 多了个 trailing slash;这两处对不上,/oauth/token 就只会返回 {"error":"invalid_request"},连具体哪错都不告诉你。











