mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-27 12:18:54 +02:00
Use jbtronics/2fa-webauthn for u2f two factor authentication
This commit is contained in:
parent
03aaff3c79
commit
068daeda75
18 changed files with 1389 additions and 604 deletions
41
src/Controller/WebauthnKeyRegistrationController.php
Normal file
41
src/Controller/WebauthnKeyRegistrationController.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Jbtronics\TFAWebauthn\Services\TFAWebauthnRegistrationHelper;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class WebauthnKeyRegistrationController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route("/webauthn/register", name="webauthn_register")
|
||||
*/
|
||||
public function register(Request $request, TFAWebauthnRegistrationHelper $registrationHelper)
|
||||
{
|
||||
|
||||
//If form was submitted, check the auth response
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$webauthnResponse = $request->request->get('_auth_code');
|
||||
|
||||
//Retrieve other data from the form, that you want to store with the key
|
||||
$keyName = $request->request->get('keyName');
|
||||
|
||||
//Check the response
|
||||
$new_key = $registrationHelper->checkRegistrationResponse($webauthnResponse);
|
||||
|
||||
dump($new_key);
|
||||
|
||||
$this->addFlash('success', 'Key registered successfully');
|
||||
}
|
||||
|
||||
|
||||
return $this->render(
|
||||
'Security/U2F/u2f_register.html.twig',
|
||||
[
|
||||
'registrationRequest' => $registrationHelper->generateRegistrationRequestAsJSON(),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -44,8 +44,7 @@ namespace App\Entity\UserSystem;
|
|||
|
||||
use App\Entity\Base\TimestampTrait;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use R\U2FTwoFactorBundle\Model\U2F\TwoFactorKeyInterface;
|
||||
use u2flib_server\Registration;
|
||||
use Jbtronics\TFAWebauthn\Model\LegacyU2FKeyInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
|
@ -56,7 +55,7 @@ use u2flib_server\Registration;
|
|||
* })
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
*/
|
||||
class U2FKey implements TwoFactorKeyInterface
|
||||
class U2FKey implements LegacyU2FKeyInterface
|
||||
{
|
||||
use TimestampTrait;
|
||||
|
||||
|
@ -110,14 +109,6 @@ class U2FKey implements TwoFactorKeyInterface
|
|||
**/
|
||||
protected ?User $user = null;
|
||||
|
||||
public function fromRegistrationData(Registration $data): void
|
||||
{
|
||||
$this->keyHandle = $data->keyHandle;
|
||||
$this->publicKey = $data->publicKey;
|
||||
$this->certificate = $data->certificate;
|
||||
$this->counter = $data->counter;
|
||||
}
|
||||
|
||||
public function getKeyHandle(): string
|
||||
{
|
||||
return $this->keyHandle;
|
||||
|
|
|
@ -58,6 +58,7 @@ use App\Security\Interfaces\HasPermissionsInterface;
|
|||
use App\Validator\Constraints\Selectable;
|
||||
use App\Validator\Constraints\ValidPermission;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Webauthn\PublicKeyCredentialUserEntity;
|
||||
use function count;
|
||||
use DateTime;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
@ -65,8 +66,6 @@ use Doctrine\Common\Collections\Collection;
|
|||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Exception;
|
||||
use function in_array;
|
||||
use R\U2FTwoFactorBundle\Model\U2F\TwoFactorInterface as U2FTwoFactorInterface;
|
||||
use R\U2FTwoFactorBundle\Model\U2F\TwoFactorKeyInterface;
|
||||
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
|
||||
use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface;
|
||||
use Scheb\TwoFactorBundle\Model\PreferredProviderInterface;
|
||||
|
@ -74,6 +73,7 @@ use Scheb\TwoFactorBundle\Model\TrustedDeviceInterface;
|
|||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface;
|
||||
|
||||
/**
|
||||
* This entity represents a user, which can log in and have permissions.
|
||||
|
@ -86,7 +86,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
* @ORM\EntityListeners({"App\EntityListeners\TreeCacheInvalidationListener"})
|
||||
* @UniqueEntity("name", message="validator.user.username_already_used")
|
||||
*/
|
||||
class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface, BackupCodeInterface, TrustedDeviceInterface, U2FTwoFactorInterface, PreferredProviderInterface, PasswordAuthenticatedUserInterface
|
||||
class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface, BackupCodeInterface, TrustedDeviceInterface, WebauthnTwoFactorInterface, PreferredProviderInterface, PasswordAuthenticatedUserInterface
|
||||
{
|
||||
//use MasterAttachmentTrait;
|
||||
|
||||
|
@ -838,48 +838,38 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe
|
|||
++$this->trustedDeviceCookieVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if U2F is enabled.
|
||||
*/
|
||||
public function isU2FAuthEnabled(): bool
|
||||
{
|
||||
return count($this->u2fKeys) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all U2F Keys that are associated with this user.
|
||||
*
|
||||
* @psalm-return Collection<int, TwoFactorKeyInterface>
|
||||
*/
|
||||
public function getU2FKeys(): Collection
|
||||
{
|
||||
return $this->u2fKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a U2F key to this user.
|
||||
*/
|
||||
public function addU2FKey(TwoFactorKeyInterface $key): void
|
||||
{
|
||||
$this->u2fKeys->add($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a U2F key from this user.
|
||||
*/
|
||||
public function removeU2FKey(TwoFactorKeyInterface $key): void
|
||||
{
|
||||
$this->u2fKeys->removeElement($key);
|
||||
}
|
||||
|
||||
public function getPreferredTwoFactorProvider(): ?string
|
||||
{
|
||||
//If U2F is available then prefer it
|
||||
if ($this->isU2FAuthEnabled()) {
|
||||
return 'u2f_two_factor';
|
||||
}
|
||||
//if ($this->isU2FAuthEnabled()) {
|
||||
// return 'u2f_two_factor';
|
||||
//}
|
||||
|
||||
//Otherwise use other methods
|
||||
return null;
|
||||
}
|
||||
|
||||
public function isWebAuthnAuthenticatorEnabled(): bool
|
||||
{
|
||||
return count($this->u2fKeys) > 0;
|
||||
}
|
||||
|
||||
public function getLegacyU2FKeys(): iterable
|
||||
{
|
||||
return $this->u2fKeys;
|
||||
}
|
||||
|
||||
public function getWebAuthnUser(): PublicKeyCredentialUserEntity
|
||||
{
|
||||
return new PublicKeyCredentialUserEntity(
|
||||
$this->getUsername(),
|
||||
(string) $this->getId(),
|
||||
$this->getFullName(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getWebauthnKeys(): iterable
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ final class PasswordChangeNeededSubscriber implements EventSubscriberInterface
|
|||
*/
|
||||
public static function TFARedirectNeeded(User $user): bool
|
||||
{
|
||||
$tfa_enabled = $user->isU2FAuthEnabled() || $user->isGoogleAuthenticatorEnabled();
|
||||
$tfa_enabled = $user->isWebAuthnAuthenticatorEnabled() || $user->isGoogleAuthenticatorEnabled();
|
||||
|
||||
return null !== $user->getGroup() && $user->getGroup()->isEnforce2FA() && !$tfa_enabled;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue