Autenticação em 2 fatores com php e Google Authenticator

Um recurso de segurança em autenticação de sistemas que vem se popularizando bastante nos últimos tempos é a verificação em 2 etapas. Os principais aplicativos de bancos e corretoras utilizam seus próprios apps para gerar tokens que são dinâmicos (eles são atualizados constantemente em baixos ciclos de tempo), e utilizados como 2º fator para acesso ao sistema (o 1º fator é o tradicional usuário/email e senha).

Todavia, caso você não queira implementar o seu próprio gerador de tokens, você pode utilizar o Google Authenticator, um aplicativo com as características citadas (disponível para Android e IOS) e  que pode facilmente ser integrado ao seu aplicativo ou sistema web. Nesse post, eu vou mostrar para vocês como integrar sua aplicação php com o Google Authenticator.

Basicamente, o usuário do app/sistema precisa associar a conta dele ao aplicativo do Google Authenticator instalado em seu smartphone. Essa associação é feita através da leitura de um QR Code, ou informando o código manualmente (em ambos os casos, o código deve ser gerado a partir do próprio sistema). Na imagem à seguir, é possível visualizar a interface principal do app Google Authenticator. Cada conjunto de 6 dígitos referem-se a um sistema específico.

Imagem 1: Interface principal do Google Authenticator
Imagem 1: Interface principal do Google Authenticator

Para integrar uma aplicação php com o Google Authenticator, vamos utilizar a biblioteca sonata-project/GoogleAuthenticator (https://github.com/sonata-project/GoogleAuthenticator). Vamos fazer a instalação dela através do composer.

composer require sonata-project/google-authenticator

No nosso exemplo, vamos ter 2 arquivos:

  • genqrcode.php – responsável por gerar o código QR Code, para que o usuário/utilizador faça o scan 
  • check.php – valida o código de 6 dígitos (gerados pelo Google Authenticator) e então libera ou não o acesso ao sistema

No arquivo genqrcode.php vamos inserir o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php 
include_once 'vendor/sonata-project/google-authenticator/src/FixedBitNotation.php';
include_once 'vendor/sonata-project/google-authenticator/src/GoogleAuthenticatorInterface.php';
include_once 'vendor/sonata-project/google-authenticator/src/GoogleAuthenticator.php';
include_once 'vendor/sonata-project/google-authenticator/src/GoogleQrUrl.php';
 
$g = new \Google\Authenticator\GoogleAuthenticator();
$secret = 'XVQ2UIGO75XRUKJO';
//Você pode usar o $g->generateSecret() para gerar o secret
//$secret = $g->generateSecret();
 
//o método "getUrl" recebe como parâmetro: "username", "host" e a chave "secret"
echo '<img src="'.$g->getURL('rafaelwendel', 'rafaelwendel.com', $secret).'" />';
 
?>

Na linha 8 eu criei uma varíavel chamada “$secret”. Essa variável será responsável por armazenar a chave da minha aplicação. Recomendo que você utilize uma boa chave. Quanto melhor, mais seguro. Essa chave deve ser usada no momento de gerar o QR Code, e posteriormente devemos usar a mesma chave para poder validar um código de autenticação.

Na linha 10 é gerado uma imagem (QR Code) para que o usuário/utilizador faça o scan a partir do app Google Authenticator em seu celular.

Por fim, vamos implementar o arquivo check.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php 
 
include_once 'vendor/sonata-project/google-authenticator/src/FixedBitNotation.php';
include_once 'vendor/sonata-project/google-authenticator/src/GoogleAuthenticatorInterface.php';
include_once 'vendor/sonata-project/google-authenticator/src/GoogleAuthenticator.php';
include_once 'vendor/sonata-project/google-authenticator/src/GoogleQrUrl.php';
 
$g = new \Google\Authenticator\GoogleAuthenticator();
$secret = 'XVQ2UIGO75XRUKJO';
 
$code = '010989'; //código de 6 dígitos gerados pelo app do Google Authenticator
 
if($g->checkCode($secret, $code)){
	echo 'Autorizado!';
}
else{
	echo 'Código incorreto ou expirado!';
}

Na linha 11 eu insiro o código gerado pelo app do Google Authenticator. Obviamente, você terá um formulário para que esse código seja preenchido pelo usuário, submetido e recuperado. Lembre-se que esse código é dinâmico e o ciclo de vida dele é extremamente curto (apenas alguns segundos). Perceba também que na linha 9 eu utilizo a chave “$secret”, e ela deve ser EXATAMENTE a mesma que definimos lá no genqrcode.php

Para efetuar a verificação e então liberar o acesso, o código gerado pelo app e a chave “$secret” serão analisados no método “checkCode”.

Espero que gostem do conteúdo e qualquer dúvida deixe seu comentário.

Abs!

É formado em Sistemas de Informação, pós-graduado em Sistemas de Banco de Dados e mestre em Educação com foco em Tecnologias Sociocomunitárias. Trabalha como professor de ensino técnico e tecnológico no Instituto Federal de Educação, Ciência e Tecnologia de São Paulo ministrando disciplinas nas áreas de programação, banco de dados, desenvolvimento de projetos e engenharia de software.

Posts relacionados

Comentários

  1. Fiz o download da lib https://github.com/sonata-project/GoogleAuthenticator

    Obtive o secret no https://console.developers.google.com/

    Esta gerando o qr code e funcionou scaneando no google authenticator

    Mas ao digitar o 6 digitos do vodigo dentro do tempo, mesmo digitando certo ocorre o erro: Código incorreto ou expirado!

    Ao tentar usar o codigo exemplo nao funciona https://github.com/sonata-project/GoogleAuthenticator/blob/2.x/sample/example.php

    1. Olá Marcelo,

      O host que você está colocando no “$g->getUrl” é o mesmo que você está usando para hospedar seu código? Tente também utilizar o mesmo “$secret” que eu usei nos exemplos, ao invés de gerar um pelo Google Developers.

      Lembrando que depois de alterar essas informações no seu código, você deverá excluir e adicionar de novo o serviço no app Authenticator do seu celular.

      Abs!

  2. Rafael, bom dia!

    Eu percebi que se várias pessoas lerem o QRCode gerado na tela, elas vão sempre gerar o código igual e com isso, passar pela verificação da segunda etapa, independe da fase usuário e senha (primeira etapa).

    Seria isso mesmo?

    1. Olá Álvaro.

      Perceba que nas linhas 12 e 13 do arquivo genqrcode.php eu insiro o código para gerar o qrcode.

      12
      13
      
      //o método "getUrl" recebe como parâmetro: "username", "host" e a chave "secret"
      echo '<img src="'.$g->getURL('rafaelwendel', 'rafaelwendel.com', $secret).'" />';

      Perceba que o primeiro parâmetro do método getUrl é justamente o nome de usuário (username) da pessoa que está habilitando os 2 fatores.

      Obviamente, no sistema não terá usuários com o “username” duplicados, logo sempre será passado um “username” diferente e portanto sempre será gerado um qrcode diferente.

      Abs!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *