Iniciando com JWT (JSON Web Token)

Iniciando com JWT (JSON Web Token)

Seja bem-vindo(a) ao mundo dos JSON Web Tokens, também conhecidos como JWTs!

JWT (JSON Web Token) é um padrão aberto que permite transmitir informações de forma segura entre diferentes partes usando um formato compacto e autônomo em formato JSON. É amplamente usado para autenticação e autorização em aplicativos da web e APIs. Neste artigo, vamos explorar o que é JWT, como ele funciona, suas vantagens e desvantagens, possíveis vulnerabilidades, quando devemos utilizar e as melhores práticas para implementá-lo.

Vamos lá!

Introdução aos JSON Web Tokens (JWT)

Você já ouviu falar dos JWTs? Eles são como mensagens secretas que são transmitidas entre diferentes partes na forma de um objeto JSON compacto. É como se você estivesse enviando um bilhete secreto para um amigo, mas em vez de um pedaço de papel, você usa um JSON!

Agora, esses JWTs são muito úteis em aplicações web e APIs. Eles são usados principalmente para autenticação e autorização. Quando você quer se autenticar em um site ou aplicativo, geralmente precisa fornecer um nome de usuário e uma senha, certo? O que o servidor faz é verificar essas informações e, se estiverem corretas, ele cria um JWT especial para você.

Esse JWT contém informações sobre você, como seu ID de usuário e talvez até seu nome. Mas o que é legal sobre os JWTs é que eles são autocontidos. Isso significa que todas as informações necessárias estão contidas dentro do próprio JWT, e assim não é preciso ficar consultando um banco de dados ou algum outro lugar para obter os detalhes, tudo está ali!

E como o JWT é compacto, ele pode ser facilmente transmitido pela internet. É como se você enviasse uma mensagem importante em um envelope pequeno e seguro. Eles podem ser enviados como parte das solicitações que você faz ao servidor ou até mesmo incluídos em URLs.

Agora, vamos entender mais sobre a sua estrutura e como isso funciona de fato!

Estrutura do JWT

Antes de mergulharmos nos detalhes, é importante entender como um JWT é construído.

Um JWT consiste em três partes principais: o cabeçalho (header), a carga útil (payload) e a assinatura (signature). Essas partes são codificadas e colocadas juntas com pontos para formar o JWT completo.

1. Cabeçalho (Header): O cabeçalho contém informações sobre o JWT, como o tipo de token (typ) e o algoritmo de assinatura (alg). O campo typ especifica o tipo do token, que geralmente é definido como "JWT". O campo alg identifica o algoritmo usado para assinar o token. Existem diferentes algoritmos disponíveis, como HMAC SHA256 ou RSA, que são usados para criar essa assinatura especial. É como escolher qual carimbo usar para garantir que o JWT seja válido e confiável.

Um exemplo de cabeçalho de JWT:


2. Carga Útil (Payload): A carga útil transporta as declarações (claims), que são afirmações sobre uma entidade (por exemplo, usuário) e metadados adicionais. As declarações podem ser classificadas em três tipos: declarações registradas (registered claims), declarações públicas (public claims) e declarações privadas (private claims).

Vamos ver alguns exemplo:

  • Declarações registradas: São declarações predefinidas recomendadas pela especificação JWT, que incluem iss (emissor), sub (assunto), exp (hora de expiração) e iat (hora de emissão).
  • Declarações públicas: São declarações personalizadas feitas pelos usuários dos JWTs. Elas podem conter informações específicas e são definidas pelo próprio usuário. Essas declarações podem ser criadas seguindo duas opções:

1.1 Definindo-as no Registro JSON Web Token da IANA: Existem algumas declarações comuns já definidas que você pode usar.

1.2  Definindo-as como um endereço na internet (URI) que seja único e não gere conflitos com outros identificadores.

  • Declarações privadas: São declarações personalizadas específicas de uma aplicação ou organização. Elas são usadas para compartilhar informações entre as partes que concordam com o que essas declarações significam. Em outras palavras, as declarações privadas são como segredos compartilhados entre um grupo seleto de pessoas ou sistemas que entendem o seu significado. Elas permitem que você adicione informações especiais ao seu JWT para atender às necessidades específicas da sua aplicação ou organização.


3. Assinatura (Signature): A assinatura é criada combinando o cabeçalho codificado (header), a carga útil codificada (payload) e uma chave secreta usando o algoritmo especificado. A assinatura garante a integridade e autenticidade do token. Ela pode ser usada pelo destinatário para verificar a autenticidade do token e detectar qualquer tentativa de adulteração.

Um exemplo de assinatura de JWT (usando o algoritmo HMAC SHA256):

O cabeçalho codificado, a carga útil codificada e a assinatura são concatenados com pontos para formar o JWT final.

Como o JWT Funciona

Agora que sabemos como é a estrutura do JWT, vamos entender como ele realmente funciona em um cenário comum: a autenticação de usuários e o controle de acesso em uma aplicação web.

1. Autenticação: Quando um usuário fornece suas credenciais (por exemplo, nome de usuário e senha) para o servidor, o servidor verifica as credenciais. Se as credenciais forem válidas, o servidor gera um JWT como token de autenticação.

2. Geração do Token: O servidor constrói uma carga útil (payload) contendo informações relevantes sobre o usuário, como o ID do usuário, nome de usuário e quaisquer declarações necessárias. Em seguida, o servidor assina a carga útil com uma chave secreta usando um algoritmo de assinatura especificado. O JWT resultante é retornado ao cliente como parte da resposta de autenticação.

Aqui está um exemplo em Node.js usando a biblioteca jsonwebtoken:


Neste exemplo, a biblioteca jsonwebtoken é usada para gerar um JWT. O objeto payload contém as declarações e informações relevantes sobre o usuário. A secretKey é uma chave compartilhada entre o servidor e o cliente, usada para assinar e verificar o token. A função jwt.sign assina a carga útil com a chave secreta (secretKey) e o JWT resultante é impresso no console.

3. Armazenamento do Token: O cliente normalmente armazena o JWT recebido de forma segura, como em um armazenamento local (local storage) ou em um cookie, para incluí-lo em solicitações subsequentes ao servidor.

4. Controle de Acesso: Quando o cliente deseja acessar um recurso protegido no servidor, ele inclui o JWT na solicitação, geralmente como um cabeçalho HTTP (por exemplo, Authorization: Bearer <JWT>).

5. Verificação do Token: O servidor recebe a solicitação e extrai o JWT do cabeçalho HTTP. Em seguida, ele verifica a assinatura do JWT usando a chave secreta. Se a assinatura for válida, o servidor decodifica a carga útil para obter as informações do usuário e realiza verificações adicionais, como a verificação do tempo de expiração, para garantir que o token ainda seja válido.

Agora a mesma biblioteca jsonwebtoken para verificar um JWT:


Neste exemplo, a função jwt.verify é usada para verificar o JWT. A variável token contém o JWT a ser verificado e a secretKey é a chave secreta compartilhada usada para assinar e verificar o token. Se a verificação for bem-sucedida, a carga útil decodificada é impressa no console.

6. Concessão de Acesso: Se o JWT for válido e todas as verificações passarem, o servidor concede acesso ao recurso solicitado, sabendo que o usuário foi autenticado.

Conseguimos entender que, os JWTs guardam informações de autenticação e autorização, permitindo acessar partes especiais de um site, sem precisar lembrar de tudo no servidor. São perfeitos para sistemas distribuídos e aplicativos modernos com várias partes trabalhando juntas, tornando-os adequados para sistemas distribuídos e arquiteturas de microsserviços.

Vantagens do Uso de JWT

Aqui estão os motivos pelos quais os JWTs são tão populares em aplicações da web e APIs:

1. Autossuficientes (Self-contained): Como mencionado anteriormente, os JWTs são autossuficientes, o que significa que todas as informações necessárias estão contidas neles mesmos. Eles eliminam a necessidade de consultar o banco de dados ou o servidor de autenticação em cada solicitação, reduzindo a sobrecarga do servidor e melhorando a escalabilidade.

2. Formato Compacto: O formato compacto do JSON é adequado para ambientes com largura de banda limitada, tornando os JWTs fáceis de serem transmitidos pela rede, seja como parte do cabeçalho HTTP ou na URL.

3. Seguros (Secure): Os JWTs podem ser assinados digitalmente usando algoritmos criptográficos seguros, como HMAC SHA256 ou RSA. Isso garante que os tokens não sejam adulterados durante a transmissão e que somente o servidor confiável possa criar e validar os tokens.

4. Uso em Vários Domínios (Cross-domain): Devido à sua natureza autossuficiente, os JWTs podem ser facilmente usados em vários domínios ou subdomínios. Isso é uma vantagem importante quando se trabalha com APIs públicas ou sistemas distribuídos.

5. Cache e Performance: Como os JWTs podem incluir um tempo de expiração (exp), os clientes podem fazer cache deles e evitar a necessidade de renovar o token a cada solicitação. Isso melhora o desempenho e reduz a carga nos servidores de autenticação.

6. Flexibilidade nas Declarações: Os JWTs permitem declarações públicas e privadas personalizadas, tornando-os flexíveis para atender às necessidades específicas de uma aplicação.

Desvantagens do Uso de JWT

Apesar das vantagens, os JWTs também têm algumas desvantagens e é importante considerá-las ao decidir usá-los:

1. Tamanho do Token: Como os JWTs armazenam informações diretamente no token, eles podem ficar grandes se muitos dados forem incluídos. Isso pode aumentar o tamanho da carga útil e, consequentemente, aumentar o tráfego de rede.

2. Segurança dos Tokens Armazenados no Cliente: Por padrão, os JWTs são armazenados no cliente (por exemplo, em cookies ou armazenamento local). Se um token for roubado ou comprometido, um invasor poderá usá-lo para acessar recursos protegidos. Para mitigar esse risco, é essencial usar mecanismos adequados de proteção de cookies e adotar práticas de segurança, como a renovação periódica do token.

3. Falta de Controle Centralizado: Os JWTs são autocontidos e assinados pelo servidor de autenticação. Isso significa que, se um token precisar ser revogado antes do tempo de expiração, não há um mecanismo de invalidação centralizado. A revogação exigirá estratégias adicionais, como listas de revogação (blacklists) ou uso de tokens de curta duração.

4. Dependência do Relógio do Cliente: A verificação do tempo de expiração do token é feita no cliente. Isso pode levar a problemas de sincronização do relógio, onde o tempo do cliente pode estar desatualizado e resultar em problemas de autenticação.

Possíveis Vulnerabilidades e Melhores Práticas

Embora os JWTs sejam uma opção popular para autenticação e autorização, eles também estão sujeitos a várias vulnerabilidades comuns, como:

1. Ataques de Força Bruta e Dicionário: Se a chave secreta usada para assinar os tokens for fraca, os atacantes podem tentar adivinhar a chave usando ataques de força bruta ou dicionário. Portanto, é essencial usar uma chave forte e complexa.

2. Exposição a Ataques XSS: Os JWTs armazenados em cookies podem ser vulneráveis a ataques de Cross-Site Scripting (XSS), onde um invasor pode roubar o token por meio de scripts maliciosos injetados em páginas do cliente. Para mitigar esse risco, é importante usar proteções adequadas contra XSS, como a configuração de políticas de segurança de conteúdo (Content Security Policy).

3. Vazamento de Informações Confidenciais: É crucial evitar incluir informações confidenciais ou sensíveis no corpo do JWT, já que ele é decodificado no cliente e pode ser lido por qualquer pessoa. Informações como senhas ou detalhes financeiros devem ser armazenadas no servidor, não no JWT.

4. Não Confie Somente no JWT para Autorização: Embora os JWTs possam conter declarações de autorização (por exemplo, níveis de acesso), não dependa exclusivamente do JWT para controlar o acesso aos recursos. Verifique as permissões e autorizações no servidor antes de conceder acesso.

5. Mantenha os Tokens com Duração Curta: Tokens com duração curta reduzem o risco de comprometimento a longo prazo, já que eles expiram após um curto período de tempo. Use tempos de expiração apropriados com base nos requisitos da aplicação.

Casos de uso

Os JWTs são amplamente utilizados em vários cenários, tais como:

  • Autenticação de Usuários: Ao realizar o login, um JWT é gerado e enviado ao cliente, permitindo que ele acesse recursos protegidos sem a necessidade de reenviar as credenciais em cada solicitação. Isso oferece uma experiência de autenticação mais eficiente, pois o cliente pode armazenar o token e enviá-lo em cada solicitação para provar sua identidade.

Exemplo de resposta de autenticação com JWT:

  • Autorização de Acesso: Os JWTs podem conter declarações de autorização, como níveis de acesso, permitindo que o servidor controle quais recursos o cliente pode acessar. Por exemplo, um JWT pode conter informações sobre a função do usuário (administrador, usuário comum, etc.) e o servidor pode verificar essas informações antes de conceder acesso a recursos sensíveis.

Exemplo de JWT com declaração de autorização:

  • Comunicação entre Microsserviços: Em ambientes de microsserviços, os JWTs são utilizados para autenticar e autorizar a comunicação entre diferentes serviços. Cada serviço pode gerar um JWT com informações relevantes sobre a origem da solicitação e enviá-lo para outros serviços para permitir a comunicação segura e confiável.

Exemplo de JWT usado na comunicação entre microsserviços

  • Sistemas Distribuídos: Em sistemas distribuídos, os JWTs permitem que diferentes partes da aplicação se comuniquem de forma segura e autônoma. Cada componente pode gerar um JWT contendo informações necessárias para a comunicação e, em seguida, enviar o token para outras partes para garantir a autenticidade e integridade dos dados trocados.

Exemplo de JWT usado em sistemas distribuídos

Esses são só alguns exemplos de como os JWTs podem ser utilizados em diferentes cenários. Sua versatilidade, segurança e capacidade de transporte de informações os tornam uma escolha super poderosa para autenticação e autorização em ambientes variados, desde aplicações web até sistemas distribuídos complexos.

Conclusão

Espero que agora você esteja se sentindo mais à vontade com o mundo dos JWTs! Eles são realmente uma poderosa ferramenta de autenticação e autorização em aplicações da web e APIs. Sua natureza autossuficiente, formato compacto e capacidade de assinatura digital os tornam uma escolha popular para sistemas distribuídos e ambientes de microsserviços. No entanto, é essencial entender as melhores práticas e vulnerabilidades potenciais para usá-los com segurança.

Antes de adotar o JWT, é recomendado avaliar os requisitos de segurança e os casos de uso específicos da aplicação. Ao tomar decisões bem informadas e seguir as melhores práticas de segurança, você pode garantir que os JWTs sejam usados efetivamente para proteger sua aplicação e dados sensíveis.

Espero que este artigo tenha sido informativo e útil! Se você tiver mais dúvidas ou precisar de mais esclarecimentos, sinta-se à vontade para perguntar.

Boas implementações com JSON Web Tokens! 🚀

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.