
Compartilhar:
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.
Como adicionar a autenticação de dois fatores ao WordPress com a Verify API de Nexmo
Tempo de leitura: 9 minutos
Introdução
Com o aumento das violações de segurança, proteger seu site e seus usuários nunca foi tão urgente como é hoje. Neste tutorial, você configurará a autenticação de dois fatores (2FA) no WordPress usando a Verify API. Com essa configuração, sempre que um usuário tentar fazer login, ele receberá um SMS ou uma ligação no número de celular cadastrado em seu perfil com um código único; somente após inserir o código válido é que ele terá acesso ao site.
Ao final deste tutorial, você terá aprendido os conceitos básicos para criar um plugin do WordPress e terá uma boa compreensão de como integrar a API do Nexmo ao WordPress usando a biblioteca PHP do Nexmo. Então, vamos começar!
Sobre a Verify API de Nexmo
A Verify API é a solução “plug and play” da Nexmo para autenticação de dois fatores em qualquer sistema. O processo é simples: basta chamar a Send Verification , passando um número de celular; a Nexmo enviará a esse número um código único por SMS ou chamada e retornará um ID de solicitação. Com o código do usuário, você chamaria o Check Verification juntamente com o ID da solicitação para verificar o código, e a Nexmo retorna um status dependendo se o código é válido ou não. Muito simples, não é?
Gosto particularmente do Nexmo Verify por causa de algo chamado “fluxos de trabalho”. Com os fluxos de trabalho, é possível configurar várias opções alternativas para o caso de um usuário não receber o código por SMS a tempo. Você pode definir uma opção alternativa de chamada de Voice após um determinado período e muito mais; leia mais sobre os fluxos de trabalho aqui.
O que você precisa para começar:
Auto-hospedado WordPress auto-hospedado
Criando seu plugin para o WordPress
Embora seja possível criar um plugin do WordPress simplesmente adicionando uma nova pasta na pasta de plugins do WordPress, uma maneira realmente eficiente é usar um modelo básico leve para começar. Esses modelos são úteis para configurar todos os arquivos e classes de maneira padronizada. Neste tutorial, você usará o wppb ; basta preencher os detalhes no site e clicar no botão “criar plugin” para baixar seu modelo de plugin.
Wordpress Plugin Boilerplate Generator
Depois de fazer isso, extraia o arquivo zip e coloque-o na pasta de plugins do WordPress. Em seguida, acesse o painel de administração do WordPress, vá até a página de plugins instalados e ative o plugin.
Plugins
Histórias de usuários
Com o objetivo de configurar a autenticação de duas etapas (2FA) no WordPress, vamos dividir essa ideia em histórias de usuário/etapas práticas e implementá-las do início ao fim:
Nas configurações do perfil do usuário do WordPress, você precisará de campos personalizados para o número de celular do usuário para a autenticação de duas etapas (2FA) e para indicar se a autenticação de duas etapas está ativada
Você enviará um código para o número de celular do usuário quando ele fizer login
Você terá um formulário para que o usuário insira o código que recebeu e Verify o código
Entendendo as ações e os filtros do WordPress
A maioria das alterações que você fará no WordPress envolve vincular suas funções a ações e filtros já existentes no WordPress; Ações são funções executadas quando um determinado evento ocorre no WordPress. Portanto, se você quiser que sua função seja executada quando um evento específico ocorrer — por exemplo, quando um usuário faz login —, você deve vinculá-la à ação relacionada ao login. Por outro lado, filtros modificam determinadas funções; você pode usar um filtro para manipular o resultado de uma função.
Você vincula sua função a uma ação existente desta forma:
add_action( 'action_name', 'name_of_your_function' );
Você vincula sua função a um filtro da seguinte maneira:
add_filter( 'filter_name', 'name_of_your_function' );
Campos personalizados do usuário
Para resumir este post, aqui está o link para o código que adiciona os campos de número de celular e a caixa de seleção para ativação da autenticação de dois fatores (2FA) às configurações do perfil de usuário do WordPress. Com essa configuração, sua página de configurações de usuário ficaria assim:
Nexmo 2FA
Incorporando a biblioteca PHP da Nexmo ao projeto
A Nexmo recomenda que você instale a biblioteca PHP por meio do Composer; você precisará ter o Composer configurado no seu servidor ou sistema local. Caso ainda não tenha o Composer configurado, aqui estão dois guias recomendados pela Nexmo para ajudá-lo: GetComposer.org ou Scotch.io
Com o Composer instalado, abra o terminal, acesse a pasta raiz do seu plugin e execute:
Isso criará uma nova pasta chamada vendor que contém várias outras bibliotecas, incluindo a biblioteca PHP da Nexmo. Para incluir a biblioteca no seu plugin, basta adicionar esta linha ao arquivo PHP raiz do seu plugin.
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
Inicializando a classe Nexmo
Antes de fazer qualquer chamada com a biblioteca PHP da Nexmo, é necessário inicializar a classe Nexmo e usar o objeto cliente para realizar suas solicitações subsequentes.
$basic = new \Nexmo\Client\Credentials\Basic(NEXMO_API_KEY, NEXMO_API_SECRET);
$client = new \Nexmo\Client(new \Nexmo\Client\Credentials\Container($basic));Se você estiver usando o modelo padrão, poderá fazer as seguintes alterações no arquivo de classe pública na pasta /public . Você inicializará a biblioteca Nexmo no construtor e definirá o objeto cliente como uma variável protegida para que outros métodos da nossa classe pública possam acessá-lo.
<?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));
}
} Envio da solicitação de verificação
Com base em nossa história de usuário, queremos interceptar o login do usuário, verificar se ele está habilitado para a autenticação de dois fatores (2FA) e, caso esteja, iniciar uma envio de solicitação de verificação para o número de celular dele. Para isso, você precisará conectar-se à ação authenticate ação do WordPress, já que é essa ação que é acionada quando um usuário faz login com sucesso.
<?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;
}Ao vincular nossa função à authenticate ação nos dá três variáveis com as quais trabalhar: $user, $username, e $password, a $user variável geralmente é nula, mas tudo bem. O que você precisa é do $username, com isso, você pode chamar a função do WordPress para obter o objeto do usuário. Você precisa do objeto do usuário para obter outras propriedades dele, como o número de celular e se a autenticação de duas etapas (2FA) está ativada.
$_user = get_user_by( 'login', $username );// Function to get the user objectPara obter o valor dos campos personalizados de um usuário, utilize a função do WordPress get_user_meta, passando o ID do usuário e o nome do campo personalizado. Conforme definido no código de configurações do perfil do usuário, os nomes dos campos são two_factor_auth_nexmo_enabled e 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();
}Se todas as variáveis necessárias estiverem definidas (número de celular e autenticação de duas etapas ativada para o usuário), você chama a função para iniciar uma Enviar Solicitação de Verificação , a Nexmo envia ao usuário o código único e um ID de solicitação é retornado. É importante armazenar o ID de solicitação para que você possa usá-lo ao chamar a função “Validate code” na próxima etapa. Uma maneira simples de fazer isso é usando a função update_user_meta com o identificador-chave da variável (no nosso caso two_factor_auth_nexmo_request_id) e a variável $request_id.
Por fim, chame a logout função. Você deve estar se perguntando: por que faria isso? Você faz isso porque, como mencionado inicialmente, a ação de autenticação é acionada quando o usuário faz login com sucesso. Portanto, na verdade, todo esse código está sendo executado quando o usuário está conectado, mas não é isso que você quer — pelo menos não ainda. Você quer que o usuário faça login somente após a validação do código. Portanto, desconecte o usuário após enviar o código, e isso nos leva à nossa etapa final: validar o código e fazer o login do usuário.
Validação do código
Você enviou o código ao usuário na seção acima; agora basta exibir um formulário para que ele insira o código recebido e validá-lo em relação ao perfil dele para que ele faça o login.
Com base na verify_user função que você criou anteriormente, você adicionará o formulário de validação de código.
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;
}Observação: Aqui, coloquei meu código HTML no método da classe, mas você sempre pode colocar o seu em um arquivo separado e incluí-lo.
Com o código acima, você deverá ter uma página com a seguinte aparência ao tentar fazer login em um Account habilitado para a autenticação de duas etapas (2FA).
Wordpress Pin
A login_header função adiciona aquela pequena seção acima do formulário que mostra os últimos 5 dígitos do número de celular do usuário.
O <form> nesta visualização é uma réplica do formulário de login do WordPress com apenas algumas alterações. Se você examinar o formulário de login do WordPress pelo navegador, perceberá que o campo de entrada do nome de usuário possui um atributo “name” chamado “<strong>log</strong>”. Mantenha isso, pois é assim que o WordPress obtém a variável de nome de usuário; no entanto, neste caso, você passará o nome de usuário a partir do seu objeto de usuário. Para preservar a experiência de redirecionamentos e a preferência “lembrar-me” da sessão de login inicial, mantenha essas variáveis nos nomes dos respectivos campos de entrada, mas, desta vez, elas ficarão ocultas. Por fim, passe o ID da solicitação da chamada “Enviar verificação” em um campo de entrada oculto, bem como o valor do código inserido pelo usuário — todos esses dados serão usados para validar o código.
Os parâmetros do formulário são:
log: Nome de usuário do usuáriotwo_factor_auth_nexmo_pin_code: Código digitado pelo usuáriotwo_factor_auth_nexmo_request_id: ID da solicitação inicialrememberme: Status “Lembrar-me” a partir do primeiro loginredirect_to: Redirecionar para a URL caso o usuário estivesse tentando acessar uma página específica antes do formulário de login
Observação importante: A URL de ação do formulário continua sendo a rota da URL de login do WordPress
<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ) ?>. O interessante é que, como nossa função de interceptação está vinculada à ação de autenticação, quando você clica no botão “Verify” no formulário de verificação de código, sua função de interceptação ainda é executada, e é aí que você adiciona o trecho de código para validar o código digitado pelo usuário.
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;
}Além disso, você está verificando os dados POST da solicitação de login para ver se o 'two_factor_auth_nexmo_pin_code' e 'two_factor_auth_nexmo_request_id' estão definidas. Se estiverem, trata-se de uma solicitação para validar um código. Para garantir que você esteja validando o código do usuário correto, você também compara o ID da solicitação dos dados POST com o ID da solicitação salvo no perfil do usuário; se eles corresponderem, você chama a função função Check Verification para verificar se o código inserido está correto. Se estiver correto, você define o cookie de autenticação do WordPress para o usuário e o redireciona para o painel de controle.
wp_set_auth_cookie( $_user->ID, $remember_me );
wp_safe_redirect( $redirect_to );Caso contrário, basta chamar a verify_user função novamente e enviar um novo código de verificação.
Aqui está um link para o arquivo Class completo.
Conclusão
Neste tutorial, você aprendeu os conceitos básicos para criar um plugin do WordPress, integrar a biblioteca PHP da Nexmo e usar a Verify API. Espero que tenha achado isso muito útil; você pode conferir o código completo no GitHub por meio deste link. Obrigado pela leitura!