From 8e528d3b5eefde7742418faeaf9adc5a5346f1ff Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 11 Jan 2022 12:02:16 -0700 Subject: [PATCH 1/3] Support for `YubiKey OTP` 2-Factor authenticator --- CHANGELOG.md | 6 ++++ classes/TwoFactorAuth/TwoFactorAuth.php | 37 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 512475a..a1b475d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v3.6.2 +## mm/dd/2022 + +1. [](#new) + * Support for `YubiKey OTP` 2-Factor authenticator + # v3.6.1 ## 01/03/2022 diff --git a/classes/TwoFactorAuth/TwoFactorAuth.php b/classes/TwoFactorAuth/TwoFactorAuth.php index 091480e..5206daa 100644 --- a/classes/TwoFactorAuth/TwoFactorAuth.php +++ b/classes/TwoFactorAuth/TwoFactorAuth.php @@ -10,8 +10,14 @@ namespace Grav\Plugin\Login\TwoFactorAuth; use Grav\Common\Grav; +use Grav\Common\HTTP\Client; +use Grav\Common\Utils; use RobThree\Auth\TwoFactorAuth as Auth; use RobThree\Auth\TwoFactorAuthException; +use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; /** * Class TwoFactorAuth @@ -73,4 +79,35 @@ public function getQrImageData($username, $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 (null === $yubikey_id || null === $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; + } } From 1f7da3722b1014a153013fdc682a0d5365d0bee6 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 12 Jan 2022 10:54:39 +0200 Subject: [PATCH 2/3] Minor fix for OTP code --- classes/TwoFactorAuth/TwoFactorAuth.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/classes/TwoFactorAuth/TwoFactorAuth.php b/classes/TwoFactorAuth/TwoFactorAuth.php index 5206daa..ee29292 100644 --- a/classes/TwoFactorAuth/TwoFactorAuth.php +++ b/classes/TwoFactorAuth/TwoFactorAuth.php @@ -61,6 +61,10 @@ public function createSecret($bits = 160) */ public function verifyCode($secret, $code) { + if (!$secret || !$code) { + return false; + } + $secret = str_replace(' ', '', $secret); return $this->twoFa->verifyCode($secret, $code); @@ -88,9 +92,10 @@ public function getQrImageData($username, $secret) public function verifyYubikeyOTP(string $yubikey_id, string $otp): bool { // Quick sanity check - if (null === $yubikey_id || null === $otp || !Utils::startsWith($otp, $yubikey_id)) { + 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(); From 8a30352d1885260bcea409c04be1423a9eb2a64f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 12 Jan 2022 11:24:32 -0700 Subject: [PATCH 3/3] prepare for release --- CHANGELOG.md | 3 ++- blueprints.yaml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1b475d..89b5630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # v3.6.2 -## mm/dd/2022 +## 01/12/2022 1. [](#new) * Support for `YubiKey OTP` 2-Factor authenticator + * Requires Grav `v1.7.27` # v3.6.1 ## 01/03/2022 diff --git a/blueprints.yaml b/blueprints.yaml index 174860a..c771ca5 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -1,7 +1,7 @@ name: Login slug: login type: plugin -version: 3.6.1 +version: 3.6.2 testing: false description: Enables user authentication and login screen. icon: sign-in @@ -15,7 +15,7 @@ bugs: https://github.com/getgrav/grav-plugin-login/issues license: MIT dependencies: - - { name: grav, version: '>=1.7.21' } + - { name: grav, version: '>=1.7.27' } - { name: form, version: '>=5.1.0' } - { name: email, version: '>=3.1.0' }