扩展 scheb/2fa-bundle,通过电子邮件实现双因素认证

v1.1.0 2024-04-19 23:08 UTC

This package is auto-updated.

Last update: 2024-09-19 23:58:11 UTC


README

PHPCSFixer PHPStan PHPUnit Packagist Version Packagist Downloads

danieldburger1337/2fa-email

本扩展是 scheb/2fa-bundle 的扩展,提供了比默认的 scheb/2fa-email 提供程序更高级的电子邮件双因素认证。

它增加了让认证码过期(默认为 15 分钟)的功能,并使生成电子邮件消息的定制更加友好。

安装

composer install danielburger1337/2fa-email
// config/bundles.php
return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
    danielburger1337\SchebTwoFactorBundle\TwoFactorEmailBundle::class => ['all' => true],
];

自定义电子邮件

您有多种方式可以自定义创建和发送认证码消息的过程。

默认情况下,该扩展生成一个基本的电子邮件。您可以通过设置 email_subjectemail_bodysender_emailsender_name 参数来自定义主题和正文。在 email_body 模板中的 "{{AUTH_CODE}}" 字符串将在发送电子邮件时被实际的认证码替换。

您可以通过创建一个实现 AuthCodeEmailGeneratorInterface 的服务并设置 email_generator 参数为该服务 ID 来更改 symfony/mime 电子邮件消息生成(例如创建一个twig TemplatedEmail)。

然后,生成的消息将通过 symfony/mailer 和默认的 mailer.mailer 服务发送。如果您想使用不同的 symfony/mailer 服务来发送消息,只需将服务 ID 设置为 symfony_mailer 参数。

最后,如果您根本不想使用 symfony/mailer,您可以创建一个实现 AuthCodeMailerInterface 的服务,该服务可以完全独立地处理消息生成和发送。要使用此服务,您只需将 mailer 参数设置为该服务的 ID。

重新发送认证码

如果您想重新发送认证消息(可能消息在传输过程中丢失),最简单的方法是使用 RequestEvent::class 事件监听器并注入 AuthCodeMailerInterface 服务并调用 "sendAuthCode" 方法。

默认情况下,使用 "正常" 路由不起作用,因为 scheb/2fa-bundle 会始终将该路由重定向到 2fa 终端。

declare(strict_types=1);

use danielburger1337\SchebTwoFactorBundle\Mailer\AuthCodeMailerInterface;
use danielburger1337\SchebTwoFactorBundle\Model\TwoFactorEmailInterface;
use Scheb\TwoFactorBundle\Security\Authentication\Token\TwoFactorTokenInterface;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

#[AsEventListener(RequestEvent::class)]
class ResendEmailAuthCodeEventListener
{

    public function __construct(
        private readonly RateLimiterFactory $rateLimiterFactory,
        private readonly AuthCodeMailerInterface $authCodeMailer,
        private readonly TokenStorageInterface $tokenStorage,
    ) {
    }

    public function __invoke(RequestEvent $request): void
    {
        $request = $event->getRequest();

        if ($request->attributes->get('_route') !== '2fa_login') {
            return;
        }

        $token = $this->tokenStorage->getToken();
        $user = $token?->getUser();

        if (!$token instanceof TwoFactorTokenInterface || !$user instanceof TwoFactorEmailInterface) {
            return;
        }

        // somehow determine that you want to resend the email
        if ($request->request->get('resendAuthCode') === 'true') {
            // If you use rate limiting, make sure to also use the auth code as key,
            // otherwise the user might get throttled when their code has expired and a new one should be sent.
            $rateLimiter = $this->rateLimiterFactory->create(
                'tfa_email_'.\hash('xxh128', $user->getEmailAuthCode().$user->getEmailAuthRecipient())
            );

            if ($rateLimiter->consume(1)->isAccepted()) {
                // mail the auth code
                $this->authCodeMailer->sendAuthCode($user);
            }
        }
    }

}

配置参考

列出的值是默认值。每个值都是可选的。

# config/packages/two_factor_email.yaml
two_factor_email:
    # A custom service to manage the auth code
    # It must implement AuthCodeProviderInterface
    auth_code_provider: null
    # This option is only used when the default `auth_code_provider` is used:
    # A \DateInterval compatible value that sets
    # how long an auth code is considered valid.
    # `null` disables expiration.
    expires_after: PT15M

    # ---------------------------------------------

    # A custom service that creates the auth code
    # It must implement AuthCodeGeneratorInterface
    code_generator: null
    # This option is only used when the default `code_generator` is used:
    # The length of the generated auth code
    digits: 6

    # A custom service that sends the auth code to the user
    # It must implement AuthCodeMailerInterface
    # The default implementation has a hard dependency on symonfy/mailer,
    # so make sure that you have the package installed.
    mailer: null
    # A custom symfony/mailer service to send the emails with.
    # "mailer.mailer" is the default symfony/mailer service.
    symfony_mailer: mailer.mailer
    # A custom service that generates the mime email messsage to send
    # It must implement AuthCodeEmailGeneratorInterface.
    email_generator: null
    # Subject of the generated email
    email_subject: Authentication Code
    # Text message body of the generated email
    # "{{AUTH_CODE}}" is a template string that will be replaced with the actual auth code.
    email_body: "{{AUTH_CODE}}"
    # "From" header address
    sender_email: null
    # "From" header name
    sender_name: null

    # A custom form renderer service that renders the 2fa form.
    # It must implement TwoFactorFormRendererInterface.
    form_renderer: null
    # The twig template to render when no custom form renderer was defined.
    template: "@SchebTwoFactor/Authentication/form.html.twig"

许可

本软件可在 MIT 许可下使用。