Google2FA est une implémentation PHP du module d'authentification à deux facteurs de Google, prenant en charge l'algorithme de mot de passe à usage unique basé sur HMAC (HOTP) spécifié dans la RFC 4226 et l'algorithme de mot de passe à usage unique basé sur le temps (TOTP) spécifié dans la 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 |
Ce package est agnostique, mais il existe un pont Laravel.
Ce package ne génère pas de QRCodes pour 2FA.
Si vous recherchez l'authentification à deux facteurs Google, mais que vous devez également générer un QRCode, vous pouvez utiliser le package Google2FA QRCode, qui intègre ce package et génère également des QRCodes à l'aide de la bibliothèque BaconQRCode, ou vérifier les options pour le faire vous-même. ici dans la documentation.
Veuillez consulter le Google2FA Package Playground.
Voici une application de démonstration montrant comment utiliser Google2FA : google2fa-example.
Vous pouvez scanner le code QR sur cette (ancienne) page de démonstration avec une application Google Authenticator et voir l'évolution du code (presque) en temps réel.
Utilisez Composer pour l'installer :
composer require pragmarx/google2fa
Pour générer des QRCodes en ligne, vous devrez installer un générateur de code QR, par exemple BaconQrCode :
composer require bacon/bacon-qr-code
use PragmaRX Google2FA Google2FA ;
$ google2fa = new Google2FA ();
return $ google2fa -> generateSecretKey ();
Générez une clé secrète pour votre utilisateur et enregistrez-la :
$ user -> google2fa_secret = $ google2fa -> generateSecretKey ();
La manière la plus sûre de créer un QRCode est de le faire vous-même ou d'utiliser une bibliothèque. Vous devez d'abord installer un générateur de code QR par exemple BaconQrCode, comme indiqué ci-dessus, puis il vous suffit de générer l'url du code QR en utilisant :
$ qrCodeUrl = $ google2fa -> getQRCodeUrl (
$ companyName ,
$ companyEmail ,
$ secretKey
);
Une fois que vous avez l'URL du code QR, vous pouvez la transmettre à votre générateur de code QR préféré.
// 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="">
Et pour vérifier, il vous suffit de :
$ secret = $ request -> input ( ' secret ' );
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret );
Ce package suggère l'utilisation de Bacon/QRCode car il est connu comme un bon package QR Code, mais vous pouvez l'utiliser avec n'importe quel autre package, par exemple Google2FA QRCode, Simple QrCode ou Endroid QR Code, tous utilisent Bacon/QRCode pour produire des QR Codes.
Habituellement, vous aurez besoin d'une URL 2FA, il vous suffit donc d'utiliser le générateur d'URL :
$ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )
Obtenez un QRCode à utiliser en ligne :
$ google2fa = ( new PragmaRX Google2FAQRCode Google2FA ());
$ inlineUrl = $ google2fa -> getQRCodeInline (
' Company Name ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
Et utilisez dans votre modèle :
<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>
Générer l'URL des données
$ qrCode = new Endroid QrCode QrCode ( $ value );
$ qrCode -> setSize ( 100 );
$ google2fa_url = $ qrCode -> writeDataUri ();
Et à votre avis
<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 ));
Et montrez-le sous forme d'image :
<img src="data:image/png;base64, <?php echo $ qrcode_image; ?> "/>
Pour être conforme à la RFC6238, ce package prend en charge SHA1, SHA256 et SHA512. Sa valeur par défaut est SHA1, donc pour utiliser un algorithme différent, il vous suffit d'utiliser la méthode setAlgorithm()
:
use PragmaRX Google2FA Support Constants ;
$ google2fa -> setAlgorithm ( Constants :: SHA512 );
Il est très important que vous gardiez l'heure de votre serveur synchronisée avec celle d'un serveur NTP. Sur Ubuntu, vous pouvez ajouter ceci à la crontab :
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start
Pour éviter les problèmes avec des horloges légèrement désynchronisées, nous ne vérifions pas uniquement la clé actuelle, mais considérons également les clés $window
du passé et du futur. Vous pouvez transmettre $window
comme troisième paramètre facultatif à verifyKey
, la valeur par défaut est 1
. Lorsqu'une nouvelle clé est générée toutes les 30 secondes, alors avec le paramètre par défaut, les clés de l'intervalle de 30 secondes précédent, actuel et suivant seront prises en compte. Pour l'utilisateur dont l'horloge est correctement synchronisée, il semblera que la clé est valide pendant 60 secondes au lieu de 30, car le système l'acceptera même si elle a déjà expiré pendant, disons, 29 secondes.
$ secret = $ request -> input ( ' secret ' );
$ window = 8 ; // 8 keys (respectively 4 minutes) past and future
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret , $ window );
Définir le paramètre $window
sur 0
peut également signifier que le système n'acceptera pas une clé qui était valide lorsque l'utilisateur l'a vue dans son générateur, car il faut généralement un certain temps à l'utilisateur pour saisir la clé dans le champ de formulaire particulier.
Un attaquant pourrait être en mesure de regarder l'utilisateur saisir ses informations d'identification et sa clé unique. Sans autres précautions, la clé reste valide jusqu'à ce qu'elle ne soit plus dans la fenêtre horaire du serveur. Afin d'empêcher l'utilisation d'une clé unique qui a déjà été utilisée, vous pouvez utiliser la fonction 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
}
Notez que $timestamp
est soit false
(si la clé n'est pas valide ou a été utilisée auparavant), soit l'horodatage Unix de la clé fournie divisé par la période de régénération de la clé de 30 secondes.
Bien que la probabilité de collision d'une chaîne aléatoire de 16 octets (128 bits) soit très faible, vous pouvez la renforcer en :
$ secretKey = $ google2fa -> generateSecretKey ( 32 ); // defaults to 16 bytes
Vous pouvez préfixer vos clés secrètes, mais vous devez comprendre que, comme votre clé secrète doit avoir une longueur puissance 2, votre préfixe devra avoir une taille complémentaire. Donc, si votre clé fait 16 octets, si vous ajoutez un préfixe, il doit également faire 16 octets, mais comme vos préfixes seront convertis en base 32, la longueur maximale de votre préfixe est de 10 octets. Voici donc les tailles que vous pouvez utiliser dans vos préfixes :
1, 2, 5, 10, 20, 40, 80...
Et il peut être utilisé comme ceci :
$ prefix = strpad ( $ userId , 10 , ' X ' );
$ secretKey = $ google2fa -> generateSecretKey ( 16 , $ prefix );
La propriété Window définit la durée de fonctionnement d'un OTP ou le nombre de cycles qu'il durera. Une clé a un cycle de 30 secondes, régler la fenêtre sur 0 fera durer la clé pendant ces 30 secondes, la régler sur 2 la fera durer 120 secondes. Voici comment définir la fenêtre :
$ secretKey = $ google2fa -> setWindow ( 4 );
Mais vous pouvez également régler la fenêtre tout en vérifiant la clé. Si vous devez définir une fenêtre de 4 lors de la vérification des clés, voici comment procéder :
$ isValid = $ google2fa -> verifyKey ( $ seed , $ key , 4 );
Vous pouvez modifier l'intervalle de régénération des clés, qui est par défaut de 30 secondes, mais rappelez-vous qu'il s'agit d'une valeur par défaut sur la plupart des applications d'authentification, comme Google Authenticator, qui, en gros, désynchronisera votre application avec elles.
$ google2fa -> setKeyRegeneration ( 40 );
Pour être compatible avec Google Authenticator, la longueur de votre clé secrète (convertie en base 32) doit être d'au moins 8 caractères et être une puissance de 2 : 8, 16, 32, 64...
Ainsi, pour éviter les erreurs, vous pouvez faire quelque chose comme ceci lors de sa génération :
$ secretKey = ' 123456789 ' ;
$ secretKey = str_pad ( $ secretKey , pow ( 2 , ceil ( log ( strlen ( $ secretKey ), 2 ))), ' X ' );
Et cela générera
123456789XXXXXXX
Par défaut, ce package appliquera la compatibilité, mais si Google Authenticator n'est pas une cible, vous pouvez le désactiver en faisant
$ google2fa -> setEnforceGoogleAuthenticatorCompatibility ( false );
Pour utiliser l'authentification à deux facteurs, votre utilisateur devra installer une application compatible Google Authenticator, voici quelques-unes des applications actuellement disponibles :
L'API Google pour le générateur QR est désactivée. Toutes les versions de ce package antérieures à 5.0.0 sont obsolètes. Veuillez mettre à niveau et consulter la documentation concernant la génération de QRCode.
Les tests du package ont été écrits avec PHPUnit. Il existe quelques scripts Composer pour vous aider à exécuter des tests et des analyses :
Unité PHP :
composer test
Analyse PHPStan :
composer analyse
Google2FA est sous licence MIT - voir le fichier LICENSE pour plus de détails.
Les demandes de tirage et les problèmes sont plus que bienvenus.
Aucun.