diff --git a/config/packages/scheb_2fa.yaml b/config/packages/scheb_2fa.yaml index 62a6611d..4359d0fb 100644 --- a/config/packages/scheb_2fa.yaml +++ b/config/packages/scheb_2fa.yaml @@ -3,8 +3,8 @@ scheb_two_factor: google: enabled: true # If Google Authenticator should be enabled, default false - server_name: '%partdb.title%' # Server name used in QR code - issuer: 'Part-DB' # Issuer name used in QR code + server_name: '$$DOMAIN$$' # This field is replaced by the domain name of the server in DecoratedGoogleAuthenticator + issuer: '%partdb.title%' # Issuer name used in QR code digits: 6 # Number of digits in authentication code window: 1 # How many codes before/after the current one would be accepted as valid template: security/2fa_form.html.twig diff --git a/src/Controller/UserSettingsController.php b/src/Controller/UserSettingsController.php index 4c721bb8..ce407a6b 100644 --- a/src/Controller/UserSettingsController.php +++ b/src/Controller/UserSettingsController.php @@ -35,6 +35,7 @@ use App\Services\UserSystem\UserAvatarHelper; use Doctrine\ORM\EntityManagerInterface; use RuntimeException; use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google\GoogleAuthenticator; +use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google\GoogleAuthenticatorInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -204,7 +205,8 @@ class UserSettingsController extends AbstractController * @return RedirectResponse|Response */ #[Route(path: '/settings', name: 'user_settings')] - public function userSettings(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordEncoder, GoogleAuthenticator $googleAuthenticator, BackupCodeManager $backupCodeManager, FormFactoryInterface $formFactory, UserAvatarHelper $avatarHelper): RedirectResponse|Response + public function userSettings(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordEncoder, + GoogleAuthenticatorInterface $googleAuthenticator, BackupCodeManager $backupCodeManager, FormFactoryInterface $formFactory, UserAvatarHelper $avatarHelper): RedirectResponse|Response { /** @var User $user */ $user = $this->getUser(); diff --git a/src/Services/UserSystem/TFA/DecoratedGoogleAuthenticator.php b/src/Services/UserSystem/TFA/DecoratedGoogleAuthenticator.php new file mode 100644 index 00000000..562358c5 --- /dev/null +++ b/src/Services/UserSystem/TFA/DecoratedGoogleAuthenticator.php @@ -0,0 +1,71 @@ +. + */ + +namespace App\Services\UserSystem\TFA; + +use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface; +use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google\GoogleAuthenticator; +use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google\GoogleAuthenticatorInterface; +use Symfony\Component\DependencyInjection\Attribute\AsDecorator; +use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated; +use Symfony\Component\HttpFoundation\RequestStack; + +#[AsDecorator(GoogleAuthenticatorInterface::class)] +class DecoratedGoogleAuthenticator implements GoogleAuthenticatorInterface +{ + + public function __construct( + #[AutowireDecorated] + private GoogleAuthenticatorInterface $inner, + private RequestStack $requestStack) + { + + } + + public function checkCode(TwoFactorInterface $user, string $code): bool + { + return $this->inner->checkCode($user, $code); + } + + public function getQRContent(TwoFactorInterface $user): string + { + $qr_content = $this->inner->getQRContent($user); + + //Replace $$DOMAIN$$ with the current domain + $request = $this->requestStack->getCurrentRequest(); + + //If no request is available, just put "Part-DB" as domain + $domain = "Part-DB"; + + if ($request !== null) { + $domain = $request->getHttpHost(); + } + + //Domain must be url encoded + $domain = urlencode($domain); + + return str_replace(urlencode('$$DOMAIN$$'), $domain, $qr_content); + } + + public function generateSecret(): string + { + return $this->inner->generateSecret(); + } +} \ No newline at end of file