Google2FA — это PHP-реализация модуля двухфакторной аутентификации Google, поддерживающая алгоритм одноразового пароля на основе HMAC (HOTP), указанный в RFC 4226, и алгоритм одноразового пароля на основе времени (TOTP), указанный в RFC 6238.
PHP | Google2FA |
---|---|
5.4 | 7.х ЛТС |
5,5 | 7.х ЛТС |
5,6 | 7.х ЛТС |
7.1 | 8.х |
7.2 | 8.х |
7.3 | 8.х |
7.4 | 8.х |
8,0 (β) | 8.х |
Этот пакет независим, но есть мост Laravel.
Этот пакет не генерирует QRCоды для 2FA.
Если вы ищете двухфакторную аутентификацию Google, но вам также необходимо сгенерировать для нее QRCode, вы можете использовать пакет Google2FA QRCode, который интегрирует этот пакет, а также генерирует QRCodes с использованием библиотеки BaconQRCode, или проверьте варианты, как это сделать самостоятельно. здесь, в документах.
Пожалуйста, проверьте игровую площадку пакета Google2FA.
Вот демо-приложение, показывающее, как использовать Google2FA: google2fa-example.
Вы можете отсканировать QR-код на этой (старой) демонстрационной странице с помощью приложения Google Authenticator и просмотреть изменение кода (почти) в режиме реального времени.
Используйте Composer для его установки:
composer require pragmarx/google2fa
Чтобы генерировать встроенные QRCоды, вам необходимо установить генератор QR-кодов, например BaconQrCode:
composer require bacon/bacon-qr-code
use PragmaRX Google2FA Google2FA ;
$ google2fa = new Google2FA ();
return $ google2fa -> generateSecretKey ();
Создайте секретный ключ для вашего пользователя и сохраните его:
$ user -> google2fa_secret = $ google2fa -> generateSecretKey ();
Более безопасный способ создания QRCode — сделать это самостоятельно или использовать библиотеку. Сначала вам нужно установить генератор QR-кода, например BaconQrCode, как указано выше, затем вам просто нужно сгенерировать URL-адрес QR-кода, используя:
$ qrCodeUrl = $ google2fa -> getQRCodeUrl (
$ companyName ,
$ companyEmail ,
$ secretKey
);
Получив URL-адрес QR-кода, вы можете передать его в предпочитаемый вами генератор QR-кода.
// Use your own QR Code generator to generate a data URL:
$ google2fa_url = custom_generate_qrcode_url ( $ qrCodeUrl );
/// and in your view:
<img src="{{ $ google2fa_url }}" alt="">
И чтобы убедиться, вам просто нужно:
$ secret = $ request -> input ( ' secret ' );
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret );
Этот пакет предполагает использование Bacon/QRCode, поскольку он известен как хороший пакет QR-кода, но вы можете использовать его с любым другим пакетом, например Google2FA QRCode, Simple QrCode или Endroid QR Code, все они используют Bacon/QRCode для создавать QR-коды.
Обычно вам понадобится URL-адрес 2FA, поэтому вам просто нужно использовать генератор URL-адресов:
$ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )
Получите QRCode для использования внутри:
$ google2fa = ( new PragmaRX Google2FAQRCode Google2FA ());
$ inlineUrl = $ google2fa -> getQRCodeInline (
' Company Name ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
И используйте в своем шаблоне:
<img src="{{ $ inlineUrl }}">
<div class="visible-print text-center">
{!! QrCode :: size ( 100 )-> generate ( $ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )); !!}
<p> Scan me to return to the original page.</p>
</div>
Создайте URL-адрес данных
$ qrCode = new Endroid QrCode QrCode ( $ value );
$ qrCode -> setSize ( 100 );
$ google2fa_url = $ qrCode -> writeDataUri ();
И на ваш взгляд
<div class="visible-print text-center">
{!! $ google2fa_url !!}
<p> Scan me to return to the original page.</p>
</div>
<?php
use PragmaRX Google2FA Google2FA ;
use BaconQrCode Renderer ImageRenderer ;
use BaconQrCode Renderer Image ImagickImageBackEnd ;
use BaconQrCode Renderer RendererStyle RendererStyle ;
use BaconQrCode Writer ;
$ google2fa = app ( Google2FA ::class);
$ g2faUrl = $ google2fa -> getQRCodeUrl (
' pragmarx ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
$ writer = new Writer (
new ImageRenderer (
new RendererStyle ( 400 ),
new ImagickImageBackEnd ()
)
);
$ qrcode_image = base64_encode ( $ writer -> writeString ( $ g2faUrl ));
И покажите это как изображение:
<img src="data:image/png;base64, <?php echo $ qrcode_image; ?> "/>
В соответствии с RFC6238 этот пакет поддерживает SHA1, SHA256 и SHA512. По умолчанию используется SHA1, поэтому для использования другого алгоритма вам просто нужно использовать метод setAlgorithm()
:
use PragmaRX Google2FA Support Constants ;
$ google2fa -> setAlgorithm ( Constants :: SHA512 );
Очень важно синхронизировать время вашего сервера с каким-либо NTP-сервером. В Ubuntu вы можете добавить это в crontab:
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start
Чтобы избежать проблем с часами, которые немного не синхронизированы, мы не проверяем только текущий ключ, но также рассматриваем ключи $window
из прошлого и будущего. Вы можете передать $window
в качестве необязательного третьего параметра verifyKey
, по умолчанию он равен 1
. Если новый ключ генерируется каждые 30 секунд, то при настройке по умолчанию будут учитываться ключи из одного предыдущего, текущего и следующего 30-секундного интервала. Для пользователя с правильно синхронизированными часами это будет выглядеть так, как будто ключ действителен в течение 60 секунд вместо 30, поскольку система примет его, даже если срок его действия уже истек, скажем, 29 секунд.
$ secret = $ request -> input ( ' secret ' );
$ window = 8 ; // 8 keys (respectively 4 minutes) past and future
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret , $ window );
Установка параметра $window
в значение 0
также может означать, что система не примет ключ, который был действительным, когда пользователь видел его в своем генераторе, поскольку обычно пользователю требуется некоторое время для ввода ключа в определенное поле формы.
Злоумышленник может наблюдать за тем, как пользователь вводит свои учетные данные и одноразовый ключ. Без дополнительных мер предосторожности ключ остается действительным до тех пор, пока он не выйдет за пределы окна серверного времени. Чтобы предотвратить использование уже использованного одноразового ключа, вы можете использовать verifyKeyNewer
.
$ secret = $ request -> input ( ' secret ' );
$ timestamp = $ google2fa -> verifyKeyNewer ( $ user -> google2fa_secret , $ secret , $ user -> google2fa_ts );
if ( $ timestamp !== false ) {
$ user -> update ([ ' google2fa_ts ' => $ timestamp ]);
// successful
} else {
// failed
}
Обратите внимание, что $timestamp
имеет значение false
(если ключ недействителен или использовался ранее) или представляет собой временную метку предоставленного ключа unix, разделенную на период регенерации ключа, равный 30 секундам.
Хотя вероятность коллизии случайной строки длиной 16 байт (128 бит) очень мала, вы можете усилить ее следующим образом:
$ secretKey = $ google2fa -> generateSecretKey ( 32 ); // defaults to 16 bytes
Вы можете добавлять префикс к своим секретным ключам, но вы должны понимать, что, поскольку длина вашего секретного ключа должна быть равна степени 2, ваш префикс должен иметь дополнительный размер. Таким образом, если длина вашего ключа составляет 16 байт, то если вы добавите префикс, он также должен иметь длину 16 байт, но поскольку ваши префиксы будут преобразованы в базу 32, максимальная длина вашего префикса составит 10 байт. Итак, вот размеры, которые вы можете использовать в своих префиксах:
1, 2, 5, 10, 20, 40, 80...
И его можно использовать так:
$ prefix = strpad ( $ userId , 10 , ' X ' );
$ secretKey = $ google2fa -> generateSecretKey ( 16 , $ prefix );
Свойство Window определяет, как долго будет работать OTP или сколько циклов он будет длиться. Ключ имеет 30-секундный цикл: установка окна на 0 продлит срок действия ключа в течение этих 30 секунд, установка на 2 сделает его длительным в течение 120 секунд. Вот как вы устанавливаете окно:
$ secretKey = $ google2fa -> setWindow ( 4 );
Но вы также можете установить окно при проверке ключа. Если вам нужно установить окно 4 во время проверки ключа, сделайте следующее:
$ isValid = $ google2fa -> verifyKey ( $ seed , $ key , 4 );
Вы можете изменить интервал регенерации ключа, который по умолчанию составляет 30 секунд, но помните, что это значение по умолчанию для большинства приложений аутентификации, таких как Google Authenticator, что, по сути, приводит к тому, что ваше приложение с ними не синхронизируется.
$ google2fa -> setKeyRegeneration ( 40 );
Чтобы быть совместимым с Google Authenticator, длина вашего секретного ключа (преобразованного в базу 32) должна составлять не менее 8 символов и быть степенью 2: 8, 16, 32, 64...
Итак, чтобы предотвратить ошибки, вы можете сделать что-то вроде этого при его создании:
$ secretKey = ' 123456789 ' ;
$ secretKey = str_pad ( $ secretKey , pow ( 2 , ceil ( log ( strlen ( $ secretKey ), 2 ))), ' X ' );
И это будет генерировать
123456789XXXXXXX
По умолчанию этот пакет обеспечивает совместимость, но если Google Authenticator не является целью, вы можете отключить его, выполнив
$ google2fa -> setEnforceGoogleAuthenticatorCompatibility ( false );
Чтобы использовать двухфакторную аутентификацию, вашему пользователю необходимо установить приложение, совместимое с Google Authenticator, вот некоторые из доступных на данный момент:
Google API для генератора QR отключен. Все версии этого пакета до 5.0.0 устарели. Пожалуйста, обновите и проверьте документацию, касающуюся генерации QRCode.
Тесты пакета были написаны с использованием PHPUnit. Существует несколько скриптов Composer, которые помогут вам запускать тесты и анализ:
PHPUnit:
composer test
Анализ PHPStan:
composer analyse
Google2FA лицензируется по лицензии MIT — подробности см. в файле ЛИЦЕНЗИИ.
Запросы на включение и проблемы более чем приветствуются.
Никто.