Wednesday, March 17, 2021

Autorização JWT Puro Java: parte 1

Este artigo pretende ilustrar a aplicação de autenticação JWT em RESTFUL web services em java simples (sem lib de terceiros). Na parte 2 criamos um exemplo prático

Visão Geral

JWT é uma especificação aberta (RFC 7519) usada para gerenciar autorização e troca de informações de uma maneira segura e stateless, isto é, o servidor não mantem informações relacionadas à sessão do cliente. Este é o cenário ideal no contexto mais utilizado hoje com boa parte da comunicação  ocorrendo via Restful APIs, dessa forma o escalonamento horizontal dos serviços pode ocorrer sem nenhum empecilho (no que tange aos aspectos relacionados à sessão do usuário).



JWT Workflow

O diagrama de sequencia abaixo ilustra de forma geral o fluxo em serviços baseados em autenticações JWT. Um enpoint de autentição recebe as credenciais do cliente, as verifica, caso válidas, emite um token específico com prazo de validade para aquele cliente específico:



Quando for acessar os demais serviços, o cliente deve apresentar o token recebido na requisição anterior, um filtro intercepta a requisição, confere o token, e libera o acesso ao serviço se for o caso.



Segurança

Embora também possa garantir confidencialidade, desde que transmitido via HTTPS, o foco da especificação JWT é validação, ou seja, deve responder à pertgunta: os dados apresentados foram alterados indevidamente? 

Para assegurar essa proposta, a RFC 7519 especifica que deve-se utilizar um Message Authentication Code (MAC) para assinar o token. MACs são reconhecidamente usados para assegurar  integridade e autenticidade durante a troca de mensagens. Há vários algoritmos que implementam o MAC, o que utilizaremos será HMAC-SHA256. 

Um token JWT é composto por 3 objetos JSON concatenados:

  • Header: contém o algoritmo usado para gerar o MAC e o tipo de token
  • Payload: pode conter qualquer informação pertinente as regras de negócio, além de elementos registrados pela RFC 7519, como iss (quem gerou o token), exp (validade), iat (quando foi gerado), sub (assunto), etc.
  • Assinatura: é o resultado da aplicação do MAC ao Header e Payload concatenados.
Antes de processar cada objeto, eles devem ser convertidos em base64 URL safe de modo que o token não seja comrrompido durante o envio pela internet. Exemplo:

HEADER

{"alg":"HS256","typ":"jwt"} 

base64 aplicada
 eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9


PAYLOAD

{"scope":"read_only","iss":"rafael.senior.engineer","name":"daniel","exp":1615718739,"iat":1615718679,"jti":"d970fea6-78ce-4724-b35a-37c49b01a832"} 

base64 aplicada
eyJzY29wZSI6InJlYWRfb25seSIsImlzcyI6InJhZmFlbC5zZW5pb3IuZW5naW5lZXIiLCJuYW1lIjoiZGFuaWVsIiwiZXhwIjoxNjE1NzE4NzM5LCJpYXQiOjE2MTU3MTg2NzksImp0aSI6ImQ5NzBmZWE2LTc4Y2UtNDcyNC1iMzVhLTM3YzQ5YjAxYTgzMiJ9


ASSINATURA

Concatene-se o header e o payload anteriores, aplica-se ao resultado a função MAC:

        HMAC-SHA256(header +"."+ payload)

Converta o resultado da função MAC em base64:
eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJzY29wZSI6InJlYWRfb25seSIsImlzcyI6InJhZmFlbC5zZW5pb3IuZW5naW5lZXIiLCJuYW1lIjoiZGFuaWVsIiwiZXhwIjoxNjE1NzE4NzM5LCJpYXQiOjE2MTU3MTg2NzksImp0aSI6ImQ5NzBmZWE2LTc4Y2UtNDcyNC1iMzVhLTM3YzQ5YjAxYTgzMiJ9.m5zc-JoYEn2fGY44iJfLJjN8si1MPw934My42VAPaFs


JWT final:

    header.payload.assinatura

eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJzY29wZSI6InJlYWRfb25seSIsImlzcyI6InJhZmFlbC5zZW5pb3IuZW5naW5lZXIiLCJuYW1lIjoiZGFuaWVsIiwiZXhwIjoxNjE1NzE4NzM5LCJpYXQiOjE2MTU3MTg2NzksImp0aSI6ImQ5NzBmZWE2LTc4Y2UtNDcyNC1iMzVhLTM3YzQ5YjAxYTgzMiJ9.eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJzY29wZSI6InJlYWRfb25seSIsImlzcyI6InJhZmFlbC5zZW5pb3IuZW5naW5lZXIiLCJuYW1lIjoiZGFuaWVsIiwiZXhwIjoxNjE1NzE4NzM5LCJpYXQiOjE2MTU3MTg2NzksImp0aSI6ImQ5NzBmZWE2LTc4Y2UtNDcyNC1iMzVhLTM3YzQ5YjAxYTgzMiJ9.m5zc-JoYEn2fGY44iJfLJjN8si1MPw934My42VAPaFs

Conforme dito no início, este artigo não pretende ser uma explicação exaustiva sobre JWT, o objetivo é ilustrar sua aplicação prática em java simples (sem lib de terceiros), caso queira se aprofundar, consulte a documentação oficial.

Na parte 2 criaremos uma API no container Wildfly com o seguintes serviços:


Eles só poderão ser acessados através de um token, com validade determinada, segundo os fluxos apresentados no começo do artigo.



       

No comments:

Post a Comment