Target [Lcobucci\\JWT\\Parser] is not instantiable

16 Июля 2024 23:34

Ошибка "Target [Lcobucci\\JWT\\Parser] is not instantiable while building [App\\Containers\\Authentication\\Actions\\LogoutAction]." возникла при работе с Laravel Passport и использовании его в рамках архитектурного паттерна Porto на laravel 11. Нужно было распарсить $id

Вообще эта ошибка всегда означает, что какой-то сторонний класс не может быть загружен через Dependency Injection фреймворка Laravel, но в данном случае, это должен был обеспечить Passport. По невыясненным причинам, Passport этого не сделал.

Основные ответы на просторах интернета были в духе "добавь в composer.json laravel/passport 3.3.3 и запусти composer update", но этот вариант не сработал (Естественно, даже с более новыми версиями).

Решение

Как вариант, подключить собственный сервис провайдер.

Создаем файл App/Providers/JwtServiceProvider.php со следующим содержимым:

<?php declare(strict_types=1);

namespace App\Ship\Providers;

use Illuminate\Support\ServiceProvider;
use Lcobucci\JWT\Configuration;

/**
 * Подключаем Lcobucci\JWT вручную т.к. через Passport не работает
 */
class JwtServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(Configuration::class, function ($app) {
            return Configuration::forSymmetricSigner(
                new \Lcobucci\JWT\Signer\Hmac\Sha256(), // Алгоритм подписания
                \Lcobucci\JWT\Signer\Key\InMemory::plainText(env('PASSPORT_CLIENT_SECRET')) // Ключ для работы
            );
        });
    }

    public function boot()
    {
        //
    }
}

В env('PASSPORT_CLIENT_SECRET') - должен быть секретный ключ, который был сгенерирован при запуске php artisan passport:keys.

Регистрируем сервис провайдер в config/app.php (Если laravel до 11 версии) или в bootstrap/providers.php (если Laravel 11)

Использовать можно следующим образом:

<?php

namespace App\Containers\Authentication\Actions;

use App\Containers\Authentication\UI\API\Requests\LogoutRequest;
use Lcobucci\JWT\Configuration;
use Lorisleiva\Actions\Concerns\AsAction;

class LogoutAction
{
    use AsAction;

    public function __construct(
        private readonly Configuration $jwtConfig,
    )
    {
    }

    public function handle()
    {
        // ...
    }

    public function asController(LogoutRequest $request)
    {
        //...
        $id = $this->jwtConfig->parser()->parse($request->bearerToken())->claims()->get('jti');
        //...
    }
}

Таким образом, парсер jwt Будет работать, как и остальные сервисы Lcobucci.