Skip to content

Commit 10d0ca8

Browse files
committed
temp totp
1 parent b3c63bd commit 10d0ca8

4 files changed

Lines changed: 79 additions & 7 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20250409225651 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Add TOTP secret';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql(<<<'SQL'
20+
ALTER TABLE "user" ADD totp_secret VARCHAR(255) DEFAULT NULL
21+
SQL);
22+
}
23+
24+
public function down(Schema $schema): void
25+
{
26+
$this->addSql(<<<'SQL'
27+
ALTER TABLE "user" DROP totp_secret
28+
SQL);
29+
}
30+
}

src/Controller/Dashboard/DashboardAccountController.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use CodedMonkey\Dirigent\Form\AccountFormType;
88
use CodedMonkey\Dirigent\Form\ChangePasswordFormType;
99
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
10+
use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Totp\TotpAuthenticatorInterface;
1011
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1112
use Symfony\Component\Form\FormError;
1213
use Symfony\Component\HttpFoundation\Request;
@@ -28,6 +29,7 @@ public static function getSubscribedServices(): array
2829
public function __construct(
2930
private readonly UserRepository $userRepository,
3031
private readonly UserPasswordHasherInterface $passwordHasher,
32+
private readonly TotpAuthenticatorInterface $totpAuthenticator,
3133
) {
3234
}
3335

@@ -36,8 +38,6 @@ public function __construct(
3638
public function account(Request $request, #[CurrentUser] User $user): Response
3739
{
3840
$accountForm = $this->createForm(AccountFormType::class, $user);
39-
$passwordForm = $this->createForm(ChangePasswordFormType::class);
40-
4141
$accountForm->handleRequest($request);
4242

4343
if ($accountForm->isSubmitted() && $accountForm->isValid()) {
@@ -50,6 +50,7 @@ public function account(Request $request, #[CurrentUser] User $user): Response
5050
return $this->redirect($url);
5151
}
5252

53+
$passwordForm = $this->createForm(ChangePasswordFormType::class);
5354
$passwordForm->handleRequest($request);
5455

5556
if ($passwordForm->isSubmitted()) {
@@ -72,9 +73,17 @@ public function account(Request $request, #[CurrentUser] User $user): Response
7273
}
7374
}
7475

76+
$totpSecret = $this->totpAuthenticator->generateSecret();
77+
78+
$mfaForm = $this->createForm(MfaFormType::class, ['secret' => $totpSecret]);
79+
$mfaForm->handleRequest($request);
80+
81+
$oneTimePassword = $this->totpAuthenticator->checkCode()
82+
7583
return $this->render('dashboard/account.html.twig', [
7684
'accountForm' => $accountForm,
7785
'passwordForm' => $passwordForm,
86+
'totpSecret' => $totpSecret,
7887
]);
7988
}
8089
}

src/Doctrine/Entity/User.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
use Doctrine\ORM\Mapping\GeneratedValue;
99
use Doctrine\ORM\Mapping\Id;
1010
use Doctrine\ORM\Mapping\Table;
11+
use Scheb\TwoFactorBundle\Model\Totp\TotpConfiguration;
12+
use Scheb\TwoFactorBundle\Model\Totp\TotpConfigurationInterface;
13+
use Scheb\TwoFactorBundle\Model\Totp\TwoFactorInterface;
1114
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
1215
use Symfony\Component\Security\Core\User\UserInterface;
1316

1417
#[Entity(repositoryClass: UserRepository::class)]
1518
#[Table(name: '`user`')]
16-
class User implements UserInterface, PasswordAuthenticatedUserInterface
19+
class User implements UserInterface, PasswordAuthenticatedUserInterface, TwoFactorInterface
1720
{
1821
#[Column]
1922
#[GeneratedValue]
@@ -37,6 +40,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
3740

3841
private ?string $plainPassword = null;
3942

43+
#[Column(nullable: true)]
44+
private ?string $totpSecret = null;
45+
4046
public function getId(): ?int
4147
{
4248
return $this->id;
@@ -108,6 +114,16 @@ public function setPlainPassword(string $password): self
108114
return $this;
109115
}
110116

117+
public function getTotpSecret(): ?string
118+
{
119+
return $this->totpSecret;
120+
}
121+
122+
public function setTotpSecret(?string $totpSecret): void
123+
{
124+
$this->totpSecret = $totpSecret;
125+
}
126+
111127
public function getUserIdentifier(): string
112128
{
113129
return (string) $this->username;
@@ -158,4 +174,19 @@ public function setSuperAdmin(bool $admin): void
158174
}
159175
}
160176
}
177+
178+
public function isTotpAuthenticationEnabled(): bool
179+
{
180+
return null !== $this->totpSecret;
181+
}
182+
183+
public function getTotpAuthenticationUsername(): string
184+
{
185+
return $this->username;
186+
}
187+
188+
public function getTotpAuthenticationConfiguration(): ?TotpConfigurationInterface
189+
{
190+
return new TotpConfiguration($this->totpSecret, TotpConfiguration::ALGORITHM_SHA1, 20, 8);
191+
}
161192
}

templates/dashboard/account.html.twig

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,20 @@
4141
<div class="form-fieldset field-form_fieldset">
4242
<div class="form-fieldset-header with-help">
4343
<div class="form-fieldset-title">
44-
<span class="not-collapsible form-fieldset-title-content">Multi-Factor Authentication</span>
45-
<div class="form-fieldset-help">Add an extra layer of security</div>
44+
<span class="not-collapsible form-fieldset-title-content">{{ 'Multi-Factor Authentication' }}</span>
45+
<div class="form-fieldset-help">{{ 'account.mfa.help'|trans }}</div>
4646
</div>
4747
</div>
4848

4949
<div class="form-fieldset-body show">
5050
<div class="row">
5151
<div class="col-md-6 col-xxl-5">
52-
todo
52+
<div class="mb-3">
53+
<label for="totp_secret" class="form-label required">{{ 'MFA secret' }}</label>
54+
<input id="totp_secret" type="text" value="{{ totpSecret }}" class="form-control">
55+
</div>
5356
</div>
5457
</div>
5558
</div>
5659
</div>
57-
5860
{% endblock %}

0 commit comments

Comments
 (0)