Artigo original: Best practices for building secure API Keys

Escrito por: Ramesh Lingappa

Todos sabemos o valor das APIs. Elas são a porta de entrada para a exploração de outros serviços, para a integração com eles e para a criação de soluções incríveis mais rapidamente.

Você já deve ter criado ou está pensando em criar APIs para que outros desenvolvedores as utilizem. Uma API precisa de alguma forma de autenticação para dar acesso autorizado aos dados que ela retorna.

Existem vários padrões de autenticação disponíveis hoje em dia, como chaves de API, OAuth, JWT, entre outros.

Neste artigo, veremos como gerenciar corretamente as chaves para acessar APIs.

Por que usar chaves de API?

As chaves de API são simples de usar, são breves, estáticas e não expiram até terem sido revogadas. Elas fornecem uma maneira fácil para que diversos serviços se comuniquem.

Se você fornecer uma API para que seus clientes a consumam, é essencial que você crie as chaves de API do modo certo.

Vamos começar. Quero mostrar a vocês como criar chaves de API corretamente.

Geração de chaves de API

Como a própria chave de API é uma identidade a partir da qual reconheceremos a aplicação ou o usuário, ela precisa ser exclusiva, aleatória e não ser fácil de adivinhar. Chaves de API geradas também devem usar caracteres alfanuméricos e especiais. Um exemplo de chave de API seria zaCELgL.0imfnc8mVLWwsAawjYr4Rx-Af50DDqtlx.

Armazenamento seguro de chaves de API

Como a chave da API fornece acesso direto aos dados, ela é semelhante a uma senha que o usuário da web ou da aplicação para dispositivos móveis fornece para obter acesso aos mesmos dados.

Pense nisto: o motivo pelo qual precisamos armazenar chaves de API é garantir que a chave da API que se encontra na requisição seja válida e emitida por nós mesmos (como uma senha).

Não precisamos conhecer a chave de API bruta. Precisamos apenas validar se a chave está correta. Assim, em vez de armazenar a chave em texto simples (o que é ruim) ou criptografá-la, devemos armazená-la como um valor com um hash em nosso banco de dados.

Um valor com hash significa que, mesmo que alguém obtivesse acesso não autorizado ao nosso banco de dados, as chaves de API não seriam "vazadas" e tudo continuaria seguro. O usuário final poderia enviar a chave de API bruta em toda solicitação à API e poderíamos validar a chave passando-a pelo hash na solicitação e comparando a chave com hash com a chave com hash armazenada em nosso banco de dados. O problema está no fato de que armazenar um valor com hash pode trazer problemas específicos de usabilidade. Falaremos deles agora.

Como apresentar as chaves de API aos usuários

Como não armazenamos a chave de API original, podemos mostrá-la apenas uma vez para o usuário, no momento de sua criação. Desse modo, não se esqueça de alertar os usuários de que ela não poderá ser obtida novamente, sendo preciso gerar um novo token caso eles tenham se esquecido de copiar a chave de API e de armazená-la de modo seguro. Você pode fazer algo assim:

1_DutIyYh2hE-YAkirxtoIxg
Mostrando a chave de API gerada com uma mensagem de alerta

Como os usuários podem identificar posteriormente uma chave de API gerada

Outro problema está em como os usuários identificam a chave de API certa em nosso console se precisarem editá-la ou revogá-la. Isso pode ser resolvido adicionando um prefixo à chave de API. Perceba na figura acima os primeiros 7 caracteres (nosso prefixo), separados do resto da chave de API pelo ponto.

Agora, você pode armazenar este prefixo no banco de dados e exibi-lo no console para que os usuários possam identificar rapidamente a entrada certa da chave de API, assim:

1_WU0mFXXFXW2VlA9BXK3ffA
Console de gerenciamento das chaves de API

Não dê todo o poder à chave de API

Um erro comum que cometem os fornecedores de chaves de API é o de dar a uma única chave acesso a tudo, já que isso facilita o gerenciamento. Não faça isso. Leve em conta que um usuário precisa apenas ler um e-mail para gerar uma chave de API. Essa chave, porém, agora terá acesso total aos outros serviços, incluindo a permissão de exclusão de registros no banco de dados.

A abordagem correta seria a de permitir aos usuários finais terem acesso a chaves de API restritas e selecionar ações específicas que essas chaves possam realizar. Isso pode ser feito por meio do fornecimento de escopos, onde cada escopo representa uma permissão específica.

Por exemplo:

  • se você precisa de uma chave de API apenas para enviar e-mails, pode gerar uma chave de API com o escopo sendo algo como "email.envios"
  • se o usuário final tiver diversos servidores e cada um deles realizar uma ação específica, uma chave de API separada pode ser gerada para cada escopo específico.

Assim, ao criar uma chave de API, permita que os usuários selecionem qual o acesso à chave de API deve ter, assim como na imagem abaixo.

1_-HHZ-Vfwz9FBPl-FIlS6mg

Desse modo, os usuários podem gerar diversas chaves de API, cada uma com regras específicas de acesso, gerando uma maior segurança. Quando uma requisição de API for recebida, será possível verificar se a chave de API tem o escopo certo para acessar aquela API. O banco de dados, agora, teria uma aparência semelhante a esta:

1_y9SVyRJa3m50tQ0buEU1VA
Entidade do banco de dados de chaves de API

Chaves de API com limitação de taxa

Sim, talvez você já saiba disso, mas é importante limitar a taxa de solicitações feitas com chaves de API específicas para garantir que ninguém mal-intencionado possa derrubar seus servidores de APIs ou causar problemas de desempenho que possam afetar outros usuários. Ter uma limitação de taxa adequada e monitorar soluções mantém o serviço da API em bom estado.

Conclusão

Chaves de API, quando criadas do modo certo, seguem sendo uma grande maneira de se comunicar com outro servidor. Como revisamos neste artigo, seguir certas práticas oferece benefícios tanto aos fornecedores quanto aos consumidores das APIs. Espero que o artigo tenha ajudado você.

Divirta-se deixando suas APIs cada vez mais seguras!