Backup Codes
Prerequisites
To make use of this feature, you have to install scheb/2fa-backup-code
.
1
composer require scheb/2fa-backup-code
What it does
Backup codes are one-time authentication codes, which can be used instead of the actual codes. They're meant as emergency codes, when the authentication device is not available, and you have to pass the two-factor authentication process.
Enable the feature in the configuration:
1 2 3 4
# config/packages/scheb_2fa.yaml
scheb_two_factor:
backup_codes:
enabled: true # If the backup code feature should be enabled
Backup codes have to be provided from the user object. The user entity has to implement
Scheb\TwoFactorBundle\Model\BackupCodeInterface
. Here's an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
<?php
namespace Acme\Demo\Entity;
use Doctrine\ORM\Mapping as ORM;
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
class User implements BackupCodeInterface
{
/**
* @ORM\Column(type="json")
*/
private array $backupCodes = [];
// [...]
/**
* Check if it is a valid backup code.
*/
public function isBackupCode(string $code): bool
{
return in_array($code, $this->backupCodes);
}
/**
* Invalidate a backup code
*/
public function invalidateBackupCode(string $code): void
{
$key = array_search($code, $this->backupCodes);
if ($key !== false){
unset($this->backupCodes[$key]);
}
}
/**
* Add a backup code
*/
public function addBackUpCode(string $backUpCode): void
{
if (!in_array($backUpCode, $this->backupCodes)) {
$this->backupCodes[] = $backUpCode;
}
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
<?php
namespace Acme\Demo\Entity;
use Doctrine\ORM\Mapping as ORM;
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
class User implements BackupCodeInterface
{
#[ORM\Column(type: 'json')]
private array $backupCodes = [];
// [...]
/**
* Check if it is a valid backup code.
*/
public function isBackupCode(string $code): bool
{
return in_array($code, $this->backupCodes);
}
/**
* Invalidate a backup code
*/
public function invalidateBackupCode(string $code): void
{
$key = array_search($code, $this->backupCodes);
if ($key !== false){
unset($this->backupCodes[$key]);
}
}
/**
* Add a backup code
*/
public function addBackUpCode(string $backUpCode): void
{
if (!in_array($backUpCode, $this->backupCodes)) {
$this->backupCodes[] = $backUpCode;
}
}
}
The example assumes that there are already codes generated for that user. In addition to this, you should implement the backup code (re-)generation as you prefer.
Custom backup code manager
If you don't like the way this is implemented, you can also have your own backup code manager. Create a service
implementing Scheb
and register it in the
configuration:
1 2 3 4
# config/packages/scheb_2fa.yaml
scheb_two_factor:
backup_codes:
manager: acme.custom_backup_code_manager # Use a custom backup code manager