Skip to content

Commit 503f1ce

Browse files
committed
Implement QR code for MFA setup
1 parent b217674 commit 503f1ce

4 files changed

Lines changed: 38 additions & 0 deletions

File tree

assets/stylesheets/dashboard-theme.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,11 @@
6969
display: inline-block;
7070
width: 120px;
7171
}
72+
73+
body.ea-dark-scheme img.img-light {
74+
display: none;
75+
}
76+
77+
body:not(.ea-dark-scheme) img.img-dark {
78+
display: none;
79+
}

src/Controller/Dashboard/DashboardAccountController.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use CodedMonkey\Dirigent\Form\ChangePasswordFormType;
99
use CodedMonkey\Dirigent\Form\MfaClearFormType;
1010
use CodedMonkey\Dirigent\Form\MfaSetupFormType;
11+
use Endroid\QrCode\Builder\Builder as QrCodeBuilder;
12+
use Endroid\QrCode\Color\Color;
1113
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Totp\TotpAuthenticatorInterface;
1214
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1315
use Symfony\Component\Form\FormError;
@@ -134,6 +136,29 @@ public function mfa(Request $request, #[CurrentUser] User $user): Response
134136
]);
135137
}
136138

139+
#[Route('/account/mfa/qr-code', name: 'dashboard_account_mfa_qr_code', methods: ['GET'])]
140+
#[IsGranted('ROLE_USER')]
141+
public function mfaQrCode(Request $request, #[CurrentUser] User $user): Response
142+
{
143+
$session = $request->getSession();
144+
145+
if (null === $totpSecret = $session->get('totp_secret')) {
146+
throw $this->createNotFoundException();
147+
}
148+
149+
$darkMode = 'dark' === $request->query->getString('mode', 'light');
150+
151+
$user->setTotpSecret($totpSecret);
152+
153+
$builder = new QrCodeBuilder(data: $this->totpAuthenticator->getQRContent($user));
154+
$result = $builder->build(
155+
foregroundColor: $darkMode ? new Color(212, 212, 212) : null,
156+
backgroundColor: $darkMode ? new Color(17, 21, 23) : null,
157+
);
158+
159+
return new Response($result->getString(), 200, ['Content-Type' => 'image/png']);
160+
}
161+
137162
private function validatePassword(FormInterface $passwordField, User $user): void
138163
{
139164
$currentPassword = $passwordField->getData();

templates/dashboard/account/mfa_setup.html.twig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
{% block page_content %}
66
<div class="row">
77
<div class="col-md-6 col-xxl-5">
8+
<div class="mb-3">
9+
<img src="{{ path('dashboard_account_mfa_qr_code', {mode: 'dark'}) }}" alt="{{ 'account.mfa.qr-code-alt'|trans }}" class="img-dark">
10+
<img src="{{ path('dashboard_account_mfa_qr_code') }}" alt="{{ 'account.mfa.qr-code-alt'|trans }}" class="img-light">
11+
</div>
812
<div class="mb-3">
913
<label for="totp_secret" class="form-label">{{ 'MFA secret' }}</label>
1014
<input id="totp_secret" type="text" value="{{ totpContent }}" readonly class="form-control">

translations/messages.en.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,6 @@ account:
118118
disable: Disable MFA authentication
119119
enable: Enable MFA authentication
120120
help: Secure your account with a time-based code from an authenticator app.
121+
qr-code-alt: QR-code containing the MFA secret.
121122
state-disabled: Multi-Factor Authentication is currently disabled.
122123
state-enabled: Multi-Factor Authentication is currently enabled.

0 commit comments

Comments
 (0)