Google2FA es una implementación PHP del módulo de autenticación de dos factores de Google, que admite el algoritmo de contraseña de un solo uso basado en HMAC (HOTP) especificado en RFC 4226 y el algoritmo de contraseña de un solo uso basado en tiempo (TOTP) especificado en RFC 6238.
PHP | Google2FA |
---|---|
5.4 | 7.x LTS |
5.5 | 7.x LTS |
5.6 | 7.x LTS |
7.1 | 8.x |
7.2 | 8.x |
7.3 | 8.x |
7.4 | 8.x |
8,0 (β) | 8.x |
Este paquete es agnóstico, pero hay un puente Laravel.
Este paquete no genera códigos QR para 2FA.
Si está buscando la autenticación de dos factores de Google, pero también necesita generar un código QR, puede usar el paquete Google2FA QRCode, que integra este paquete y también genera códigos QR utilizando la biblioteca BaconQRCode, o consulte las opciones sobre cómo hacerlo usted mismo. aquí en los documentos.
Consulte el área de juegos del paquete Google2FA.
Aquí hay una aplicación de demostración que muestra cómo usar Google2FA: google2fa-example.
Puede escanear el código QR en esta (antigua) página de demostración con una aplicación Google Authenticator y ver el código cambiando (casi) en tiempo real.
Utilice Composer para instalarlo:
composer require pragmarx/google2fa
Para generar códigos QR en línea, necesitará instalar un generador de códigos QR, por ejemplo, BaconQrCode:
composer require bacon/bacon-qr-code
use PragmaRX Google2FA Google2FA ;
$ google2fa = new Google2FA ();
return $ google2fa -> generateSecretKey ();
Genera una clave secreta para tu usuario y guárdala:
$ user -> google2fa_secret = $ google2fa -> generateSecretKey ();
La forma más segura de crear QRCode es hacerlo usted mismo o utilizar una biblioteca. Primero debe instalar un generador de códigos QR, por ejemplo, BaconQrCode, como se indicó anteriormente, luego solo debe generar la URL del código QR usando:
$ qrCodeUrl = $ google2fa -> getQRCodeUrl (
$ companyName ,
$ companyEmail ,
$ secretKey
);
Una vez que tenga la URL del código QR, puede enviarla a su generador de códigos QR preferido.
// 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="">
Y para comprobarlo sólo tienes que:
$ secret = $ request -> input ( ' secret ' );
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret );
Este paquete sugiere el uso de Bacon/QRCode porque se lo conoce como un buen paquete de Código QR, pero puede usarlo con cualquier otro paquete, por ejemplo Google2FA QRCode, Simple QrCode o Endroid QR Code, todos usan Bacon/QRCode para producir códigos QR.
Por lo general, necesitarás una URL 2FA, por lo que solo tendrás que usar el generador de URL:
$ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )
Obtenga un código QR para utilizarlo en línea:
$ google2fa = ( new PragmaRX Google2FAQRCode Google2FA ());
$ inlineUrl = $ google2fa -> getQRCodeInline (
' Company Name ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
Y usa en tu plantilla:
<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>
Generar la URL de datos
$ qrCode = new Endroid QrCode QrCode ( $ value );
$ qrCode -> setSize ( 100 );
$ google2fa_url = $ qrCode -> writeDataUri ();
Y en tu vista
<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 ));
Y muéstralo como una imagen:
<img src="data:image/png;base64, <?php echo $ qrcode_image; ?> "/>
Para cumplir con RFC6238, este paquete admite SHA1, SHA256 y SHA512. El valor predeterminado es SHA1, por lo que para usar un algoritmo diferente solo tienes que usar el método setAlgorithm()
:
use PragmaRX Google2FA Support Constants ;
$ google2fa -> setAlgorithm ( Constants :: SHA512 );
Es muy importante que mantengas la hora de tu servidor sincronizada con algún servidor NTP; en Ubuntu puedes agregar esto al crontab:
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start
Para evitar problemas con relojes que están ligeramente desincronizados, no verificamos solo la clave actual, sino que también consideramos las claves $window
del pasado y del futuro. Puede pasar $window
como tercer parámetro opcional para verifyKey
, el valor predeterminado es 1
. Cuando se genera una nueva clave cada 30 segundos, con la configuración predeterminada, se considerarán las claves de un intervalo de 30 segundos anterior, actual y siguiente. Para el usuario con un reloj sincronizado correctamente, le parecerá que la clave es válida durante 60 segundos en lugar de 30, ya que el sistema la aceptará incluso cuando ya haya caducado durante, digamos, 29 segundos.
$ secret = $ request -> input ( ' secret ' );
$ window = 8 ; // 8 keys (respectively 4 minutes) past and future
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret , $ window );
Establecer el parámetro $window
en 0
también puede significar que el sistema no aceptará una clave que era válida cuando el usuario la vio en su generador, ya que normalmente el usuario tarda algún tiempo en ingresar la clave en el campo del formulario en particular.
Un atacante podría observar al usuario ingresando sus credenciales y su clave de uso único. Sin más precauciones, la clave sigue siendo válida hasta que ya no esté dentro de la ventana de tiempo del servidor. Para evitar el uso de una clave única que ya se ha utilizado, puede utilizar la función 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
}
Tenga en cuenta que $timestamp
es false
(si la clave no es válida o se ha utilizado antes) o es la marca de tiempo Unix de la clave proporcionada dividida por el período de regeneración de la clave de 30 segundos.
Aunque la probabilidad de colisión de una cadena aleatoria de 16 bytes (128 bits) es muy baja, puedes reforzarla de la siguiente manera:
$ secretKey = $ google2fa -> generateSecretKey ( 32 ); // defaults to 16 bytes
Puede prefijar sus claves secretas, pero debe comprender que, como su clave secreta debe tener una longitud en potencia de 2, su prefijo deberá tener un tamaño complementario. Entonces, si su clave tiene una longitud de 16 bytes, si agrega un prefijo, también debe tener una longitud de 16 bytes, pero como sus prefijos se convertirán a base 32, la longitud máxima de su prefijo es 10 bytes. Entonces, esos son los tamaños que puedes usar en tus prefijos:
1, 2, 5, 10, 20, 40, 80...
Y se puede utilizar así:
$ prefix = strpad ( $ userId , 10 , ' X ' );
$ secretKey = $ google2fa -> generateSecretKey ( 16 , $ prefix );
La propiedad Ventana define cuánto tiempo funcionará una OTP o cuántos ciclos durará. Una clave tiene un ciclo de 30 segundos, configurar la ventana en 0 hará que la clave dure esos 30 segundos, configurarla en 2 hará que dure 120 segundos. Así es como configuras la ventana:
$ secretKey = $ google2fa -> setWindow ( 4 );
Pero también puedes configurar la ventana mientras verificas la clave. Si necesita establecer una ventana de 4 durante la verificación de clave, así es como se hace:
$ isValid = $ google2fa -> verifyKey ( $ seed , $ key , 4 );
Puede cambiar el intervalo de regeneración de claves, que por defecto es 30 segundos, pero recuerde que este es un valor predeterminado en la mayoría de las aplicaciones de autenticación, como Google Authenticator, lo que, básicamente, hará que su aplicación no esté sincronizada con ellas.
$ google2fa -> setKeyRegeneration ( 40 );
Para ser compatible con Google Authenticator, la longitud de su clave secreta (convertida a base 32) debe tener al menos 8 caracteres y una potencia de 2: 8, 16, 32, 64...
Entonces, para evitar errores, puedes hacer algo como esto mientras lo generas:
$ secretKey = ' 123456789 ' ;
$ secretKey = str_pad ( $ secretKey , pow ( 2 , ceil ( log ( strlen ( $ secretKey ), 2 ))), ' X ' );
Y generará
123456789XXXXXXX
De forma predeterminada, este paquete exigirá la compatibilidad, pero, si Google Authenticator no es un objetivo, puede desactivarlo haciendo
$ google2fa -> setEnforceGoogleAuthenticatorCompatibility ( false );
Para utilizar la autenticación de dos factores, su usuario deberá instalar una aplicación compatible con Google Authenticator, estas son algunas de las disponibles actualmente:
La API de Google para el generador de QR está desactivada. Todas las versiones de ese paquete anteriores a la 5.0.0 están en desuso. Actualice y verifique la documentación sobre la generación de códigos QR.
Las pruebas del paquete fueron escritas con PHPUnit. Hay algunos scripts de Composer que le ayudarán a ejecutar pruebas y análisis:
Unidad PHP:
composer test
Análisis PHPStan:
composer analyse
Google2FA tiene la licencia MIT; consulte el archivo de LICENCIA para obtener más detalles.
Las solicitudes de extracción y los problemas son más que bienvenidos.
Ninguno.