LexikJWT与Scheb 2FA集成问题:验证码确认失败
问题:Symfony集成LexikJWT与Scheb2FA时验证码验证失败
环境配置
Security配置
firewalls: login: pattern: ^/login stateless: true provider: fos_userbundle json_login: check_path: /login_check username_path: _username password_path: _password success_handler: App\Application\Module\User\EventHandler\Security\AuthenticationSuccessHandler failure_handler: App\Application\Module\User\EventHandler\Security\AuthenticationFailureHandler user_checker: App\Application\Module\User\EventListener\Security\UserChecker two_factor: prepare_on_login: true main: pattern: ^/ provider: fos_userbundle stateless: true guard: authenticators: - lexik_jwt_authentication.jwt_token_authenticator two_factor: check_path: 2fa_login_check auth_code_parameter_name: _auth_code authentication_required_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationRequiredHandler failure_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationFailureHandler success_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationSuccessHandler
Scheb2FA配置
# See the configuration reference at https://symfony.com/bundles/SchebTwoFactorBundle/6.x/configuration.html scheb_two_factor: security_tokens: - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken email: enabled: true digits: 6 mailer: App\Application\Module\User\Service\Auth\AuthCodeMailer
LexikJWT配置
lexik_jwt_authentication: private_key_path: '%jwt_private_key_path%' public_key_path: '%jwt_public_key_path%' pass_phrase: '%jwt_key_pass_phrase%' token_ttl: '%jwt_token_ttl%' token_extractors: cookie: enabled: true name: shbee
问题现象
- 提交验证码验证时,报错:
User is not in a two-factor authentication process. - 排查发现当前认证使用的token为
Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken,而非Scheb2FA要求的Scheb\TwoFactorBundle\Security\Authentication\Token\TwoFactorTokenInterface
解决方案
1. 更新Scheb2FA的security_tokens配置
将JWTUserToken加入到Scheb2FA识别的token列表中,让Bundle能处理JWT类型的认证token:
scheb_two_factor: security_tokens: - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken - Lexik\Bundle\JWTAuthenticationBundle\Security\Authentication\Token\JWTUserToken # ...其他原有配置
2. 调整Stateless模式下的2FA状态存储
由于项目使用stateless防火墙,默认session存储无法保存2FA中间状态,需实现自定义token存储:
- 创建实现
Scheb\TwoFactorBundle\Security\TwoFactor\Token\TwoFactorTokenStorageInterface的存储类(如基于Redis) - 在配置中指定该存储:
scheb_two_factor: # ...其他配置 persistence: token_storage: App\Security\TwoFactor\CustomTwoFactorTokenStorage
3. 重构认证流程逻辑
- 用户名密码验证阶段:在
AuthenticationSuccessHandler中,不直接返回JWT,而是触发2FA准备流程,生成TwoFactorToken存入自定义存储,返回需验证2FA的响应。 - 2FA验证阶段:在
TwoFactorAuthenticationSuccessHandler中,验证通过后生成有效JWT并返回给客户端,完成全流程认证。
4. 修正防火墙的2FA配置顺序
确保main防火墙中two_factor配置在guard认证器之前,让2FA验证逻辑优先处理:
main: pattern: ^/ provider: fos_userbundle stateless: true two_factor: check_path: 2fa_login_check auth_code_parameter_name: _auth_code authentication_required_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationRequiredHandler failure_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationFailureHandler success_handler: App\Application\Module\User\EventHandler\Security\TwoFactorAuthenticationSuccessHandler guard: authenticators: - lexik_jwt_authentication.jwt_token_authenticator
内容的提问来源于stack exchange,提问作者Tebby
相关产品推荐
相关产品推荐

