Maurício Santos
Jul 29 · 7 min read

Introdução

Um dos desafios de se criar uma aplicação baseada em uma arquitetura de microsserviços, em que componentes com um micro escopo devem ser independentes entre si, é realizar a autenticação de todos os requests que chegam aos diversos microsserviços que compõem a aplicação.

Realizar a autenticação consiste em verificar se o request que chega ao API Gateway deve ser encaminhado ao microsserviço para ser processado, ou se este request deve ser respondido com status HTTP 401 — Unauthorized.

A AWS fornece serviços para a implementação de uma solução de autorização para microsserviços de forma centralizada, escalável, cacheavel e plug’n’play.

Neste artigo, vou explicar os conceitos envolvidos e os detalhes de implementação ao adotar um Autenticador Customizado do AWS API Gateway.


Autenticação vs. Autorização

Antes de seguir em frente, dois conceitos precisam estar bem claros: A diferença entre Autenticação e Autorização.

Autenticação: é o processo de identificar quem é o usuário. O caminho mais comum para se autenticar usuários é através de solicitação de login e senha. Mas também pode ser feito através de single sign-on (login com google, facebook, …), biometria, por mensagem SMS, etc.

Autorização: é o processo onde, uma vez que já se sabe quem é o usuário, é realizada uma verificação se este usuário pode acessar um determinado recurso, que pode ser uma página HTML, um REST endpoint, um arquivo do servidor, um recurso na AWS…


Implementando a Autenticação

Existem inúmeras soluções para realizar a autenticação de usuários. É possível fazer isso de maneira bem simples apenas solicitando login e senha ou até fazendo uma leitura biométrica.

Para uma determinada aplicação, escolhemos utilizar a integração com a plataforma Auth0. Atenção! Auth0 é uma solução comercial de autenticação, com diversas complexidades já abstraídas, apenas plugar e usar. Não confunda Auth0, que é uma solução comercial, com OAuth2, que é um padrão de arquitetura de soluções de autenticação.

No lugar do Auth0, poderíamos desenvolver um serviço que identifica um usuário pelo seu login e senha e retorna um JWT. Por mais trivial que pareça em um primeiro momento, é uma implementação complexa que precisa seguir diversas boas práticas de segurança.

Após implementada a integração com a plataforma Auth0, é possível saber QUEM está tentando acessar a nossa aplicação. Os detalhes de como implementar a integração com Auth0 você pode conferir na documentação oficial.

O Auth0 permite diversas customizações, uma delas é a implementação de uma Regra (Rule), que é um código javascript executado durante o processo de autenticação. Com isso é possível implementar regras de negócio específicas no processo de autenticação, e incluir no retorno do Auth0 (dentro do token JWT) alguns parâmetros específicos das regras de negócio da nossa aplicação.

Também é possível guardar alguns dados relacionados ao usuário no Auth0, com a finalidade desses dados serem enviados dentro do JWT. No Auth0, esses dados são conhecidos como user metadata.

Uma vez que o Auth0 autenticou o usuário e pode garantir à nossa aplicação qual é o usuário logado, ele nos retorna um JWT, contendo parâmetros genéricos, como por exemplo: login, senha, quantas vezes já realizou login, e parâmetros específicos como por exemplo o id do usuário na nossa aplicação.

Neste ponto, recebemos na nossa aplicação um JWT com algumas informações do usuário como nome, email, id do usuário no Auth0, id do usuário na nossa aplicação, quantos acessos este usuário já fez ao sistema, etc.

Você pode estar se perguntando: “Como essa solução é segura, se o JWT pode ser facilmente simulado?”. No próximo tópico, explico como fechamos essa brecha, entre outros detalhes da Autorização.


Implementando a Autorização

Neste ponto a nossa SPA no frontend já sabe quem é o usuário e algumas outras informações a seu respeito, que estão contidas dentro do JWT. Agora a SPA vai precisar enviar requisições para a aplicação do backend que fornecem as funcionalidades da aplicação. Mas temos 2 problemas de autorização:

  • Como saber se o JWT que estamos recebendo é um JWT genuíno, gerado pelo Auth0?
  • Como validar se o usuário que acessa um determinado recurso no Backend tem permissão para acessar tal recurso?

Validando o JWT

A nossa aplicação de backend consiste em vários componentes AWS, como lambdas e EC2 containers, que fornecem suas funcionalidades através de REST APIs e estão disponibilizadas na Web através do API Gateway.

O AWS API Gateway oferece algumas formas de implementar um esquema de autorização dos HTTP Requests que chegam ao gateway.

A solução que escolhemos para implementar a validação e outras regras de negócio da autorização foi a implementação de um Lambda Autorizador. Como o próprio nome sugere, a função que executa a autorização habita em um AWS Lambda que é apontado no API Gateway como um Lambda Autorizador, e toda vez (nem toda vez, podemos usar cache! Falo mais a frente) que o API Gateway recebe um request este Lambda é executado para validar e autorizar o JWT que é enviado junto com o request.

Note que é possível configurar um “Authorization Caching”, ou seja, cache para o seu autorizador, evitando que o lambda autorizador seja executado em todo request, reduzindo custos com este lambda e tempo de resposta dos seus endpoints.

O código do Lambda Autorizador fica assim: https://gist.github.com/msantos-sw/3b4de84ddd16451435024ce0b6141a12

Portanto, se o autorizador validar o acesso do usuário ele terá acesso ao microsserviço, caso contrário, o request não chega ao microsserviço e o API Gateway responde ao request com status code 401.

Neste ponto, já sabemos quem é o usuário, se o seu token JWT é válido e já fizemos as primeiras validações de autorização, além da validação do token (código acima, na função userIsAuthorized).

Enviando os dados do JWT para os microsserviços

O API Gateway permite que os dados incluídos no atributo context da policy (código acima, função buildPolicy) seja mapeado para o request encaminhado aos microsserviços.

Se o microsserviço é um lambda e está configurado para receber as requisições via lambda proxy, os dados do contexto da autorização são automaticamente incluídos dentro da variável event: event.requestContext.

Se o microsserviço é uma aplicação hospedada em um EC2, mapeada dentro do API Gateway como um {proxy+}, é possível mapear os atributos do contexto da autorização para o HTTP Request, tanto para os headers, como para os query strings do request.

Dependendo do microserviço, validações específicas de autorização precisarão ser implementadas antes da execução do serviço requisitado, como por exemplo, validações que verificam se o usuário em questão tem permissão para acessar determinado recurso de acordo com o seu perfil.

Resolver essa questão, com a solução que já temos é bem simples, considerando que os dados do usuário chegam ao seu microsserviço, é possível fazer a validação dentro do próprio microsserviço ou requisitando um microsserviço apartado de autorização por permissões, passando como parâmetro o id do usuário e o recurso que o usuário pretende acessar.


Utilizar a integração com Auth0, JWT, API Gateway e um Lambda Autorizador é possível implementar uma camada de autenticação e autorização para os seus microserviços sem muito esforço, seguindo várias boas práticas de segurança e de maneira bem abstrata e desacoplada dos próprios microserviços.

No próximo, artigo ainda relacionado à este assunto, vou detalhar aspectos que reforçam a segurança do token JWT e mostrar alguns desafios que encontramos durante essa implementação e as soluções providenciadas.


Meu nome é Mauricio Santos, Engenheiro de Software em constante formação há 8 anos. Minha praia é Java e Javascript e estou curtindo muito desbravar soluções em Cloud.

Ficou alguma dúvida? Me chama nos comentários. ⬇
Você também me encontra aqui. 😉 Forte abraço e até logo.


A Mobicare combina os Melhores Talentos, Tecnologias de Ponta, Práticas Agile e DevOps com Capacidades Operacionais avançadas para ajudar Operadoras Telecom a gerar novas receitas e a melhorar a experiência dos seus próprios clientes.

Se você gosta de inovar, trabalhar com tecnologia de ponta e está sempre buscando conhecimento, somos um match perfeito!

Vem trabalhar com a gente 😉 bit.ly/mobicarreiras

mobicareofficial

Se você gosta de inovar, trabalhar com tecnologia de ponta e está sempre buscando conhecimento, somos um match perfeito! Vem trabalhar com a gente 😉 bit.ly/mobicarreiras

Maurício Santos

Written by

Engenheiro de Software em constante formação. Minha praia é Java, SpringBoot, Javascript, Node e React. Curtindo muito desbravar soluções em Cloud.

mobicareofficial

Se você gosta de inovar, trabalhar com tecnologia de ponta e está sempre buscando conhecimento, somos um match perfeito! Vem trabalhar com a gente 😉 bit.ly/mobicarreiras

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade