Google2FA ist eine PHP-Implementierung des Google Two-Factor Authentication Module, die den in RFC 4226 spezifizierten HMAC-Based One-Time Password (HOTP)-Algorithmus und den in RFC 6238 spezifizierten Time-based One-time Password (TOTP)-Algorithmus unterstützt.
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 |
Dieses Paket ist agnostisch, es gibt jedoch eine Laravel-Brücke.
Dieses Paket generiert keine QRCodes für 2FA.
Wenn Sie nach der Zwei-Faktor-Authentifizierung von Google suchen, dafür aber auch QRCode generieren müssen, können Sie das Google2FA QRCode-Paket verwenden, das dieses Paket integriert und auch QRCodes mithilfe der BaconQRCode-Bibliothek generiert, oder Optionen prüfen, wie Sie dies selbst tun können hier in den Dokumenten.
Bitte überprüfen Sie den Google2FA-Paket-Playground.
Hier ist eine Demo-App, die zeigt, wie man Google2FA verwendet: google2fa-example.
Sie können den QR-Code auf dieser (alten) Demoseite mit einer Google Authenticator-App scannen und die Codeänderung (fast) in Echtzeit verfolgen.
Verwenden Sie Composer, um es zu installieren:
composer require pragmarx/google2fa
Um Inline-QRCodes zu generieren, müssen Sie einen QR-Code-Generator installieren, z. B. BaconQrCode:
composer require bacon/bacon-qr-code
use PragmaRX Google2FA Google2FA ;
$ google2fa = new Google2FA ();
return $ google2fa -> generateSecretKey ();
Generieren Sie einen geheimen Schlüssel für Ihren Benutzer und speichern Sie ihn:
$ user -> google2fa_secret = $ google2fa -> generateSecretKey ();
Die sicherere Möglichkeit, QRCode zu erstellen, besteht darin, es selbst zu erstellen oder eine Bibliothek zu verwenden. Zuerst müssen Sie einen QR-Code-Generator installieren, z. B. BaconQrCode, wie oben beschrieben, dann müssen Sie nur noch die QR-Code-URL generieren mit:
$ qrCodeUrl = $ google2fa -> getQRCodeUrl (
$ companyName ,
$ companyEmail ,
$ secretKey
);
Sobald Sie die QR-Code-URL haben, können Sie sie an Ihren bevorzugten QR-Code-Generator weiterleiten.
// 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="">
Und um dies zu überprüfen, müssen Sie nur Folgendes tun:
$ secret = $ request -> input ( ' secret ' );
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret );
Dieses Paket empfiehlt die Verwendung von Bacon/QRCode, da es als gutes QR-Code-Paket bekannt ist, Sie können es jedoch mit jedem anderen Paket verwenden, zum Beispiel Google2FA QRCode, Simple QrCode oder Endroid QR Code, die alle Bacon/QRCode verwenden QR-Codes erstellen.
Normalerweise benötigen Sie eine 2FA-URL, Sie müssen also nur den URL-Generator verwenden:
$ google2fa -> getQRCodeUrl ( $ companyName , $ companyEmail , $ secretKey )
Holen Sie sich einen QRCode zur Inline-Nutzung:
$ google2fa = ( new PragmaRX Google2FAQRCode Google2FA ());
$ inlineUrl = $ google2fa -> getQRCodeInline (
' Company Name ' ,
' [email protected] ' ,
$ google2fa -> generateSecretKey ()
);
Und verwenden Sie in Ihrer Vorlage:
<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>
Generieren Sie die Daten-URL
$ qrCode = new Endroid QrCode QrCode ( $ value );
$ qrCode -> setSize ( 100 );
$ google2fa_url = $ qrCode -> writeDataUri ();
Und aus Ihrer Sicht
<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 ));
Und zeige es als Bild:
<img src="data:image/png;base64, <?php echo $ qrcode_image; ?> "/>
Um RFC6238 zu entsprechen, unterstützt dieses Paket SHA1, SHA256 und SHA512. Der Standardwert ist SHA1. Um einen anderen Algorithmus zu verwenden, müssen Sie lediglich die Methode setAlgorithm()
verwenden:
use PragmaRX Google2FA Support Constants ;
$ google2fa -> setAlgorithm ( Constants :: SHA512 );
Es ist wirklich wichtig, dass Sie die Zeit Ihres Servers mit einem NTP-Server synchron halten. Unter Ubuntu können Sie Folgendes zur Crontab hinzufügen:
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start
Um Probleme mit leicht asynchronen Uhren zu vermeiden, überprüfen wir nicht nur den aktuellen Schlüssel, sondern berücksichtigen auch $window
-Schlüssel jeweils aus der Vergangenheit und der Zukunft. Sie können $window
als optionalen dritten Parameter an verifyKey
übergeben, der Standardwert ist 1
. Wenn alle 30 Sekunden ein neuer Schlüssel generiert wird, werden in der Standardeinstellung Schlüssel aus einem vorherigen, dem aktuellen und einem nächsten 30-Sekunden-Intervall berücksichtigt. Für den Benutzer mit ordnungsgemäß synchronisierter Uhr sieht es so aus, als ob der Schlüssel 60 statt 30 Sekunden gültig wäre, da das System ihn auch dann akzeptiert, wenn er bereits seit beispielsweise 29 Sekunden abgelaufen ist.
$ secret = $ request -> input ( ' secret ' );
$ window = 8 ; // 8 keys (respectively 4 minutes) past and future
$ valid = $ google2fa -> verifyKey ( $ user -> google2fa_secret , $ secret , $ window );
Das Setzen des Parameters $window
auf 0
kann auch bedeuten, dass das System einen Schlüssel nicht akzeptiert, der gültig war, als der Benutzer ihn in seinem Generator gesehen hat, da es normalerweise einige Zeit dauert, bis der Benutzer den Schlüssel in das bestimmte Formularfeld eingibt.
Ein Angreifer kann möglicherweise beobachten, wie der Benutzer seine Anmeldeinformationen und seinen Einmalschlüssel eingibt. Ohne weitere Vorkehrungen bleibt der Schlüssel solange gültig, bis er sich nicht mehr innerhalb des Zeitfensters des Servers befindet. Um die Verwendung eines bereits verwendeten Einmalschlüssels zu verhindern, können Sie die Funktion verifyKeyNewer
verwenden.
$ 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
}
Beachten Sie, dass $timestamp
entweder false
(wenn der Schlüssel ungültig ist oder bereits verwendet wurde) oder der Unix-Zeitstempel des bereitgestellten Schlüssels dividiert durch die Schlüsselregenerationsperiode von 30 Sekunden ist.
Obwohl die Wahrscheinlichkeit einer Kollision einer 16 Byte (128 Bit) großen Zufallszeichenfolge sehr gering ist, können Sie sie wie folgt absichern:
$ secretKey = $ google2fa -> generateSecretKey ( 32 ); // defaults to 16 bytes
Sie können Ihren geheimen Schlüsseln ein Präfix voranstellen, aber Sie müssen verstehen, dass Ihr Präfix eine komplementäre Größe haben muss, da Ihr geheimer Schlüssel eine Länge in Zweierpotenzen haben muss. Wenn Ihr Schlüssel also 16 Byte lang ist und Sie ein Präfix hinzufügen, muss dieses ebenfalls 16 Byte lang sein. Da Ihre Präfixe jedoch in die Basis 32 konvertiert werden, beträgt die maximale Länge Ihres Präfixes 10 Byte. Das sind also die Größen, die Sie in Ihren Präfixen verwenden können:
1, 2, 5, 10, 20, 40, 80...
Und es kann so verwendet werden:
$ prefix = strpad ( $ userId , 10 , ' X ' );
$ secretKey = $ google2fa -> generateSecretKey ( 16 , $ prefix );
Die Window-Eigenschaft definiert, wie lange ein OTP funktioniert oder wie viele Zyklen es dauern wird. Eine Taste hat einen 30-Sekunden-Zyklus. Wenn Sie das Fenster auf 0 setzen, hält die Taste diese 30 Sekunden lang an. Wenn Sie den Wert auf 2 setzen, dauert sie 120 Sekunden. So stellen Sie das Fenster ein:
$ secretKey = $ google2fa -> setWindow ( 4 );
Sie können das Fenster aber auch beim Prüfen des Schlüssels einstellen. Wenn Sie bei der Schlüsselüberprüfung ein Fenster von 4 festlegen müssen, gehen Sie folgendermaßen vor:
$ isValid = $ google2fa -> verifyKey ( $ seed , $ key , 4 );
Sie können das Schlüsselregenerationsintervall ändern, das standardmäßig 30 Sekunden beträgt. Beachten Sie jedoch, dass dies bei den meisten Authentifizierungs-Apps wie Google Authenticator ein Standardwert ist, der im Grunde dazu führt, dass Ihre App nicht mehr mit ihnen synchronisiert ist.
$ google2fa -> setKeyRegeneration ( 40 );
Um mit Google Authenticator kompatibel zu sein, muss Ihr (in Basis 32 umgewandelter) geheimer Schlüssel mindestens 8 Zeichen lang sein und eine Potenz von 2 sein: 8, 16, 32, 64 ...
Um Fehler zu vermeiden, können Sie beim Generieren Folgendes tun:
$ secretKey = ' 123456789 ' ;
$ secretKey = str_pad ( $ secretKey , pow ( 2 , ceil ( log ( strlen ( $ secretKey ), 2 ))), ' X ' );
Und es wird generieren
123456789XXXXXXX
Standardmäßig erzwingt dieses Paket die Kompatibilität. Wenn Google Authenticator jedoch kein Ziel ist, können Sie es auf diese Weise deaktivieren
$ google2fa -> setEnforceGoogleAuthenticatorCompatibility ( false );
Um die Zwei-Faktor-Authentifizierung nutzen zu können, muss Ihr Benutzer eine mit Google Authenticator kompatible App installieren. Dies sind einige der derzeit verfügbaren Apps:
Google API für QR-Generator ist deaktiviert. Alle Versionen dieses Pakets vor 5.0.0 sind veraltet. Bitte aktualisieren Sie die Dokumentation zur QRCode-Generierung und überprüfen Sie sie.
Die Pakettests wurden mit PHPUnit geschrieben. Es gibt einige Composer-Skripte, die Sie bei der Durchführung von Tests und Analysen unterstützen:
PHPUnit:
composer test
PHPStan-Analyse:
composer analyse
Google2FA ist unter der MIT-Lizenz lizenziert – Einzelheiten finden Sie in der LIZENZ-Datei.
Pull-Requests und Issues sind mehr als willkommen.
Keiner.