twoFa = new Auth('Grav', 6, 30, 'sha1', new BaconQrProvider); } /** * @return Auth */ public function get2FA() { return $this->twoFa; } /** * @param int $bits * @return string * @throws TwoFactorAuthException */ public function createSecret($bits = 160) { return $this->twoFa->createSecret($bits); } /** * @param string $secret * @param string $code * @return bool */ public function verifyCode($secret, $code) { if (!$secret || !$code) { return false; } $secret = str_replace(' ', '', $secret); return $this->twoFa->verifyCode($secret, $code); } /** * @param string $username * @param string $secret * @return string * @throws TwoFactorAuthException */ public function getQrImageData($username, $secret) { $label = $username . ':' . Grav::instance()['config']->get('site.title'); $secret = str_replace(' ', '', $secret); return $this->twoFa->getQRCodeImageAsDataUri($label, $secret); } /** * @param string $yubikey_id * @param string $otp * @return bool */ public function verifyYubikeyOTP(string $yubikey_id, string $otp): bool { // Quick sanity check if (!$yubikey_id || !$otp || !Utils::startsWith($otp, $yubikey_id)) { return false; } $api_url = "https://api.yubico.com/wsapi/2.0/verify?id=1&otp=%s&nonce=%s"; $client = Client::getClient(); $url = sprintf($api_url, $otp, Utils::getNonce('yubikey')); try { $response = $client->request('GET', $url); if ($response->getStatusCode() === 200) { $content = $response->getContent(); if (Utils::contains($content, 'status=OK')) { return true; } } } catch (TransportExceptionInterface|ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) { return false; } return false; } }