Quais são as estratégias de autenticação de webhooks?

Em um artigo anterior, concluímos que uma das principais vulnerabilidades do design de webhooks é a falta de autenticação nas duas pontas do canal de comunicação. Um consumidor não consegue verificar que está recebendo um webhook da origem esperada; da mesma forma, um produtor de webhooks não consegue verificar o consumidor.

Para resolver esse problema, precisamos de um sistema de autenticação que garanta que os webhooks sejam enviados ao destino certo e que a origem seja verificada. Neste artigo, discutimos as estratégias de autenticação de webhooks disponíveis para desenvolvedores hoje. Depois, comparo cada método para te ajudar a decidir com base em informação sólida na hora de escolher uma estratégia de autenticação.

Proteja seus webhooks automaticamente.

O Hookdeck verifica assinaturas de webhook de mais de 160 provedores — para você focar no processamento, não na autenticação.

Como proteger um webhook?

Antes de mergulhar nas estratégias de autenticação de webhooks, vamos recapitular rapidamente as vulnerabilidades de segurança de webhooks e os métodos para mitigá-las. A tabela abaixo mapeia as vulnerabilidades de segurança que identificamos junto com as soluções discutidas no nosso artigo com o checklist de segurança de webhooks.

Vulnerabilidade de segurançaSolução
Nenhuma verificação da origem e do destino de um webhookAutenticação
Os dados do webhook ficam expostos em trânsitoCriptografia TLS/SSL
Os dados do webhook não são verificadosVerificação de assinatura
Nenhuma restrição sobre de onde o webhook pode virAutenticação/TLS mútuo
Requisições de webhook podem ser duplicadasNonce criptográfico

Uma observação interessante sobre a tabela acima é o número de vezes em que a autenticação aparece como solução. Pelo menos 3 das 5 vulnerabilidades listadas podem ser resolvidas por meio de autenticação.

É por isso que a autenticação é tão importante quando o assunto é proteger webhooks. Na próxima seção, vamos ver as diferentes formas de conseguir isso.

Quais são as estratégias de autenticação de webhooks?

Autenticação básica

A autenticação básica é uma das formas mais antigas e simples de verificar webhooks. Ela usa um username e uma password para que os produtores de webhook sejam autenticados ao enviar webhooks para um endpoint HTTP (a URL do webhook). Vamos ver como a autenticação básica funciona com webhooks, passo a passo.

  1. O desenvolvedor da aplicação de destino envia o seu usuário e senha ao provedor do webhook.
  2. O provedor envia primeiro uma requisição sem o header Authorization. Essa requisição é rejeitada com um status 401 pelo endpoint de destino, que devolve um desafio de autenticação usando o header WWW-Authenticate.
  3. O produtor então combina usuário e senha com dois-pontos (:) e envia a versão codificada em base64 dessa string no header Authorization da requisição, para autenticá-la, no formato:
Authorization: Basic {base64(username:password)
  1. O endpoint de destino recebe as requisições autenticadas, verifica as credenciais e, se forem válidas, aceita o webhook. Se as credenciais não forem válidas, o webhook é rejeitado.

Um dos principais provedores de webhook que suportam autenticação básica é o Twilio. O Twilio também suporta digest authentication, que é mais complexa e foi projetada para substituir a autenticação básica oferecendo mais recursos de proteção.

O Okta também usa autenticação básica para autorizar requisições de webhook. Em vez de enviar usuário e senha diretamente ao Okta, você faz a combinação username:password, codifica em base64 e fornece esse valor ao Okta como segredo de autorização.

Token de verificação (bearer) e headers customizados

Outro tipo de estratégia de autenticação envolve passar uma string secreta no header da requisição. Essa string é entregue ao produtor do webhook após uma autenticação bem-sucedida e usada para verificar cada requisição de webhook.

Autenticação por token

Um método padrão dessa abordagem é a autenticação por token. Trata-se de um protocolo de verificação OAuth que permite aos usuários verificar sua identidade em uma aplicação web, receber um token de acesso e verificar cada requisição à aplicação com esse token. A requisição autenticada usa o header Authorization para enviar o token no formato abaixo:

Authorization: Bearer {token}

Consumidores de webhook podem usar essa estratégia para autenticar as requisições que chegam à URL do webhook.

Do lado dos produtores de webhook, diferentemente da autenticação básica, a implementação de autenticação baseada em token não é tão difundida. Isso pode se dever ao fato de que a autenticação baseada em token tem um fluxo mais complicado e muitas vezes envolve um servidor de autorização para fornecer os tokens.

Serviços como SparkPost e Akamai Identity Cloud têm suporte completo à autenticação por token em webhooks. Isso inclui permitir que os usuários configurem um servidor de autorização informando o client ID, o client secret e a URL do servidor de onde o token será obtido.

Outros provedores de webhook, como Zapier e JIRA, permitem que você adicione um header de autorização enviado a cada disparo de webhook. Você pode usar isso para inserir um token de autenticação nas suas requisições, de modo que os seus webhooks sejam autenticados com sucesso no seu endpoint de API.

Headers customizados

Um método menos usado de autenticação envolvendo uma string secreta passada de um produtor de webhook para um consumidor é o uso de headers customizados. Provedores de webhook como Okta e ContentStack permitem definir headers HTTP customizados na configuração do webhook.

Esses headers são enviados junto com o seu webhook e são usados pelo consumidor para autenticar as requisições e rejeitar webhooks que não contenham os headers customizados.

Verificação de assinatura

A verificação de assinatura brilha principalmente pela capacidade de validar o payload do webhook. A autenticação da origem e do destino é implícita, porque as duas pontas participam do processo de verificação. A verificação de assinatura também é a única estratégia de autenticação com um método para prevenir replay attacks.

Vamos ver como a verificação de assinatura funciona.

  1. Uma chave secreta é conhecida tanto pelo produtor quanto pelo consumidor do webhook.
  2. Ao enviar um webhook, o produtor usa essa chave e um algoritmo criptográfico (por exemplo, HMAC) para criar um hash criptográfico do payload. Essa é a assinatura única do webhook.
  3. A assinatura é enviada em um header customizado junto com a requisição do webhook. Às vezes, o tipo de algoritmo usado também é enviado.
  4. Quando o webhook chega à URL do webhook, a aplicação receptora pega o payload e usa a chave secreta e o algoritmo criptográfico para calcular a assinatura.
  5. A assinatura calculada é então comparada com a enviada pelo produtor no header customizado. Se houver correspondência, a requisição é válida; caso contrário, o webhook é rejeitado.

Esse processo permite aos desenvolvedores verificar a integridade do payload do webhook e a autenticidade do produtor. Para saber mais, confira este guia, em que ficamos mais práticos e mostramos como implementar verificação de assinatura, do jeito certo, na sua aplicação.

Prevenindo replay attacks

Como mencionei antes, uma grande vantagem da verificação de assinatura é a capacidade de prevenir replay attacks em webhooks. Um replay attack acontece quando um atacante se apossa de uma requisição autenticada e a repete, fazendo com que o efeito do webhook seja duplicado na aplicação receptora.

Para prevenir replay attacks, a verificação de assinatura permite adicionar um timestamp que pode ser usado para expirar o webhook depois de um certo período, por exemplo 2 minutos. Esse tempo pode ser ajustado conforme os seus requisitos de segurança.

Um exemplo de provedor de webhook que faz isso por padrão é a Stripe. A Stripe adiciona um timestamp de expiração em um header Stripe-Signature do webhook. Esse timestamp também é verificado junto com o restante do conteúdo do payload, o que significa que o atacante não consegue manipulá-lo.

Quando o webhook chega à URL do webhook, ele é comparado com o horário atual para ver se ainda é válido. Se o timestamp for antigo demais, o webhook é rejeitado.

Rotacionando o segredo HMAC

A verificação de assinatura é tão forte quanto o segredo por trás dela. Se esse segredo vaza por um log comprometido, uma variável de ambiente exposta ou um integrante que deixa o time, um atacante consegue forjar assinaturas válidas. Rotacionar o segredo periodicamente, e imediatamente após qualquer suspeita de exposição, limita por quanto tempo uma chave vazada continua útil.

A dificuldade é que produtor e consumidor não conseguem trocar de segredo no mesmo instante. Se você troca o segredo primeiro no produtor, todo webhook em trânsito falha na verificação até o consumidor acompanhar; se troca primeiro no consumidor, você rejeita requisições legítimas ainda assinadas com a chave antiga. De um jeito ou de outro, você perde webhooks durante a transição.

O padrão de rotação com segredo duplo elimina essa janela:

  1. Gere um novo segredo e adicione-o ao lado do existente, de modo que os dois fiquem ativos ao mesmo tempo.
  2. O produtor assina cada webhook com as duas chaves e envia as duas assinaturas (por exemplo, em um header de assinatura separado por vírgulas).
  3. O consumidor aceita a requisição se ela corresponder ao segredo antigo ou ao novo.
  4. Assim que todos os consumidores estiverem implantados com o novo segredo, aposente o antigo e volte a uma única assinatura.

Como as duas chaves são válidas durante toda a janela de transição, nenhum webhook é rejeitado enquanto você aplica a mudança em produtores e consumidores. A Stripe implementa exatamente isso: ao rotacionar um segredo de assinatura, o antigo continua ativo por 24 horas e, durante essa janela, o header Stripe-Signature carrega uma assinatura para cada segredo ativo, para você poder verificar contra qualquer um deles.

Ao verificar contra múltiplos segredos, compare cada assinatura candidata usando uma função de comparação em tempo constante para evitar vazar informação por timing, e rejeite a requisição apenas se ela falhar contra todos os segredos ativos.

Quais estratégias de autenticação de webhooks eu devo usar?

Agora que conhecemos as diferentes estratégias que podem ser usadas para autenticar webhooks, vamos olhar as capacidades de cada uma lado a lado para você decidir qual se encaixa melhor no seu caso de uso.

As três abordagens que você vai comparar com mais frequência são Basic Auth, JWT (bearer token) e verificação de assinatura HMAC. Veja como elas se comparam rapidamente:

Basic AuthJWT (bearer token)Assinatura HMAC
O que é transmitidousername:password codificado em Base64 no header AuthorizationUm token assinado no header Authorization: BearerUm hash do payload em um header de assinatura; o segredo nunca é enviado
Verifica a integridade do payloadNãoNão — o token é assinado, não o corpo do webhookSim — a assinatura é calculada sobre o corpo da requisição
Previne replay attacksNãoNão, até o token expirar (tokens de vida curta encurtam a janela)Sim, quando um timestamp assinado é incluído
Exposição do segredoAlta — as credenciais viajam em toda requisição e Base64 é trivialmente decodificável, então HTTPS é obrigatórioMédia — um token roubado é utilizável até expirar, mas as credenciais de longa duração ficam no servidorBaixa — o segredo compartilhado nunca é transmitido
Complexidade de implementaçãoBaixaMédia — normalmente precisa de um servidor de autorização para emitir os tokensMédia — calcular o hash, comparar em tempo constante, suportar rotação de segredo
Provedores de webhook típicosTwilio, OktaSparkPost, Akamai Identity CloudStripe, Shopify, GitHub
Melhor paraEndpoints de baixa sensibilidade em que a simplicidade venceConsumidores já investidos em infraestrutura de OAuth/tokensQualquer webhook que carregue dados sensíveis ou que mudem estado (padrão recomendado)

Vamos olhar as vulnerabilidades que a autenticação deve mitigar (veja a tabela acima) e explorar como esses métodos de autenticação se saem contra cada uma.

VulnerabilidadesAutenticação básicaAutenticação por tokenVerificação de assinatura
Verifica a origemSimSimSim
Verifica o destinoSimSimSim
Valida o payloadNão: não há método nativo de verificar que o payload é o que foi enviado pelo produtor do webhook.Não: tokens como o JWT contêm uma assinatura que valida as credenciais de autenticação (por exemplo, o usuário), mas não valida o payload inteiro do webhook.Sim
Protege as credenciaisNão: a codificação de usuário e senha pode ser revertida e expor as credenciais de login. Você precisa usar HTTP seguro (HTTPS) para garantir que todos os dados sejam criptografados.SimSim
Previne replay attacksNão: a requisição autenticada pode ser repetida várias vezes e causar efeitos indesejados.Não: enquanto o token ainda for válido (a menos que expire), uma requisição autenticada pode ser repetida várias vezes por um atacante.Sim

Como se vê na tabela acima, a verificação de assinatura é o único método de autenticação que cobre todas as frentes. Isso significa que devemos descartar todos os outros métodos em favor da verificação de assinatura? Não exatamente. Muitos grandes provedores de webhook, como Okta, Twilio e Stripe, ainda suportam autenticação básica.

Recomendação

Como discutido no Guia completo de segurança de webhooks, os métodos de segurança de webhooks podem ser aplicados conforme a sensibilidade da informação que eles carregam ou conforme as políticas de segurança da sua organização. Há casos de uso simples em que a simplicidade da autenticação básica é exatamente o que se precisa. Também há casos em que os desenvolvedores adotam um modelo composto, com autenticação básica combinada com verificação de assinatura.

Ainda assim, recomendamos que você configure verificação de assinatura para proteção máxima dos seus webhooks.

Como o Hookdeck ajuda

Escolher a estratégia de autenticação certa é uma decisão — implementá-la corretamente em cada provedor com que você integra é outra. Cada provedor traz o próprio esquema de assinatura, convenções de header e regras de codificação do payload, e errar qualquer um deles quebra a entrega silenciosamente. Uma única incompatibilidade significa rejeitar webhooks legítimos ou, pior, aceitar webhooks forjados (e o peso da manutenção cresce a cada novo provedor que você integra).

O Event Gateway do Hookdeck faz a verificação de assinatura de mais de 160 provedores de webhook de forma nativa. Você seleciona o provedor, informa o segredo de assinatura e toda requisição de entrada é verificada na borda antes de chegar à sua aplicação, com as requisições não verificadas sendo rejeitadas automaticamente. Isso significa que os seus handlers podem confiar em cada payload que chega, sem que você precise manter uma estratégia de autenticação diferente para cada provedor integrado. Comece a usar o Hookdeck e tire a autenticação de webhooks das suas costas em minutos.

Conclusão

Neste artigo, passamos pelas diferentes estratégias de autenticação para validar a integridade dos nossos webhooks. A segurança de webhooks é frequentemente ignorada, o que pode levar a muitas consequências indesejadas. Vimos como a autenticação resolve boa parte das vulnerabilidades que acompanham os webhooks, o que indica que, se você se importa com segurança, autenticar os seus webhooks deve ser o primeiro passo. Depois de proteger os seus webhooks, siga as nossas boas práticas para colocar webhooks em produção.

Bom código!