50 lines
1.1 KiB
PHP
50 lines
1.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace App\Libraries;
|
||
|
|
|
||
|
|
use Config\Auth as AuthConfig;
|
||
|
|
use RobThree\Auth\Providers\Qr\QRServerProvider;
|
||
|
|
use RobThree\Auth\TwoFactorAuth;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* TOTP 생성·검증·QR (robthree/twofactorauth)
|
||
|
|
*/
|
||
|
|
class TotpService
|
||
|
|
{
|
||
|
|
private TwoFactorAuth $tfa;
|
||
|
|
|
||
|
|
public function __construct(?AuthConfig $authConfig = null)
|
||
|
|
{
|
||
|
|
$authConfig ??= config('Auth');
|
||
|
|
$this->tfa = new TwoFactorAuth(
|
||
|
|
new QRServerProvider(),
|
||
|
|
$authConfig->totpIssuer,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function createSecret(): string
|
||
|
|
{
|
||
|
|
return $this->tfa->createSecret();
|
||
|
|
}
|
||
|
|
|
||
|
|
public function verify(string $plainSecret, string $code): bool
|
||
|
|
{
|
||
|
|
$code = preg_replace('/\s+/', '', $code) ?? '';
|
||
|
|
if (strlen($code) !== 6 || ! ctype_digit($code)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this->tfa->verifyCode($plainSecret, $code);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* PNG data URI (외부 QR API 호출 — 네트워크 필요)
|
||
|
|
*/
|
||
|
|
public function getQrDataUri(string $accountLabel, string $secret): string
|
||
|
|
{
|
||
|
|
return $this->tfa->getQRCodeImageAsDataUri($accountLabel, $secret);
|
||
|
|
}
|
||
|
|
}
|