我在Passport::tokensCan
文件的启动方法中使用AuthServiceProvider.php
方法定义了API的作用域:
Passport::routes();
Passport::tokensCan([
'view-posts' => 'View posts',
'create-posts' => 'Create posts'
]);
在$routeMiddleware
文件的app/Http/Kernel.php
属性中添加了以下中间件:
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中的任何内容吗?
答案 0 :(得分:1)
您只需要覆盖MissingScopeException异常以返回所需的任何消息,并仍然将中间件作用域包含在路由文件中
渲染功能中处理程序文件中的Exception文件夹中的
if ($exception instanceof MissingScopeException && $request->wantsJson()){
return response()->json([
'error' => 'Unauthenticated',
], 403);
}
答案 1 :(得分:0)
您请求了view-posts
范围,但是尝试创建一个需要create-posts
范围的帖子。那是问题。
答案 2 :(得分:-1)
创建access_token时,添加范围:create-posts
$request->user()->token()->create([
'access_token' => $response->access_token
], ['create-posts']);
答案 3 :(得分:-1)
我通过添加中间件并验证范围来解决此问题,而不是在路由中使用“ scopes:some_scope”。这是我解决的方法。
创建一个中间件并在这样的中间件中验证作用域。
public function handle($request, Closure $next){
if (!$request->user()->tokenCan('user')) {
return response()->json([
'message' => "Unauthenticated",
]);
}
return $next($request);
}
您可以根据需要返回错误消息。
return response()->json([
'message' => "Unauthenticated",
]);
使用中间件。我一直在寻找答案,这是我能想到的最佳解决方案,该解决方案仍在边界内,工作量不大。如果您确实找到了更好的方法,请也与我分享。我也想知道。