
Compartilhar:
Russ has been arguing with computers since 1985, and now mostly wins the fights. He has worked in video games, defence and investment banking, and joined the Vonage team four days before the Coronavirus lockdown. He enjoys travel, poker, games of all sorts, science fiction, and is easily dist... ooh, squirrel!
Crie um “Google Authenticator” a partir de um telefone fixo com a Vonage
Tempo de leitura: 23 minutos
Adoramos a autenticação de dois fatores (2FA) — ela torna o login muito mais seguro, pois combina uma senha memorizada com um código de acesso único gerado pelo seu celular. O problema com uma boa segurança, porém, é que fica muito fácil ficar sem acesso à conta.
Imagine que você está longe de casa — de férias, talvez, ou em uma viagem de negócios para uma cidade distante. É para isso que a autenticação de dois fatores (2FA) foi criada; você pode usar aquele computador compartilhado no saguão do hotel sem ficar com muito medo de keyloggers. Os hackers podem conseguir sua senha, mas ainda assim não conseguirão acessar suas coisas sem o celular na sua mão!

Mas e se você não tiver seu celular? E se ele se perder, se danificar ou for roubado? Bem, para começar, você vai querer ligar para a sua seguradora… mas os dados de contato estão no seu celular e no e-mail como backup… e você não consegue acessar seu e-mail sem o celular, já que usa a autenticação de dois fatores (2FA)! 😱
E se você pudesse acessar sua senha de autenticação de duas etapas (2FA) como um serviço remoto? Você poderia ligar para um número, digitar seu PIN e ouvir os dígitos sendo lidos para você.
Contexto tecnológico
Embora as primeiras implementações fossem proprietárias, existe um padrão aberto da Iniciativa para Autenticação Aberta (OATH) para senhas de uso único baseadas em tempo (TOTP), especificado na RFC 6238. Esse padrão utiliza um segredo pré-compartilhado e o número de intervalos de 30 segundos desde 01/01/1970 00:00:00 UTC, calcula um hash criptográfico e transforma-o em um número de seis dígitos que não pode ser previsto sem conhecer o segredo.
O que torna isso prático de usar, no entanto, é um esquema de URI definido pelo Google. Eles têm o seguinte formato: otpauth://totp/Example:totp@example.com?secret=KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD&issuer=Example
Normalmente, esses URIs são codificados como um código QR, assim:

Pré-requisitos
Há algumas coisas de que você vai precisar para este exemplo:
Google Authenticator (Android/iOSou qualquer aplicativo OATH TOTP semelhante)
Um serviço compatível com a autenticação de dois fatores (como uma Account do Google)
Um ngrok Account
A Heroku Account
ngrok instalado localmente (usei a versão 2.3.35)
node.js instalado localmente (usei a versão 12.6.1)
Applications
Vamos usar o Node.js neste exemplo porque ele facilita muito a execução de um serviço web simples. Além disso, há uma implementação bastante boa da lógica de senha de uso único de que precisamos: otplib.
Primeiro, precisamos instalar as bibliotecas necessárias, o que faremos com o npm.
Agora, insira o código a seguir em um arquivo chamado totp.js. Vamos começar com o PIN de acesso e o segredo compartilhado, que é o mesmo do código QR acima, e importar o otplib.
const totp = require('otplib');
// Hardcoded secrets
const secret = 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD';
const pin = '1234';Vamos criar um simples serviço web Node.js Express , usando a Voice API da Vonage para atender a chamada e retornar um Nexmo Call Control Object (NCCO), instruindo a API a usar a conversão de texto em fala para reproduzir uma frase e, em seguida, aguardar a entrada do usuário pelo teclado do telefone. Este é um sistema de Resposta Interativa de Voz (IVR) muito simples, mas não vamos nos aprofundar aqui no funcionamento da Voice API. Se você quiser entender melhor o que esse código está fazendo, dê uma olhada neste este tutorial.
const app = require('express')()
const bodyParser = require('body-parser')
app.use(bodyParser.json())
const onInboundCall = (request, response) => {
const ncco = [
{
action: 'talk',
text: 'Please enter your PIN, followed by a hash.'
},
{
action: 'input',
eventUrl: [`${request.protocol}://${request.get('host')}/webhooks/passcode`]
}
]
response.json(ncco)
}
Agora, a parte crucial: verifique o PIN digitado pelo usuário. Se estiver correto, obteremos a senha atual e a leremos em voz alta para ele.
const onInput = (request, response) => {
const dtmf = request.body.dtmf;
if (dtmf === pin) {
const token = totp.authenticator.generate(secret);
const slow = token.split('').join('. ');
const ncco = [{
action: 'talk',
text: `Passcode is ${slow}. Repeat. ${slow}.`
}]
response.json(ncco)
} else {
const ncco = [{
action: 'talk',
text: `Incorrect PIN. Goodbye.`
}]
response.json(ncco)
}
}
Por fim, associamos as funções que acabamos de definir aos métodos/caminhos HTTP e iniciamos o aplicativo para que ele fique à escuta em port 3000.
const PORT = 3000
app
.get('/webhooks/answer', onInboundCall)
.post('/webhooks/passcode', onInput)
app.listen(PORT)É isso aí! Agora você pode executar isso com o comando `node totp.js` e testá-lo acessando http://localhost:3000/webhooks/answer no seu navegador — ele retornará o objeto JSON da onInboundCall função que acabamos de definir!
Implantação local com o ngrok
Bem, é bom que algo esteja funcionando, mas não adianta muito se só pudermos acessá-lo na nossa máquina local!
O ngrok oferece uma maneira excelente de configurar um redirecionador dinâmico para disponibilizar nosso pequeno serviço na internet. Cadastre-se no site — basta um Account gratuito — e, em seguida, execute:
Isso salvará as credenciais da sua conta localmente; em seguida, você poderá configurar o redirecionamento de HTTP para a porta 3000 (a que usamos acima) executando:

Anote os URIs exibidos, pois eles serão específicos do seu serviço e mudarão sempre que o ngrok for executado.
Mais uma vez, podemos testar isso no nosso navegador acessando: https://bd934ed5.ngrok.io/webhooks/answer
Observação: você precisará usar o URI fornecido pelo ngrok.
O ngrok também oferece HTTPS gratuito, então nossa conexão será segura — não é demais?
Configuração das APIs da Vonage
Ainda não fazer fazernada, no entanto. É nessa parte que a coisa fica interessante.
Primeiramente, precisamos criar um novo aplicativo da Voice API. Acesse a aba “Seus aplicativos” do painel de controle das APIs da Vonage e clique no grande botão “Criar um novo aplicativo”:

Digite um nome como “Exemplo de senha TOTP” e gere um par de chaves para que ele tenha acesso à API:

Em seguida, ative o recurso “Voice” e configure o evento (https://bd934ed5.ngrok.io/webhooks/passcode) e a resposta (https://bd934ed5.ngrok.io/webhooks/answer) com os URIs do ngrok que você anotou acima. Certifique-se de usar seus próprios URIs do ngrok. Observe que o URI do evento usa HTTP POST; portanto, você precisará selecionar essa opção no menu suspenso:

Como alternativa, se você preferir usar uma interface de linha de comando (CLI), pode criar um aplicativo assim.
Instale a CLI do Vonage globalmente com este comando:
npm install @vonage/cli -gEm seguida, configure a CLI com sua chave e seu segredo da API da Vonage. Você pode encontrar essas informações no Painel do Desenvolvedor.
vonage config:set --apiKey=VONAGE_API_KEY --apiSecret=VONAGE_API_SECRETCrie um novo diretório para o seu projeto e acesse-o com o comando `cd`:
mkdir my_project
CD my_projectAgora, use a CLI para criar um aplicativo da Vonage.
Para poder ligar para esse serviço, precisamos de um número externo. Crie um usando “Numbers” -> “Comprar números” no painel de controle:

Mais uma vez, para os fãs da CLI, há a opção de pesquisar primeiro números com serviço de voz (por exemplo, nos EUA):
Então compre um da lista:
Por fim, precisamos vincular esse número ao aplicativo. Se você acessar “Meus Applications” no painel e clicar no seu aplicativo TOTP, deverá ver uma linha na parte inferior para inserir o seu número e um botão “Vincular” abaixo de “Gerenciar”:

Clique em “Link” e confirme, se necessário:

Não se preocupem, exército da CLI, também existe um comando para isso:
Existem também comandos úteis caso você não se lembre do número de telefone (vonage numbers) ou o UUID do aplicativo (vonage apps).
Agora temos nosso serviço vinculado a um número de telefone. Se ligarmos para esse número, isso acionará o /webhooks/answer endpoint, e o NCCO retornado acionará a conversão de texto em fala para reproduzir a frase “Digite seu PIN, seguido de um cerquilha.” e, em seguida, aguardará a entrada do teclado do telefone. Digite “1234#” no teclado, e isso será enviado para o /webhooks/passcode ponto de extremidade, que lerá em voz alta a senha de seis dígitos.
Digitalize o código QR na parte superior desta postagem do blog no Google Authenticator e você verá que os códigos coincidem perfeitamente!
Implantação global com o Heroku
É bom que tenhamos isso funcionando, mas não é muito prático mantê-lo rodando no seu computador — ele vai parar se você desligá-lo e, se estiver viajando, é improvável que você deixe um computador ligado em casa! Portanto, claramente será melhor se pudermos mantê-lo funcionando em algum lugar na internet.
O Heroku é ótimo para isso, permitindo a implantação e hospedagem simples de serviços web. Um Account gratuito já é suficiente, então vá e se cadastre uma e configure-a (com o Git e a CLI do Heroku). Eu espero.
Alterações no código
O Heroku atribuirá uma porta aleatória para a aplicação escutar, então não podemos simplesmente usar a 3000. Precisamos fazer essa alteração de uma linha para totp.js para que ela seja obtida do ambiente:
const PORT = process.env.PORT || 3000É necessária outra alteração no package.json arquivo para que o npm start comando funcione, pois, caso contrário, o Heroku não saberá como iniciar nosso aplicativo! Basta adicionar o node totp.js comando que usamos localmente ao elemento `scripts`. O código completo package.json agora deve ficar mais ou menos assim:
{
"name": "totp",
"version": "1.0.0",
"description": "One Time Password by phone",
"main": "totp.js",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"nexmo": "^2.6.0",
"otplib": "^12.0.1"
},
"devDependencies": {},
"scripts": {
"start": "node totp.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Russ Williams",
"license": "ISC"
}
Configurando o controle de versão do Git
Precisamos usar o Git para fazer a implantação no Heroku; além disso, é obviamente uma boa prática ter um controle de versão para qualquer projeto de desenvolvimento. Por enquanto, vamos nos limitar a um repositório local, mas o GitHub é gratuito e manterá seu código seguro, ao mesmo tempo em que o disponibiliza para você de qualquer lugar do mundo.
Primeiro, crie um repositório:
Em seguida, adicione os arquivos de origem de que precisaremos:
Por fim, precisamos confirmar essas alterações:
Implantação no Heroku
Primeiro, precisamos criar um novo aplicativo no Heroku:
Isso atribuirá ao seu novo aplicativo um nome gerado aleatoriamente, algo como lit-spire-15244. O heroku create comando configura um repositório remoto (por exemplo, https://git.heroku.com/lit-spire-15244.git) para o qual podemos enviar código.
Para implantar o aplicativo, precisamos usar o Git novamente para fazer o push para aquele repositório remoto:
Isso enviará o código para o Heroku e acionará uma implantação. Internamente, será executado npm start e informará um status como https://lit-spire-15244.herokuapp.com/ deployed to Heroku. Se você usar essa URI, https://lit-spire-15244.herokuapp.com/webhooks/answer, no meu caso, você deverá ver que o serviço já está em execução. Mais uma vez, temos HTTPS gratuito, o que é ótimo.
Se você tiver problemas ou apenas quiser saber o que está acontecendo, pode consultar os logs do serviço com o comando:
Atualize o aplicativo da Vonage
Por fim, precisamos atualizar o painel de controle das APIs da Vonage. Vá até a aba “Seus Applications”, selecione o aplicativo TOTP, clique em “Editar” e altere as URIs:

Próximos passos
Como faço para obter a senha dos meus accounts?
Infelizmente, o Google Authenticator e a maioria dos aplicativos semelhantes não permitem isso. Depois de escanearem um código QR, eles não oferecem nenhuma maneira de recuperar o segredo.
Para contas do G-Suite/Google (por exemplo, Gmail), há uma opção “Alterar telefone” na página de configuração da autenticação de duas etapas (2FA), que permite obter um novo código QR. Para a maioria dos outros serviços, você precisará desativar e, em seguida, reativar a autenticação de duas etapas (2FA), ou solicitar ao administrador do sistema que faça isso por você — essencialmente o mesmo processo que substituir seu celular.
Fazer uma captura de tela e escanear o código QR no aplicativo permitirá que você extraia o segredo e o utilize neste aplicativo.
Como faço para obter a senha de um código QR?
Use um aplicativo genérico de leitura de códigos QR para obter o URI — há muitos disponíveis para todos os celulares, e pode até haver um integrado ao aplicativo de câmera do seu celular. Como alternativa, você pode usar um site como https://webqr.com/ para escanear uma foto.
O segredo de que você precisa é a sequência de letras maiúsculas entre “secret=” e o “&” na URI: otpauth://totp/Example:totp@example.com?secret=KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD&issuer=Example
Para onde podemos levar isso?
Existem várias maneiras de ampliar este aplicativo de exemplo:
Exigir o uso de segredos codificados diretamente no código não é a melhor opção; seria muito melhor recuperá-los de um banco de dados no lado do servidor
Não há proteção contra ataques de força bruta ao seu PIN se alguém estiver disposto a fazer 10.000 chamadas para este aplicativo; portanto, seria útil implementar algum tipo de limitação de taxa
É um desperdício ter um número de telefone só para um segredo; por isso, poderíamos criar um sistema de menu IVR (“Pressione 1 para a senha do Gmail, pressione 2 para…”)
Os códigos de acesso têm validade limitada; portanto, se faltar apenas alguns segundos para que o código mude, provavelmente devemos usar a função de conversão de texto em fala para informar isso e aguardar o próximo código, em vez de ler um código já expirado. É melhor prolongar a ligação por alguns segundos do que ter que rediscar e tentar novamente
Extrair manualmente segredos de códigos QR é um saco, e existem módulos do Node.js (por exemplo, qrcode-reader) que podem fazer isso por nós. Se estivéssemos armazenando os segredos do aplicativo em um banco de dados, poderíamos adicionar um front-end web simples para fazer o cadastro a partir de uma captura de tela (por exemplo, este guia do Google)
… ou por meio do acesso à câmera do celular e um pouco de código HTML5 para capturar uma imagem (por exemplo, getUserMedia) ou até mesmo analisar o código QR (por exemplo, este tutorial ou html5-qrcode) e chamar o serviço web de inscrição
Espero que isso tenha lhe dado algumas ideias sobre como você pode usar as APIs da Vonage com a autenticação de dois fatores.
Compartilhar:
Russ has been arguing with computers since 1985, and now mostly wins the fights. He has worked in video games, defence and investment banking, and joined the Vonage team four days before the Coronavirus lockdown. He enjoys travel, poker, games of all sorts, science fiction, and is easily dist... ooh, squirrel!