Protege os teus recursos de API para comunicação entre máquinas
Aprende como utilizar OAuth 2.0 e JWT para proteger os teus recursos de API para comunicação entre máquinas.
Aprende como utilizar OAuth 2.0 e JWT para proteger os teus recursos de API para comunicação entre máquinas.
Ao construir um projeto que envolve múltiplos serviços, a segurança dos recursos de API é uma preocupação crítica. Neste artigo, vou mostrar-te como utilizar OAuth 2.0 e JWT para proteger a comunicação entre serviços (máquina-a-máquina), e como aplicar controlo de acesso baseado em funções (RBAC) para seguir o princípio do privilégio mínimo.
Para seguir em frente, assumo que tens os seguintes pré-requisitos:
Para fins de demonstração, suponhamos que temos os seguintes serviços:
https://cart.example.com/apihttps://payment.example.com/apiAgora, o nosso serviço de carrinho precisa chamar o serviço de pagamentos para processar pagamentos. O fluxo de autenticação é o seguinte:
Alguns conceitos-chave no diagrama acima:
Cada participante no diagrama acima tem um papel para desempenhar no fluxo de autenticação:
Vamos passar pelo fluxo de autenticação passo a passo.
Para realizar o fluxo de autenticação, precisamos criar uma aplicação máquina-a-máquina (serviço de carrinho) e um recurso de API (serviço de pagamentos) no Logto.
Como o nosso serviço de carrinho precisa estar ciente da API do serviço de pagamentos ao realizar a autenticação, precisamos criar um recurso de API primeiro. Vai ao Console Logto, clica em API resources na barra lateral esquerda, e clica em Create API resource. No diálogo aberto, oferecemos alguns tutoriais para te ajudar a começar. Podes também clicar em Continue without tutorial para ignorá-lo.
Insere o nome e o identificador da API, por exemplo, Serviço de Pagamentos e https://payment.example.com/api, depois clica em Create API resource.
Após criar o recurso de API, serás redirecionado para a página de detalhes. Podemos deixá-la como está por agora.
Clica em Applications na barra lateral esquerda, e clica em Create application. No diálogo aberto, encontra o cartão Machine-to-machine, depois clica em Start building.
Insere o nome da aplicação, por exemplo, Serviço de Carrinho, e clica em Create application. Um guia interativo será mostrado para ajudar-te a configurar a aplicação. Podes seguir o guia para entender o uso básico, ou clicar em Finish and done para ignorá-lo.
Como se assume que as aplicações máquina-a-máquina são seguras (por exemplo, estão implantadas numa rede privada), podemos usar a concessão "client_credentials" do OAuth 2.0 para obter um token de acesso. Usa autenticação básica para autenticar o cliente:
POST.Content-Type do pedido é application/x-www-form-urlencoded.Authorization, o valor é Basic <base64(app_id:app_secret)>, onde app_id e app_secret são o ID da aplicação e o segredo da aplicação da aplicação máquina-a-máquina, respetivamente. Podes encontrá-los na página de detalhes da aplicação.grant_type=client_credentials&resource=https://payment.example.com/api.
grant_type=client_credentials: O valor constante para a concessão "client_credentials".resource=https://payment.example.com/api: O identificador da API do recurso de API que o cliente deseja acessar.scope=read:payment write:payment. Vamos cobrir escopos mais tarde.Aqui está um exemplo do pedido usando curl:
Um corpo de resposta bem-sucedido seria assim:
Agora temos o token de acesso, e podemos adicioná-lo ao cabeçalho Authorization do pedido para o recurso de API. Por exemplo, se quisermos chamar a API POST /payments do serviço de pagamentos, podemos enviar o seguinte pedido:
Podes notar que o serviço de pagamentos precisa validar o JWT usando o conjunto de JWK, e pode ter um cache do conjunto de JWK local para evitar buscar o conjunto de JWK do Logto toda vez. Felizmente, devido à popularidade do JWT, existem muitas bibliotecas que podem ajudar-te a alcançar o objetivo com algumas linhas de código.
Essas bibliotecas são geralmente chamadas "jose" (JavaScript Object Signing and Encryption) ou "jsonwebtoken". Por exemplo, no Node.js podemos usar jose para validar o JWT:
Se a validação for bem-sucedida, a variável payload será o payload decodificado do JWT. Caso contrário, um erro será lançado.
Agora protegemos com sucesso a comunicação entre o serviço de carrinho e o serviço de pagamentos. No entanto, o fluxo de autenticação apenas garante que o cliente é o verdadeiro serviço de carrinho, mas não garante que o serviço de carrinho tem permissão para realizar ações no serviço de pagamentos.
Digamos que queremos permitir que o serviço de carrinho crie pagamentos, mas não leia pagamentos.
No Logto, "escopos" e "permissões" são intercambiáveis. Vai à página de detalhes do recurso de API do serviço de pagamentos, e navega até à aba Permissions. Deve estar vazia agora. Clica em Create permission, insere read:payment como o nome da permissão, e insere Read payments como a descrição da permissão. Depois clica em Create permission.
Repete os passos acima para criar outra permissão com o nome write:payment e a descrição Create payments.
Uma função é um grupo de permissões. No Logto, as aplicações máquina-a-máquina podem ser atribuídas funções para conceder permissões. Clica em "Roles" na barra lateral esquerda, e clica em Create role.
checkout como o nome da função, e insere Serviço de Checkout como a descrição da função.write:payment.


Além dos parâmetros de corpo de pedido que mencionamos em Solicitar token de acesso, podemos também especificar os escopos no corpo do pedido. Por exemplo, se quisermos solicitar a permissão write:payment, podemos enviar o seguinte pedido:
Para solicitar múltiplos escopos, podes separá-los com espaços. Por exemplo, scope=write:payment read:payment.
Se uma ação precisar da permissão write:payment no serviço de pagamentos, podemos validar os escopos ao afirmar que a declaração scope do payload do JWT:
Se quiseres proteger o acesso ao serviço de carrinho, podes também aplicar o mesmo fluxo de autenticação. Desta vez, o serviço de carrinho é o recurso de API, e o cliente é outro serviço que precisa de acessar.
Com o Logto, os teus recursos de API estão protegidos com OAuth 2.0 e JWT, e podes seguir o princípio do privilégio mínimo ao aplicar controlo de acesso baseado em funções. Além disso, podes também usar o Logto para gerir os teus utilizadores e as suas permissões, e até integrar com fornecedores de identidade de terceiros.