Недопустимая область действия паспорта Laravel при условии исключения

  • Laravel Passport версии 8.0.0
  • Версия Laravel: 6.2

Я определил области своего API, используя метод Passport::tokensCan в методе загрузки файла AuthServiceProvider.php:

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,
];

Затем я защитил маршрут API в routes/api.php:

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.

Почему это происходит? Пропустил ли я что-нибудь в документах?


person N'Bayramberdiyev    schedule 12.11.2019    source источник
comment
вы нашли решение?   -  person nassim miled    schedule 20.05.2020


Ответы (4)


Вам просто нужно перезаписать исключение MissingScopeException, чтобы вернуть любое сообщение, которое вы хотите, и по-прежнему определять промежуточное ПО в ваших файлах маршрута.

в папке исключений в файле обработчика в функции рендеринга

if ($exception instanceof MissingScopeException && $request->wantsJson()){
            return response()->json([
                'error' => 'Unauthenticated',
            ], 403);
        }
person Mohammed Alama    schedule 14.05.2020

Вы запросили view-posts область, но затем попытались создать сообщение, для которого требуется create-posts область. Это проблема.

person burakcalik    schedule 01.12.2019
comment
Да, точно. Но в моем случае вместо исключения исключения он должен вернуть ответ 401 с сообщением Unauthenticated.. - person N'Bayramberdiyev; 02.12.2019

При создании access_token добавьте scope: create-posts

 $request->user()->token()->create([
            'access_token' => $response->access_token
        ], ['create-posts']);

person F.FB    schedule 09.01.2020

Я решаю эту проблему, добавляя промежуточное ПО и проверяя область действия, а не используя scopes: some_scope в маршрутах. Вот как я решил.

  1. создать промежуточное ПО и проверить область видимости в таком промежуточном программном обеспечении.

    public function handle($request, Closure $next){
    if (!$request->user()->tokenCan('user')) {
        return response()->json([
            'message' => "Unauthenticated",
        ]);
    }
    
    return $next($request);
    

    }

  2. request->user()->tokenCan('user') подтвердите объем. Я взял пример из документации laravel

  3. Вы можете вернуть сообщение об ошибке, что захотите.

    return response()->json([
        'message' => "Unauthenticated",
    ]);
    
  4. Используйте промежуточное ПО. Я нашел этот ответ, и это лучшее решение, которое я могу придумать, которое все еще находится в границах и не слишком много работы. Если вы решили лучше, поделитесь, пожалуйста, и со мной. Я тоже хочу знать.

person meowfitchoo    schedule 22.04.2020