LexikJWTAuthenticationBundle всегда отклоняет токены JWT при использовании кодировщика веб-токенов

Я пытался настроить LexikJWTAuthenticationBundle для использования в проекте на основе платформы API.

Этот API добавляется в существующий проект, который использует Sulu CMS (2.6.2) и Symfony (6.4.7). Я использую PHP 8.3, у меня установлен и включен OpenSSL.

Я хотел бы иметь возможность использовать функцию веб-токена LexikJWTAuthenticationBundle. Мне удалось заставить работать следующую конфигурацию, основанную на настройках пакета по умолчанию:

lexik_jwt_authentication:
  secret_key: '%env(resolve:JWT_SECRET_KEY)%'
  public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
  pass_phrase: '%env(JWT_PASSPHRASE)%'
  api_platform:
    enabled: true
    check_path: /api/login_check
    username_path: username
    password_path: password
  encoder:
    service: lexik_jwt_authentication.encoder.lcobucci
    signature_algorithm: ES512
  token_ttl: 3600
  allow_no_expiration: false
  clock_skew: 0
  user_id_claim: username
  token_extractors:
    authorization_header:
      enabled: true
      prefix: Bearer
      name: Authorization
    cookie:
      enabled: false
      name: BEARER
    query_parameter:
      enabled: false
      name: bearer
    split_cookie:
      enabled: false
      cookies: {  }
  remove_token_from_body_when_cookies_used: true
  set_cookies: {  }

Я следовал документации по настройке функции веб-токена. К сожалению, все рушится, как только я перехожу на использование lexik_jwt_authentication.encoder.web_token. Токены JWT всегда недействительны.

Я написал свою собственную службу поставщика пользователей, чтобы избежать конфликтов с Sulu, и проверил, что она работает с кодировщиком пакета по умолчанию.

Моя конфигурация пакета после перехода на кодировщик веб-токенов:

lexik_jwt_authentication:
  secret_key: '%env(resolve:JWT_SECRET_KEY)%'
  public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
  pass_phrase: '%env(JWT_PASSPHRASE)%'
  api_platform:
    enabled: true
    check_path: /api/login_check
    username_path: username
    password_path: password
  encoder:
    service: lexik_jwt_authentication.encoder.web_token
    signature_algorithm: ES512
  token_ttl: 3600
  allow_no_expiration: false
  clock_skew: 0
  user_id_claim: username
  token_extractors:
    authorization_header:
      enabled: true
      prefix: Bearer
      name: Authorization
    cookie:
      enabled: false
      name: BEARER
    query_parameter:
      enabled: false
      name: bearer
    split_cookie:
      enabled: false
      cookies: {  }
  remove_token_from_body_when_cookies_used: true
  set_cookies: {  }
  access_token_issuance:
    enabled: true
    signature:
      algorithm: ES512
      key: # key
  access_token_verification:
    enabled: true
    signature:
      allowed_algorithms:
        - ES512
      keyset: # keyset
      header_checkers: {  }
      claim_checkers:
        - exp_with_clock_skew
        - iat_with_clock_skew
        - nbf_with_clock_skew
      mandatory_claims: {  }
  blocklist_token:
    enabled: false
    cache: cache.app

Как я запрашиваю токен:

curl -X POST http://localhost/api/login_check \
-H 'Content-Type: application/ld+json' \
-d '{"username":"someusername","password":"somepassword"}'

Запрос, который я делаю после получения токена:

curl -H 'Accept: application/ld+json' \
-H 'Authorization: Bearer <token>' http://localhost/api/some-endpoint/4

Мне удалось отследить проблему до момента загрузки и декодирования токена. Он правильно десериализован и разбит на массив. После этого момента это терпит неудачу. Это заставляет меня подозревать, что проблема с кодировкой моих ключей, но я не уверен, что делаю не так.

Я использовал команды web-token/jwt-bundle для генерации ключей и пробовал использовать автономное приложение JWT . Я проанализировал результаты с помощью команд key:analyze и keyset:analyze пакета. Кажется, они правы. И я просмотрел здесь связанные вопросы, чтобы узнать, была ли у кого-то подобная проблема. К сожалению, это не помогло.

Я был бы очень признателен за любую информацию по этому поводу. Я определенно врезался в стену. Заранее спасибо!

Обновлено: После некоторой отладки кажется, что шифрование является обязательным для этого пакета при использовании функции веб-токена, хотя в документации указано иное. Поскольку у меня не было настроено шифрование, все мои запросы с использованием токена отклонялись из-за неопределенного алгоритма.

Шифрование работает, а расшифровка нет. Он доходит до части процесса расшифровки, а затем терпит неудачу. Итак, я все еще получаю Invalid JWT Token ответ.

Моя полная конфигурация с включенным шифрованием:

lexik_jwt_authentication:
  secret_key: '%env(resolve:JWT_PRIVATE_KEY)%'
  public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
  pass_phrase: '%env(JWT_PASSPHRASE)%'
  api_platform:
    enabled: true
    check_path: /api/login_check
    username_path: username
    password_path: password
  encoder:
    service: lexik_jwt_authentication.encoder.web_token
    signature_algorithm: ES512
  token_ttl: 3600
  allow_no_expiration: false
  clock_skew: 0
  user_id_claim: username
  token_extractors:
    authorization_header:
      enabled: true
      prefix: Bearer
      name: Authorization
    cookie:
      enabled: false
      name: BEARER
    query_parameter:
      enabled: false
      name: bearer
    split_cookie:
      enabled: false
      cookies: {  }
  remove_token_from_body_when_cookies_used: true
  set_cookies: {  }
  access_token_issuance:
    enabled: true
    signature:
      algorithm: ES512
      key: # key
    encryption:
      enabled: true
      key_encryption_algorithm: RSA-OAEP-256
      content_encryption_algorithm: A256CBC-HS512
      key: # key
  access_token_verification:
    enabled: true
    signature:
      allowed_algorithms:
        - ES512
      keyset: # keyset
      header_checkers: {  }
      claim_checkers:
        - exp_with_clock_skew
        - iat_with_clock_skew
        - nbf_with_clock_skew
      mandatory_claims: {  }
    encryption:
      enabled: true
      continue_on_decryption_failure: false
      header_checkers:
        - iat_with_clock_skew
        - nbf_with_clock_skew
        - exp_with_clock_skew
      allowed_key_encryption_algorithms:
        - RSA-OAEP-256
      allowed_content_encryption_algorithms:
        - A256CBC-HS512
      keyset: # keyset
  blocklist_token:
    enabled: false
    cache: cache.app
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда я изначально опубликовал этот вопрос, я не был уверен, была ли проблема, с которой я столкнулся, ошибкой или проблемой конфигурации с моей стороны. Я также открыл задачу в официальном репозитории.

Сегодня мне удалось еще немного покопаться в этом, и это действительно похоже на ошибку. Я опубликовал обходной путь в проблеме GitHub вместе с дополнительной информацией. Но я также опубликую это здесь для полноты картины для всех, кто просто хочет работающее решение без дополнительных подробностей.

В качестве обходного пути, пока ошибка не будет исправлена, я расширил свой класс Kernel, реализовав CompilerPassInterface, как описано в документации Symfony Как работать с проходами компилятора. Переопределение значений конфигурации шифрования по умолчанию с помощью null предотвращает создание исключений и обеспечивает правильную работу как выдачи токена доступа, так и проверки.

Обратите внимание, что этот обходной путь работает только в том случае, если вы не используете шифрование. Мне до сих пор не удалось заставить работать расшифровку. Но это отдельная тема.

// src/Kernel.php
namespace App;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;

class Kernel extends BaseKernel implements CompilerPassInterface
{
    use MicroKernelTrait;
    
    // ...

    public function process(ContainerBuilder $container): void
    {
        $accessTokenBuilderService = 'lexik_jwt_authentication.access_token_builder';
        $accessTokenLoaderService = 'lexik_jwt_authentication.access_token_loader';

        if ($container->hasDefinition($accessTokenBuilderService)) {
            $container->getDefinition($accessTokenBuilderService)
                ->replaceArgument(5, null)
                ->replaceArgument(6, null)
                ->replaceArgument(7, null);
        }

        if ($container->hasDefinition($accessTokenLoaderService)) {
            $container->getDefinition($accessTokenLoaderService)
                ->replaceArgument(9, null)
                ->replaceArgument(10, null)
                ->replaceArgument(11, null)
                ->replaceArgument(12, null);
        }
    }

    // ...
}

Следующий пример конфигурации работает с приведенной выше Kernel реализацией. Меняйте по мере необходимости.

# config/services.yaml
parameters:
  # ...
  env(SIGNATURE_KEY): '%kernel.project_dir%/config/jwt/signature.jwk'
  env(SIGNATURE_KEYSET): '%kernel.project_dir%/config/jwt/signature.jwkset'
# config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
  secret_key: '%env(resolve:JWT_PRIVATE_KEY)%'
  public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
  pass_phrase: '%env(JWT_PASSPHRASE)%'
  api_platform:
    enabled: true
    check_path: /api/login_check
    username_path: username
    password_path: password
  encoder:
    service: lexik_jwt_authentication.encoder.web_token
  token_ttl: 3600
  allow_no_expiration: false
  clock_skew: 0
  user_id_claim: username
  token_extractors:
    authorization_header:
      enabled: true
      prefix: Bearer
      name: Authorization
  access_token_issuance:
    enabled: true
    signature:
      algorithm: RS256
      key: '%env(file:SIGNATURE_KEY)%'
  access_token_verification:
    enabled: true
    signature:
      allowed_algorithms:
        - RS256
      keyset: '%env(file:SIGNATURE_KEYSET)%'
      header_checkers: {  }
      claim_checkers:
        - exp_with_clock_skew
        - iat_with_clock_skew
        - nbf_with_clock_skew
      mandatory_claims: {  }
  blocklist_token:
    enabled: false
    cache: cache.app

Другие вопросы по теме