A privacidade e segurança dos dados é uma preocupação para quase qualquer empresa. Nesse post, explicamos como estruturar a segurança em APIs RESTful.
Vamos aprender mais sobre APIs Restful? Nesse artigo vou falar de um tema polêmico e importante sobre APIs — Segurança.
Já ouvi muita empresa perguntar, com um tom de desconfiança: “Esse negócio de APIs é realmente seguro?”
Além disso, indústrias como a bancária, que normalmente são extremamente preocupadas com o assunto segurança, serão obrigadas a exporem suas APIs ao mercado. Esse é o já famoso Open Banking, necessário até 2020 por uma mudança na legislação
Portanto, prestem bastante atenção nesse tema.
Esses são os conhecimentos básicos que você precisa ter para avançar nesse tema de segurança.
Autenticação é como se você fosse para uma festa, e o segurança exigisse suas credenciais como nome na lista e RG para liberar sua entrada.
Autorização é como se você já estivesse dentro da festa e quisesse subir ao palco do show, mas para isso você precisaria ser autorizado pelo segurança.
Basic authentication é um esquema de autenticação bem simples especificado no protocolo HTTP.
O cliente envia uma requisição com o header (Authorization) que contém a palavra Basic e o nome de usuário e senha, separados por dois pontos (:) no formato de base64.
Por exemplo, para autorizar o usuário thiago com senha thiago@123, o client enviaria na requisição, o seguinte header:
Authorization: Basic dGhpYWdvOnRoaWFnb0AxMjM=
O formato base64 é muito fácil de ser decodificado. Por isso, a basic authentication só é recomendada quando são utilizados outros complementos de segurança, como por exemplo, o certificado HTTPS.
OBS: Já vi casos em que é o token é substituido por um usuário e senha, mas isso é exceção e não é recomendado pela especificação.
API Keys é um método de autenticação que teoricamente veio para resolver alguns problemas do modelo de Basic Authentication.
A ideia do método de API Keys é simples. O servidor gera uma chave de acesso única para o client, e para utilizar a API, o client envia essa chave única em toda requisição.
É um método bem simples e rápido de ser implementado, e durante anos foi o método mais utilizado pelos desenvolvedores.
A grande questão é que esse método serve apenas para autenticação, e não para autorização. Ou seja, em teoria um usuário com uma Key válida tem acesso a todas as operações de uma API.
Além disso, ela funciona como qualquer requisição HTTP, e se algum ponto de rede estiver inseguro, ela pode ser facilmente interceptada e utilizada para acesso indevido da API.
Normalmente essa key é utilizada no header. Por exemplo, imagine que você recebeu do servidor a seguinte key: “thi123456”, nesse sentido para eu me autenticar na API, eu faria uma requisição com o seguinte header:
Api-key: thi123456
Vale ressaltar que o parâmetro de header pode variar de acordo com a API. Ou seja, pode ser “x-Api-key” por exemplo, ou então, pode ser que o envio dessa key seja via Query String, e não pelo header. O que é algo menos seguro ainda, pois fica extremamente visível para quem vai atacar.
O OAuth está na sua versão 2.0, e não é apenas um método de autenticação, e sim um protocolo completo com diversas especificações de segurança.
Ele é extremamente útil para o processo de autenticação e autorização, e por isso, atualmente é o método mais recomendado para o cenário de APIs.
Vamos entender alguns conceitos básicos do OAuth 2:
Para entender melhor, vamos supor que você desenvolveu uma aplicação que utiliza dados do usuário do Facebook. Portanto, vamos simular como seria um fluxo básico de autenticação via OAuth 2.0:
Como é um assunto denso, vou deixar aqui o link de um ótimo artigo que explica em detalhes esse protocolo.
Outros assuntos acerca da especificação do oAuth e que são interessantes para implementação:
OpenID Connect: Extensão da funcionalidade de autenticação do OAuth. Como o OAuth foi projetado para autorização, o OpenID Connect acaba sendo um ótimo complemento na segurança de APIs, conseguindo ajudar no sentido de provar que o usuário é realmente quem ele diz que é.
JWT: Formato de token seguro que utiliza JSON como base.
Temos também o SAML, ou Security Assertion Markup Language. O SAML é um padrão aberto que permite que provedores de identidade (IDP) passem credenciais de autorização para provedores de serviços (SP).
Em outras palavras, o usuário pode usar as mesmas credenciais para entrar em aplicações diferentes.
Na prática, o SAML ativa o Single Sign-On (SSO), algo bem interessante para a experiência dos usuários. Com ele, é possível fazer o login uma única vez e assim conseguir navegar em todas as aplicações com o padrão implementado.
Não vejo outro cenário de aplicação do SAML além de casos que o login único seja premissa, pois ele utiliza o XML na comunicação. O XML já é algo ultrapassado para o desenvolvimento WEB que estamos vivendo atualmente.
Se quiser entender mais sobre as diferenças e casos de uso comparados ao OAuth, leia esse artigo.
Em uma visão direta ao ponto, essas são as principais recomendações de segurança para a grande maioria dos cenários de APIs RESTful:
Pense sempre na experiência do desenvolvedor que irá consumir. Muitas APIs perdem engajamento da comunidade pela complexidade no consumo devido a implementações de segurança.
Essa é uma dica básica de segurança na WEB para você manter as mensagens trafegadas seguras e criptografadas, dificultando qualquer interceptação da requisição.
É natural que haja uma queda de performance, porém, se você estiver utilizando HTTP 2 existem diversos workarounds de otimização.
Uma má prática comum é a passagem de dados relativos a segurança via URL. Por exemplo:
GET https://api.test.com/orders?apiKey=thiago1234
Isso facilita muito a vida de alguém com más intenções na sua API.
O OAuth hoje é sem dúvidas a especificação mais completa para APIs RESTful. Por isso, utilize tudo que há de melhor no OAuth, apenas tomem muito cuidado para não deixar a implementação muito complexa e assim impactar negativamente a experiência do desenvolvedor que irá consumir sua API.
Essa é uma prática interessante que pode ajudar a prevenir ataques que focam em deixar sua infraestrutura indisponível por uma quantidade alta de requisições.
Com a implementação desse header você consegue restringir o número de requisições do client.
Com a implementação, você sempre retorna os seguintes headers na resposta de uma requisição:
Além disso, em casos que o client ultrapasse o limite de requisições, você retorna o status code 429 — Too Many Requests.
Se for uma API em que segurança é um ponto crítico, uma boa dica é criar um header customizado com o timestamp. Assim, o server pode comparar o timestamp atual, e aceitar apenas as requisições que estiverem próximas a um período de tempo (por exemplo: 2 minutos).
Isso é um procedimento simples, e que pode prevenir ataques básicos de replay em tentativas de força bruta.
Por questões de segurança, sempre valide os paramêtros da requisição antes da execução da lógica do negócio.
Caso a requisição esteja com parâmetros não especificados na sua documentação, rejeite imediatamente a requisição.Isso pode ser indício de um ataque malicioso.
Além disso, para não impactar negativamente a experiência de quem não está mal intencionado, retorne mensagens de erros claras sobre o assunto. Sempre disponibilize exemplos da requisição feita corretamente.
Existem diversas ferramentas que facilitam as implementações dessas recomendações centralizando toda a inteligência de segurança em uma camada específica de arquitetura.
Nesse desenho conseguimos entender esse modelo:
Algumas ferramentas recomendadas para essa arquitetura: LinkApi, Kong e WSO2 e Apigee.
E é isso aí, amigos e amigas developers. Encerramos mais um artigo sobre APIs RESTFul com um tema importantíssimo que é segurança. Gostou?