Skip to content

Commit 4536039

Browse files
committed
Implement QR code for MFA setup
Signed-off-by: Tim Goudriaan <tim@codedmonkey.com>
1 parent 0403d9a commit 4536039

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\HttpFoundation\Request;
@@ -119,4 +121,27 @@ public function clearMfa(Request $request, User $user): Response
119121
'form' => $form,
120122
]);
121123
}
124+
125+
#[Route('/account/mfa/qr-code', name: 'dashboard_account_mfa_qr_code', methods: ['GET'])]
126+
#[IsGranted('ROLE_USER')]
127+
public function mfaQrCode(Request $request, #[CurrentUser] User $user): Response
128+
{
129+
$session = $request->getSession();
130+
131+
if (null === $totpSecret = $session->get('totp_secret')) {
132+
throw $this->createAccessDeniedException();
133+
}
134+
135+
$darkMode = 'dark' === $request->query->getString('mode', 'light');
136+
137+
$user->setTotpSecret($totpSecret);
138+
139+
$builder = new QrCodeBuilder(data: $this->totpAuthenticator->getQRContent($user));
140+
$result = $builder->build(
141+
foregroundColor: $darkMode ? new Color(212, 212, 212) : null,
142+
backgroundColor: $darkMode ? new Color(17, 21, 23) : null,
143+
);
144+
145+
return new Response($result->getString(), 200, ['Content-Type' => 'image/png']);
146+
}
122147
}

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
@@ -119,5 +119,6 @@ account:
119119
disable: Disable MFA authentication
120120
enable: Enable MFA authentication
121121
help: Secure your account with a time-based code from an authenticator app.
122+
qr-code-alt: QR-code containing the MFA secret.
122123
state-disabled: Multi-factor authentication is currently disabled.
123124
state-enabled: Multi-factor authentication is currently enabled.

0 commit comments

Comments
 (0)