Some more work on 2FA

This commit is contained in:
Pinga 2023-11-21 16:00:49 +02:00
parent 2b6bdc71e9
commit a8be1a3c30
3 changed files with 86 additions and 8 deletions

View file

@ -23,9 +23,14 @@ class ProfileController extends Controller
public function profile(Request $request, Response $response) public function profile(Request $request, Response $response)
{ {
global $container;
$username = $_SESSION['auth_username']; $username = $_SESSION['auth_username'];
$email = $_SESSION['auth_email']; $email = $_SESSION['auth_email'];
$userId = $_SESSION['auth_user_id'];
$status = $_SESSION['auth_status']; $status = $_SESSION['auth_status'];
$db = $container->get('db');
$tfa = new \RobThree\Auth\TwoFactorAuth('Namingo'); $tfa = new \RobThree\Auth\TwoFactorAuth('Namingo');
$secret = $tfa->createSecret(); $secret = $tfa->createSecret();
$qrcodeDataUri = $tfa->getQRCodeImageAsDataUri($email, $secret); $qrcodeDataUri = $tfa->getQRCodeImageAsDataUri($email, $secret);
@ -42,15 +47,77 @@ class ProfileController extends Controller
$role = "Unknown"; $role = "Unknown";
} }
global $container;
$csrfName = $container->get('csrf')->getTokenName(); $csrfName = $container->get('csrf')->getTokenName();
$csrfValue = $container->get('csrf')->getTokenValue(); $csrfValue = $container->get('csrf')->getTokenValue();
return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'qrcodeDataUri' => $qrcodeDataUri, 'secret' => $secret, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]); $_SESSION['2fa_secret'] = $secret;
$is_2fa_activated = $db->selectValue(
'SELECT tfa_enabled FROM users WHERE id = ? LIMIT 1',
[$userId]
);
if ($is_2fa_activated) {
return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]);
} else {
return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'qrcodeDataUri' => $qrcodeDataUri, 'secret' => $secret, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]);
}
}
public function activate2fa(Request $request, Response $response)
{
global $container;
if ($request->getMethod() === 'POST') {
// Retrieve POST data
$data = $request->getParsedBody();
$db = $container->get('db');
$verificationCode = $data['verificationCode'] ?? null;
$userId = $_SESSION['auth_user_id'];
$secret = $_SESSION['2fa_secret'];
$csrfName = $container->get('csrf')->getTokenName();
$csrfValue = $container->get('csrf')->getTokenValue();
$username = $_SESSION['auth_username'];
$email = $_SESSION['auth_email'];
$status = $_SESSION['auth_status'];
if ($status == 0) {
$status = "Confirmed";
} else {
$status = "Unknown";
}
$roles = $_SESSION['auth_roles'];
if ($roles == 0) {
$role = "Admin";
} else {
$role = "Unknown";
}
try {
$db->update(
'users',
[
'tfa_secret' => $secret,
'tfa_enabled' => 1,
'auth_method' => '2fa',
'backup_codes' => null
],
[
'id' => $userId
]
);
} catch (Exception $e) {
return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]);
}
return view($response,'admin/profile/profile.twig',['email' => $email, 'username' => $username, 'status' => $status, 'role' => $role, 'csrf_name' => $csrfName, 'csrf_value' => $csrfValue]);
}
} }
public function getRegistrationChallenge(Request $request, Response $response) public function getRegistrationChallenge(Request $request, Response $response)
{ {
global $container;
$userName = $_SESSION['auth_username']; $userName = $_SESSION['auth_username'];
$userEmail = $_SESSION['auth_email']; $userEmail = $_SESSION['auth_email'];
$userId = $_SESSION['auth_user_id']; $userId = $_SESSION['auth_user_id'];
@ -86,6 +153,7 @@ class ProfileController extends Controller
public function verifyRegistration(Request $request, Response $response) public function verifyRegistration(Request $request, Response $response)
{ {
global $container;
$data = json_decode($request->getBody()->getContents()); $data = json_decode($request->getBody()->getContents());
try { try {
@ -100,7 +168,7 @@ class ProfileController extends Controller
$credential = $this->webAuthn->processCreate($clientDataJSON, $attestationObject, $challenge, true, true, false); $credential = $this->webAuthn->processCreate($clientDataJSON, $attestationObject, $challenge, true, true, false);
// Store the credential data in the database // Store the credential data in the database
$db = $this->container->get('db'); $db = $container->get('db');
$db->insert( $db->insert(
'users_webauthn', 'users_webauthn',
[ [

View file

@ -97,6 +97,9 @@
<div class="tab-pane" id="tabs-2fa"> <div class="tab-pane" id="tabs-2fa">
<h4 class="card-title">Two-Factor Authentication (2FA)</h4> <h4 class="card-title">Two-Factor Authentication (2FA)</h4>
<div class="card"> <div class="card">
{% if secret is defined %}
<form action="{{route('activate2fa')}}" name="2fa" method="post">
{{ csrf.field | raw }}
<div class="card-body"> <div class="card-body">
<p>Set up 2FA for additional security. Scan the QR code with your authentication app and enter the provided code below to verify.</p> <p>Set up 2FA for additional security. Scan the QR code with your authentication app and enter the provided code below to verify.</p>
<!-- QR Code Placeholder --> <!-- QR Code Placeholder -->
@ -114,14 +117,20 @@
<!-- Verification Code Input --> <!-- Verification Code Input -->
<div class="mb-3"> <div class="mb-3">
<label for="verificationCode" class="form-label">Verification Code</label> <label for="verificationCode" class="form-label">Verification Code</label>
<input type="text" class="form-control" id="verificationCode" placeholder="Enter code"> <input type="text" class="form-control" id="verificationCode" name="verificationCode" placeholder="Enter code">
<small class="form-text text-muted"> <small class="form-text text-muted">
Enter the code generated by your authentication app. This code verifies that your 2FA setup is working correctly. Once entered, click 'Save 2FA Settings' to activate two-factor authentication for your account. Enter the code generated by your authentication app. This code verifies that your 2FA setup is working correctly. Once entered, click 'Save 2FA Settings' to activate two-factor authentication for your account.
</small> </small>
</div> </div>
<!-- Save Button --> <!-- Save Button -->
<button type="button" class="btn btn-primary">Save 2FA Settings</button> <button type="submit" class="btn btn-primary">Save 2FA Settings</button>
</div> </div>
</form>
{% else %}
<div class="card-body">
<p>2FA active</p>
</div>
{% endif %}
</div> </div>
</div> </div>
<div class="tab-pane" id="tabs-webauthn"> <div class="tab-pane" id="tabs-webauthn">

View file

@ -83,6 +83,7 @@ $app->group('', function ($route) {
$route->get('/support/media', SupportController::class .':mediakit')->setName('mediakit'); $route->get('/support/media', SupportController::class .':mediakit')->setName('mediakit');
$route->get('/profile', ProfileController::class .':profile')->setName('profile'); $route->get('/profile', ProfileController::class .':profile')->setName('profile');
$route->post('/profile/2fa', ProfileController::class .':activate2fa')->setName('activate2fa');
$route->get('/webauthn/register/challenge', ProfileController::class . ':getRegistrationChallenge')->setName('webauthn.register.challenge'); $route->get('/webauthn/register/challenge', ProfileController::class . ':getRegistrationChallenge')->setName('webauthn.register.challenge');
$route->post('/webauthn/register/verify', ProfileController::class . ':verifyRegistration')->setName('webauthn.register.verify'); $route->post('/webauthn/register/verify', ProfileController::class . ':verifyRegistration')->setName('webauthn.register.verify');