marcinchus / secure-jwt-bundle
用于提高JWT安全性的工具包
Requires
- php: ^7.4||^8.0
- ext-json: *
- api-platform/api-pack: ^1.2
- api-platform/core: ^2.5
- doctrine/orm: ^2.7
- endroid/qr-code-bundle: ^3.4
- friendsofsymfony/rest-bundle: ^3.0
- laminas/laminas-zendframework-bridge: ^1.4
- lexik/jwt-authentication-bundle: ^2.6
- scheb/2fa-bundle: ^v5.13
- scheb/2fa-email: ^v5.13
- scheb/2fa-google-authenticator: ^v5.13
- symfony/messenger: ^5.0
Requires (Dev)
- phpunit/phpunit: ^9.1
README
Symfony工具包,使JWT更安全
安装
安装过程可能不流畅且存在错误,但很容易解决
composer require connectholland/secure-jwt-bundle
安装后可能会出现错误
Cannot autowire service "ConnectHolland\SecureJWTBundle\EventSubscriber\LoginSubscriber": argument "$googleAuthenticator" of method "__construct()" references class "Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google\GoogleAuthenticator" but no such service exists.
配置scheb twofactor Google
在scheb_two_factor.yaml
文件中
scheb_two_factor: security_tokens: - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken google: enabled: true server_name: Secure Server issuer: Connect Holland digits: 6 window: 1
再次运行
composer require connectholland/secure-jwt-bundle
以完成安装。
BTW1:在安装此工具包之前安装scheb twofactor工具包也可以防止此错误。
BTW2:当然,欢迎提交修复这些问题的PR :)
Cookie存储
本地存储中的令牌不安全,因此如果您从Web界面使用令牌,您应该将它们存储在其他地方。安全的Cookie是一个不错的选择。如下配置Cookie存储
让lexik/jwt-authentication-bundle查看Cookie
在lexik_jwt_authentication.yaml
配置文件中
lexik_jwt_authentication: secret_key: '%env(resolve:JWT_SECRET_KEY)%' public_key: '%env(resolve:JWT_PUBLIC_KEY)%' pass_phrase: '%env(JWT_PASSPHRASE)%' token_extractors: # Default header auth, can be useful to allow for other auth types (for example /api) authorization_header: enabled: true # Make sure this is enabled cookie: enabled: true name: BEARER set_cookies: BEARER: ~
确保令牌设置为安全Cookie
在security.yaml
配置文件中
login: pattern: ^/api/login stateless: true anonymous: true json_login: check_path: /api/login_check success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure
使令牌失效
默认情况下,令牌在过期前有效。这使得无法真正注销。您可以配置令牌失效以允许注销
创建数据库表
在doctrine.yaml
文件中
doctrine: orm: mappings: ConnectHolland\SecureJWTBundle: is_bundle: true type: annotation dir: '%kernel.project_dir%/vendor/connectholland/secure-jwt-bundle/src/Entity' prefix: 'ConnectHolland\SecureJWTBundle\Entity' alias: SecureJWTBundle
并运行迁移
bin/console doctrine:migrations:diff bin/console doctrine:migrations:migrate -n
配置API端点注销
在api_platform.yaml
文件中
api_platform: mapping: paths: ['%kernel.project_dir%/vendor/connectholland/secure-jwt-bundle/src/Message']
当然,不要删除可能已在paths
配置中存在的其他必需路径。
您的API中将有一个logout
端点。此端点需要以下格式化的消息
{ "logout": "some string" }
注销的值不重要且不使用。此字段是必需的,因为API平台要求消息中至少有一个字段。(欢迎提供更好的解决方案)。
不允许失效的令牌
在security.yaml
文件中
api: pattern: ^/api stateless: true anonymous: true guard: authenticators: - ConnectHolland\SecureJWTBundle\Security\Guard\JWTTokenAuthenticator
JWT中的双因素认证
配置Google身份验证器
在scheb_two_factor.yaml
文件中
scheb_two_factor: security_tokens: - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken google: enabled: true server_name: Secure Server issuer: Connect Holland digits: 6 window: 1
使用two_factor_jwt安全监听器和提供程序
在security.yaml
文件中
login: pattern: ^/api/login stateless: true anonymous: true two_factor_jwt: check_path: /api/login_check success_handler: ConnectHolland\SecureJWTBundle\Security\Http\Authentication\AuthenticationSuccessHandler failure_handler: ConnectHolland\SecureJWTBundle\Security\Http\Authentication\AuthenticationFailureHandler
实现正确的接口
您的用户对象应实现ConnectHolland\SecureJWTBundle\Entity\TwoFactorUserInterface
。
使用2FA
curl -X POST http://host/api/users/authenticate -H 'Content-Type: application/json' -d '{"username": "username", "password": "password"}'
这将返回以下响应
{ "result":"ok", "status":"two factor authentication required" }
如果尚未设置2FA,您将收到
{ "result":"ok", "message":"use provided QR code to set up two factor authentication", "qr":"QR code (data URL)" }
在下一次调用中添加双因素挑战
curl -X POST http://host/api/users/authenticate -H 'Content-Type: application/json' -d '{"username": "username", "password": "password", "challenge": "123456"}'
如果正确,您将收到
{ "result":"ok" }
响应头将包括一个包含JWT令牌的安全Cookie,允许未来的认证调用。
2FA 记住此设备
记住设备功能允许用户在可配置的天数内跳过2FA。默认配置设置为false,这意味着在登录后不会设置REMEMBER_DEVICE cookie。默认天数设置为30。
配置
在根项目的config/packages文件夹中创建一个名为:connect_holland_secure_jwt.yaml
的新文件
在此文件中可以设置配置
connect_holland_secure_jwt: is_remembered: true expiry_days: 14
如前所述,登录后,将设置REMEMBER_DEVICE cookie。它将包含一个Unix到期时间和用户的电子邮件。
除了放置cookie外,它还将保存在secure_jwt_remember_device_token
表中。该实体可在src/Entity/RememberDeviceToken.php
中找到
恢复代码
您可以检索用于2FA的恢复代码,允许您重置2FA。如果将有效的恢复代码作为challenge
输入,则2FA将重置,并返回一个QR代码响应。