使用网络令牌编码器时,LexikJWTAuthenticationBundle 始终拒绝 JWT 令牌

问题描述 投票:0回答:1

我一直在尝试配置 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 symfony jwt lexikjwtauthbundle
1个回答
0
投票

当我最初发布这个问题时,我不确定我遇到的问题是错误还是配置问题。我也在官方存储库中打开了一个问题

今天我能够更深入地研究这个问题,它确实似乎是一个错误。我在 GitHub 问题中发布了解决方法以及其他信息。但为了让那些只想要一个可行的解决方案而不需要其他细节的人保持完整,我也会将其发布在这里。

作为修复 bug 之前的解决方法,我通过实现

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
    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: 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

© www.soinside.com 2019 - 2024. All rights reserved.