Я пытался настроить 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






Когда я изначально опубликовал этот вопрос, я не был уверен, была ли проблема, с которой я столкнулся, ошибкой или проблемой конфигурации с моей стороны. Я также открыл задачу в официальном репозитории.
Сегодня мне удалось еще немного покопаться в этом, и это действительно похоже на ошибку. Я опубликовал обходной путь в проблеме 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