Laravel Passport 无效范围提供了异常
Posted
技术标签:
【中文标题】Laravel Passport 无效范围提供了异常【英文标题】:Laravel Passport invalid scope(s) provided exception 【发布时间】:2020-03-08 09:23:23 【问题描述】: Laravel Passport 8.0.0 版 Laravel 版本:6.2我在AuthServiceProvider.php
文件的引导方法中使用Passport::tokensCan
方法定义了我的API 的范围:
Passport::routes();
Passport::tokensCan([
'view-posts' => 'View posts',
'create-posts' => 'Create posts'
]);
在app/Http/Kernel.php
文件的$routeMiddleware
属性中添加了以下中间件:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
/*
. . .
*/
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
];
然后,我在routes/api.php
中保护了一个API 路由:
Route::post('/posts', [
'uses' => 'PostController@store',
'middleware' => ['auth:api', 'scope:create-posts']
]);
在客户端应用中,我的授权路线是 (routes/web.php
):
Route::middleware(['auth'])->group(function ()
Route::get('/auth/blogger', 'BloggerAuthController@redirect');
Route::get('/auth/blogger/callback', 'BloggerAuthController@callback');
);
而BloggerAuthController
控制器是这样的:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp\Client as Guzzle;
class BloggerAuthController extends Controller
protected $client;
public function __construct(Guzzle $client)
$this->client = $client;
public function redirect()
$query = http_build_query([
'client_id' => '3',
'redirect_uri' => 'http://localhost:8001/auth/blogger/callback',
'response_type' => 'code',
'scope' => 'view-posts'
]);
return redirect('http://localhost:8000/oauth/authorize?' . $query);
public function callback(Request $request)
$response = $this->client->post('http://localhost:8000/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => '3',
'client_secret' => 'gG5HcVn1JlGhzO0RfgTfWuqP8IVro1Qhu9g2q0Dq',
'redirect_uri' => 'http://localhost:8001/auth/blogger/callback',
'code' => $request->code
]
]);
$response = json_decode($response->getBody());
$request->user()->token()->delete();
$request->user()->token()->create([
'access_token' => $response->access_token
]);
return redirect('/home');
当我 (POST
) 从我的客户端应用程序向 /api/posts
请求时,
我得到一个例外:
"message": "Invalid scope(s) provided.",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException",
"file": "C:\\Users\\nbayramberdiyev\\Desktop\\fresh\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Exceptions\\Handler.php",
"line": 206,
/*
. . .
*/
但预期的结果是:
"message": "Unauthenticated."
状态为 401。
为什么会这样?我错过了docs 中的任何内容吗?
【问题讨论】:
你找到解决办法了吗? 【参考方案1】:你只需要覆盖 MissingScopeException 异常来返回你想要的任何消息,并且仍然在你的路由文件中作用域中间件
在渲染函数的Handler文件中的Exception文件夹中
if ($exception instanceof MissingScopeException && $request->wantsJson())
return response()->json([
'error' => 'Unauthenticated',
], 403);
【讨论】:
【参考方案2】:您请求view-posts
范围,但随后尝试创建需要create-posts
范围的帖子。这就是问题所在。
【讨论】:
是的,完全正确。但在我的情况下,它应该返回带有消息Unauthenticated.
的 401 响应,而不是抛出异常。【参考方案3】:
创建access_token时,添加范围:create-posts
$request->user()->token()->create([
'access_token' => $response->access_token
], ['create-posts']);
【讨论】:
【参考方案4】:我通过添加中间件和验证范围来解决这个问题,而不是在路由中使用 'scopes:some_scope'。这是我的解决方法。
创建一个中间件并在这样的中间件中验证范围。
public function handle($request, Closure $next)
if (!$request->user()->tokenCan('user'))
return response()->json([
'message' => "Unauthenticated",
]);
return $next($request);
request->user()->tokenCan('user')
验证范围。
你可以返回任何你想要的错误信息。
return response()->json([
'message' => "Unauthenticated",
]);
使用中间件。我一直在寻找那个答案,这是我能想到的最好的解决方案,它仍然处于边界并且没有太多的工作。如果您确实解决了更好的方法,请也分享给我。我也想知道。
【讨论】:
以上是关于Laravel Passport 无效范围提供了异常的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Laravel Passport (5.3) 记录身份验证尝试
Laravel 5.1 oAuth 2 服务器“无效范围”错误
身份验证用户提供程序 [passport] 未使用 laravel 护照定义
laravel Passport - 创建 REST API 用户认证以及Dingo/Api v2.0+Passport实现api认证