
Teilen Sie:
Douglas is a full stack software engineer with a keen interest to marketing, customer growth and data analytics. When he’s not coding, he’s probably watching way too many TV shows.
Hinzufügen einer 2-Faktor-Authentifizierung zu WordPress mit Nexmo Verify API
Lesedauer: 8 Minuten
Einführung
Angesichts zunehmender Sicherheitsverletzungen war der Schutz Ihrer Website und ihrer Nutzer noch nie so wichtig wie heute. In diesem Tutorial werden Sie die 2FA (Zwei-Faktor-Authentifizierung) auf WordPress mit der Nexmo Verify API einrichten. Wenn ein Benutzer versucht, sich einzuloggen, erhält er eine SMS oder einen Anruf auf die in seinem Profil registrierte Handynummer mit einem eindeutigen Code, und wenn er den gültigen Code eingibt, wird er eingeloggt.
Am Ende dieses Tutorials werden Sie die Grundlagen der Erstellung eines WordPress-Plugins kennengelernt haben und wissen, wie Sie die Nexmo-API mit WordPress unter Verwendung der Nexmo-PHP-Bibliothek integrieren können. Also lasst uns anfangen!
Über die Nexmo Verify API
Die Verify API ist Nexmos Plug-and-Play-Lösung für die Zwei-Faktor-Authentifizierung auf jedem System. Der Prozess ist einfach: Sie rufen die Verifizierung senden Endpunkt unter Angabe einer Handynummer auf, Nexmo sendet der Handynummer einen eindeutigen Code per SMS/Anruf und gibt eine Anfrage-ID zurück. Mit dem Code des Benutzers rufen Sie den Verifizierung prüfen Endpunkt zusammen mit der Request ID auf, um den Code zu verifizieren, und Nexmo gibt einen Status zurück, je nachdem ob der Code gültig ist oder nicht. Ziemlich einfach, oder?
Ich mag Nexmo Verify besonders wegen der sogenannten Workflows. Mit Workflows können Sie mehrere Rückfalloptionen einrichten, falls ein Benutzer den Code nicht rechtzeitig per SMS erhält. Sie können eine Fallback-Option für einen Sprachanruf nach einer bestimmten Dauer einrichten und vieles mehr, Sie können über Workflows lesen hier.
Was Sie für den Einstieg brauchen:
Selbstgehostet WordPress Website
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
Ihr WordPress-Plugin erstellen
Sie können zwar ein WordPress-Plugin erstellen, indem Sie einfach einen neuen Ordner im WordPress-Plugin-Ordner hinzufügen, aber eine wirklich effiziente Methode ist die Verwendung einer leichtgewichtigen Boilerplate, um loszulegen. Boilerplates sind hilfreich, um alle Dateien und Klassen auf eine standardisierte Weise einzurichten. In diesem Tutorial werden Sie die wppb Boilerplate; geben Sie einfach die Details auf der Website ein und klicken Sie auf die Schaltfläche build plugin, um Ihr Plugin-Boilerplate herunterzuladen.
Wordpress Plugin Boilerplate Generator
Entpacken Sie anschließend die Zip-Datei und legen Sie sie in Ihrem WordPress-Plugin-Ordner ab. Gehen Sie dann zu Ihrem WordPress-Admin, navigieren Sie zur Seite "Installierte Plugins" und aktivieren Sie Ihr Plugin.
Plugins
Anwendergeschichten
Mit unserem Ziel, 2FA auf WordPress einzurichten, wollen wir die Idee in umsetzbare Anwendergeschichten/Schritte aufteilen und sie von oben nach unten implementieren:
In den Einstellungen des WordPress-Benutzerprofils benötigen Sie benutzerdefinierte Felder für die 2FA-Handynummer des Benutzers und für die Angabe, ob er für 2FA aktiviert ist
Sie senden einen Code an die Handynummer des Nutzers, wenn dieser sich anmeldet
Sie werden ein Formular haben, in das der Benutzer den erhaltenen Code eingeben und verifizieren kann
Verstehen von WordPress-Aktionen und -Filtern
Die meisten Änderungen, die Sie in WordPress vornehmen werden, haben mit der Verknüpfung Ihrer Funktionen mit bestehenden WordPress-Aktionen und -Filtern zu tun; Aktionen sind Funktionen, die ausgeführt werden, wenn ein bestimmtes Ereignis in WordPress eintritt. Wenn Sie also möchten, dass Ihre Funktion ausgeführt wird, wenn ein bestimmtes Ereignis eintritt, z. B. wenn sich ein Benutzer anmeldet, verknüpfen Sie Ihre Funktion mit der Login-bezogenen Aktion. Am anderen Ende, Filter bestimmte Funktionen verändern; Sie können einen Filter verwenden, um das Ergebnis einer Funktion zu manipulieren.
Sie koppeln Ihre Funktion an eine bestehende Aktion wie diese:
add_action( 'action_name', 'name_of_your_function' );
Sie verbinden Ihre Funktion mit einem Filter wie diesem:
add_filter( 'filter_name', 'name_of_your_function' );
Benutzerdefinierte Felder
Um diesen Beitrag kurz zu halten, hier der Link zu dem Code, der die Felder für die Handynummer und das Kontrollkästchen "2FA aktiviert" zu den WordPress-Benutzerprofileinstellungen hinzufügt. Mit dieser Einrichtung würde Ihre Benutzereinstellungsseite wie folgt aussehen:
Nexmo 2FA
Hinzufügen der Nexmo PHP-Bibliothek zum Mix
Nexmo empfiehlt Ihnen die Installation der PHP-Bibliothek über den Composer zu installieren; Sie müssen den Composer auf Ihrem Server/lokalen System eingerichtet haben. Wenn Sie Composer noch nicht eingerichtet haben, finden Sie hier zwei von Nexmo empfohlene Anleitungen, die Ihnen helfen: GetComposer.org oder Scotch.io
Wenn Composer installiert ist, öffnen Sie Ihr Terminal, navigieren Sie zum Stammverzeichnis Ihres Plugins und führen Sie es aus:
Es wird ein neuer Ordner namens vendor der eine Reihe anderer Bibliotheken enthält, darunter auch die PHP-Bibliothek von Nexmo. Um die Bibliothek in Ihr Plugin einzubinden, fügen Sie einfach diese Zeile in die PHP-Stammdatei Ihres Plugins ein.
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
Initialisierung der Nexmo-Klasse
Bevor Sie einen Aufruf mit der Nexmo-PHP-Bibliothek tätigen können, müssen Sie die Nexmo-Klasse initialisieren und das Client-Objekt verwenden, um Ihre nachfolgenden Anfragen zu stellen.
$basic = new \Nexmo\Client\Credentials\Basic(NEXMO_API_KEY, NEXMO_API_SECRET);
$client = new \Nexmo\Client(new \Nexmo\Client\Credentials\Container($basic));Wenn Sie das Boilerplate verwenden, können Sie die folgenden Änderungen in der Datei öffentlichen Klassendatei in Ihrem Plugin /public Ordner. Sie werden die Nexmo-Bibliothek im Konstrukt initialisieren und das Client-Objekt als geschützte Variable festlegen, damit andere Methoden unserer öffentlichen Klasse darauf zugreifen können.
<?php
class Two_Factor_Auth_Nexmo_Public {
protected $nexmo_client;
public function __construct( $plugin_name, $version ) {
$this->nexmo_client = new Nexmo\Client(new Nexmo\Client\Credentials\Basic(TWO_FACTOR_AUTH_NEXMO_KEY, TWO_FACTOR_AUTH_NEXMO_SECRET));
}
} Versenden der Verifizierungsanfrage
Basierend auf unserer Benutzergeschichte wollen wir die Benutzeranmeldung abfangen, prüfen, ob der Benutzer für 2FA aktiviert ist, und wenn ja, eine Verifizierung senden Anfrage an die Handynummer. Um dies zu erreichen, werden Sie das Hooking der authenticate WordPress-Aktion einbinden, da dies die Aktion ist, die ausgelöst wird, wenn sich ein Benutzer erfolgreich anmeldet.
<?php
class Two_Factor_Auth_Nexmo_Public {
protected $nexmo_client;
public function __construct( $plugin_name, $version ) {
$this->nexmo_client = new Nexmo\Client(new Nexmo\Client\Credentials\Basic(TWO_FACTOR_AUTH_NEXMO_KEY, TWO_FACTOR_AUTH_NEXMO_SECRET));
add_action( 'authenticate', array( $this, 'intercept_login_with_two_factor_auth' ), 10, 3 );
}
public function intercept_login_with_two_factor_auth( $user, $username, $password ) {
$errors = array();
$redirect_to = isset( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : admin_url();
$remember_me = ( isset( $_POST['rememberme'] ) && $_POST['rememberme'] === 'forever' ) ? true : false;
$_user = get_user_by( 'login', $username );
if ( $_user ) {
$this->verify_user( $_user, $redirect_to, $remember_me );
}
return $user;
}Durch die Einbindung unserer Funktion in die authenticate Aktion einbinden, erhalten wir drei Variablen, mit denen wir arbeiten können: $user, $username, und $password, die $user Variable ist normalerweise null, aber das ist in Ordnung. Was Sie brauchen, ist die $usernameMit dieser können Sie die WordPress-Funktion aufrufen, um das Benutzerobjekt zu erhalten. Sie benötigen das Benutzerobjekt, um andere Eigenschaften des Benutzers zu erhalten, wie die Handynummer und ob er für 2FA aktiviert ist.
$_user = get_user_by( 'login', $username );// Function to get the user objectUm den Wert für die benutzerdefinierten Felder eines Benutzers zu erhalten, verwenden Sie die WordPress-Funktion get_user_metaund übergeben dabei die Benutzer-ID und den Namen des benutzerdefinierten Feldes. Wie im Code der Benutzerprofileinstellungen definiert, lauten die Namen der Felder two_factor_auth_nexmo_enabled und two_factor_auth_nexmo_mobile.
private function verify_user( $user, $redirect_to, $remember_me, $errors = array() ) {
$enabled_2fa = get_user_meta($user->ID, 'two_factor_auth_nexmo_enabled', true );
$mobile = get_user_meta($user->ID, 'two_factor_auth_nexmo_mobile', true );
if ( ! $mobile || ! $enabled_2fa) {
return;
}
try {
$verification = new \Nexmo\Verify\Verification($mobile, TWO_FACTOR_AUTH_NEXMO_SENDER_NAME);
$this->nexmo_client->verify()->start($verification);
}
catch(Exception $e) {
$errors = array( "Error sending verification request" );
}
$request_id = $verification->getRequestId();
update_user_meta( $user->ID, 'two_factor_auth_nexmo_request_id', $request_id);
wp_logout();
}Wenn alle erforderlichen Variablen gesetzt sind (Handynummer und 2FA für den Benutzer aktiviert), rufen Sie die Funktion auf, um eine Verifizierung senden Anfrage zu starten, Nexmo sendet dem Benutzer den eindeutigen Code und eine Anfrage-ID wird zurückgegeben. Es ist wichtig, die Anfrage-ID zu speichern, damit Sie sie verwenden können, um die Funktion Code validieren im nächsten Schritt aufzurufen. Ein einfacher Weg, dies zu tun, ist die Verwendung der WordPress update_user_meta Funktion mit dem Schlüsselbezeichner für die Variable (in unserem Fall two_factor_auth_nexmo_request_id) und die Variable $request_id.
Rufen Sie abschließend die logout Funktion auf. Sie fragen sich vielleicht, warum Sie das tun sollten? Sie tun dies, weil, wie eingangs erwähnt, die Authentifizierungsaktion ausgelöst wird, wenn sich der Benutzer erfolgreich angemeldet hat. In Wirklichkeit wird also der gesamte Code ausgeführt, wenn der Benutzer angemeldet ist, aber das ist nicht das, was Sie wollen - zumindest noch nicht. Sie möchten, dass der Benutzer erst nach der Validierung des Codes angemeldet wird. Melden Sie daher den Benutzer nach dem Senden des Codes ab, und das führt uns zu unserem letzten Schritt, der Validierung des Codes und der Anmeldung des Benutzers.
Validierung des Codes
Sie haben den Code im obigen Abschnitt an den Benutzer gesendet. Jetzt muss dem Benutzer nur noch ein Formular angezeigt werden, in das er den erhaltenen Code eingeben kann, und der Code muss mit seinem Profil abgeglichen werden, um ihn anzumelden.
Aufbauend auf der verify_user Funktion, die Sie zuvor erstellt haben, fügen Sie das Code-Validierungsformular hinzu.
private function verify_user( $user, $redirect_to, $remember_me, $errors = array() ) {
$enabled_2fa = get_user_meta($user->ID, 'two_factor_auth_nexmo_enabled', true );
$mobile = get_user_meta($user->ID, 'two_factor_auth_nexmo_mobile', true );
if ( ! $mobile || ! $enabled_2fa) {
return;
}
try {
$verification = new \Nexmo\Verify\Verification($mobile, TWO_FACTOR_AUTH_NEXMO_SENDER_NAME);
$this->nexmo_client->verify()->start($verification);
}
catch(Exception $e) {
$errors = array( "Error sending verification request" );
}
$request_id = $verification->getRequestId();
update_user_meta( $user->ID, 'two_factor_auth_nexmo_request_id', $request_id);
wp_logout();
nocache_headers();
header('Content-Type: ' . get_bloginfo( 'html_type' ) . '; charset=' . get_bloginfo( 'charset' ) );
login_header('Nexmo Two-Factor Authentication', '<p class="message">' . sprintf( 'Enter the PIN code sent to your mobile number ending in <strong>%1$s</strong>' , substr($mobile, -5) ) . '</p>');
if(!empty($errors)) {
?>
<div id="login_error"><?php echo implode( '<br />', $errors ) ?></div>
<?php } ?>
<form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ) ?>" method="post" autocomplete="off">
<p>
<label for="two_factor_auth_nexmo_pin_code">Code
<br />
<input type="number" name="two_factor_auth_nexmo_pin_code" id="two_factor_auth_nexmo_pin_code" class="input" value="" size="6" />
</label>
</p>
<p class="submit">
<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="Verify" />
<input type="hidden" name="log" value="<?php echo esc_attr( $user->user_login ) ?>" />
<input type="hidden" name="two_factor_auth_nexmo_request_id" value="<?php echo esc_attr( $request_id ) ?>" />
<input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ) ?>" />
<?php if ( $remember_me ) : ?>
<input type="hidden" name="rememberme" value="forever" />
<?php endif; ?>
</p>
</form>
<?php
login_footer( 'two_factor_auth_nexmo_pin_code' );
exit;
}NB: Ich habe mein HTML in der Class-Methode hier, aber Sie können Ihr HTML in einer separaten Datei speichern und einfügen.
Mit dem obigen Code sollten Sie eine Seite erhalten, die wie folgt aussieht, wenn Sie versuchen, sich bei einem für 2FA aktivierten Account anzumelden.
Wordpress Pin
Die Funktion login_header fügt den kleinen Abschnitt oberhalb des Formulars hinzu, der die letzten 5 Ziffern der Handynummer des Benutzers anzeigt.
Die <form> in dieser Ansicht ist eine Replik des WordPress-Anmeldeformulars mit nur ein paar Änderungen. Wenn Sie Ihr WordPress-Anmeldeformular über Ihren Browser untersuchen, werden Sie feststellen, dass das Eingabefeld für den Benutzernamen ein Namensattribut namens "<strong>log</strong>" hat. Behalten Sie das bei, denn so erhält WordPress die Variable "username"; in diesem Fall übergeben Sie jedoch den Benutzernamen aus Ihrem Benutzerobjekt. Um die Erfahrung mit Weiterleitungen und die Erinnerung an die erste Login-Sitzung beizubehalten, behalten Sie diese Variablen in ihren jeweiligen Eingabefeldnamen, aber dieses Mal werden sie ausgeblendet. Schließlich übergeben Sie die Anforderungs-ID aus dem Aufruf "Überprüfung senden" in einem verborgenen Eingabefeld sowie den Wert für den Code, den der Benutzer eingibt - all dies wird für die Validierung des Codes verwendet.
Die Parameter des Formulars sind:
log: Benutzername des Benutzerstwo_factor_auth_nexmo_pin_code: Code, den der Benutzer eingibttwo_factor_auth_nexmo_request_id: Anfrage-ID aus der ursprünglichen Anfragerememberme: Erinnern Sie sich an den Status bei der ersten Anmeldungredirect_to: Umleitung zur URL, wenn der Benutzer versucht hat, eine bestimmte Seite vor dem Anmeldeformular aufzurufen
Wichtiger Hinweis: Die Aktions-URL des Formulars ist immer noch die WordPress-Login-URL-Route
<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ) ?>Interessant ist, dass unsere Abfangfunktion mit der Authentifizierungsaktion verbunden ist. Wenn Sie auf die Schaltfläche "Verify" im Formular zum Verifizieren des Codes klicken, wird Ihre Abfangfunktion trotzdem ausgeführt, und dort fügen Sie das Codeschnipsel hinzu, um den vom Benutzer eingegebenen Code zu validieren.
public function intercept_login_with_two_factor_auth( $user, $username, $password ) {
$errors = array();
$redirect_to = isset( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : admin_url();
$remember_me = ( isset( $_POST['rememberme'] ) && $_POST['rememberme'] === 'forever' ) ? true : false;
$_user = get_user_by( 'login', $username );
// New addition
$saved_request_id = ($_user) ? get_user_meta($_user->ID, 'two_factor_auth_nexmo_request_id', true ) : null;
$nexmo_pin_code = isset( $_POST['two_factor_auth_nexmo_pin_code'] ) ? $_POST['two_factor_auth_nexmo_pin_code'] : false;
$nexmo_request_id = isset( $_POST['two_factor_auth_nexmo_request_id'] ) ? $_POST['two_factor_auth_nexmo_request_id'] : false;
if ( $nexmo_request_id && $nexmo_pin_code && $saved_request_id == $nexmo_request_id ) {
$verification = new \Nexmo\Verify\Verification($nexmo_request_id);
try {
$result = $this->nexmo_client->verify()->check($verification, $nexmo_pin_code);
$response = $result->getResponseData();
if ($response['status'] == "0") {
wp_set_auth_cookie( $_user->ID, $remember_me );
wp_safe_redirect( $redirect_to );
exit;
}
}
catch(Exception $e) {
// handle invalid code
if ($e->getCode() == 16){
$errors = array( "Invalid PIN code" );
}
$this->verify_user( $_user, $redirect_to, $remember_me,$errors );
}
}
// End of addition
if ( $_user ) {
$this->verify_user( $_user, $redirect_to, $remember_me );
}
return $user;
}In dem obigen Zusatz überprüfen Sie die POST-Daten der Anmeldeanforderung, um zu sehen, ob die 'two_factor_auth_nexmo_pin_code' und 'two_factor_auth_nexmo_request_id' Schlüssel gesetzt sind. Wenn ja, handelt es sich um eine Anforderung zur Validierung eines Codes. Um sicherzustellen, dass Sie den Code für den richtigen Benutzer validieren, vergleichen Sie auch die Request-ID aus den POST-Daten mit der Request-ID, die im Profil des Benutzers gespeichert ist; wenn sie übereinstimmen, dann rufen Sie die Funktion Verifizierung prüfen auf, um zu verifizieren, dass der eingegebene Code korrekt ist. Wenn er korrekt ist, setzen Sie das WordPress-Authentifizierungs-Cookie für den Benutzer und leiten ihn zum Dashboard weiter.
wp_set_auth_cookie( $_user->ID, $remember_me );
wp_safe_redirect( $redirect_to );Wenn dies nicht der Fall ist, rufen Sie einfach die verify_user Funktion erneut auf und senden einen neuen Prüfcode.
Hier ist ein Link zur vollständigen Class-Datei.
Schlussfolgerung
In diesem Tutorial haben Sie die Grundlagen der Erstellung eines WordPress-Plugins, der Integration der Nexmo PHP Library und der Verwendung der Nexmo Verify API kennengelernt. Ich hoffe, Sie fanden dies sehr hilfreich; Sie können den vollständigen Code auf GitHub über diesen Link. Vielen Dank fürs Lesen!
