Logo Logo
GitHub Designed by Logto

O que é um JSON Web Token (JWT)?

JSON Web Token (JWT) é amplamente utilizado em aplicações web modernas e padrões abertos como OpenID Connect, facilitando a autenticação (authentication) e autorização (authorization). Embora o RFC 7519 oficial sirva como uma referência essencial, pode ser desafiador para iniciantes entenderem. Neste artigo, vamos nos concentrar nos conceitos principais do JWT e apresentá-los em linguagem simples com exemplos.

Por que precisamos de JWT?

Hoje em dia, é bastante comum usar JSON para trocar dados entre duas partes. Considere um objeto JSON representando um usuário:

{
  "sub": "foo",
  "name": "John Doe"
}

sub é a abreviação de “subject”, que é uma claim padrão no OpenID Connect para representar o identificador do usuário (ID do usuário).

Como podemos garantir a integridade deste objeto JSON? Em outras palavras, como podemos ter certeza de que os dados não foram alterados durante a transmissão? Uma solução comum é usar assinaturas digitais. Por exemplo, podemos usar criptografia de chave pública : o servidor assina o objeto JSON com sua chave privada, e o cliente pode verificar a assinatura com a chave pública do servidor.

Em resumo, o JWT oferece uma abordagem padronizada para representar o objeto JSON e sua assinatura.

O JWT também pode ser usado para criptografar o objeto JSON, mas esse não é o foco deste artigo.

O formato do JWT

Como existem muitos algoritmos para criar assinaturas digitais, é necessário especificar o algoritmo usado para assinar o JWT. Isso é feito construindo um objeto JSON:

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

alg é a abreviação de “algorithm”, e typ é a abreviação de “type”.

Normalmente, typ é definido como JWT em maiúsculas. Para nosso exemplo, alg é HS256, que significa HMAC-SHA256 (explicaremos em breve), e indica que estamos usando este algoritmo para criar a assinatura.

Agora, temos todos os ingredientes para um JWT:

  • Header JSON: Algoritmo e tipo
  • Payload JSON: Os dados reais
  • Assinatura: A assinatura que abrange o header e o payload

No entanto, certos caracteres como espaços e quebras de linha não são amigáveis para transmissão em rede. Portanto, o header e o payload precisam ser codificados em Base64URL. O JWT típico se parece com isso:

{{header}}.{{payload}}.{{signature}}

O . serve como delimitador.

Vamos juntar tudo e criar um JWT:

JSON: {"alg":"HS256","typ":"JWT"}

Codificado em Base64URL: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

JSON: {"sub":"foo","name":"John Doe"}

Codificado em Base64URL: eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ

Assinatura

No HMAC-SHA256, a assinatura é criada com um segredo:

HMAC-SHA256(base64Url(header) + "." + base64Url(payload), secret)

Por exemplo, com o segredo como some-great-secret, a assinatura se torna: XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g.

JWT

O JWT final é:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ.XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g

Este JWT válido pode ser verificado por qualquer parte que possua o segredo.

Escolha do algoritmo de assinatura

Como mencionado anteriormente, existem vários algoritmos para criar assinaturas digitais. Usamos HS256 como exemplo, mas pode não ser forte o suficiente, pois o segredo deve ser compartilhado entre as partes (por exemplo, o cliente e o servidor).

Em cenários do mundo real, os clientes podem incluir aplicativos públicos como aplicativos React que não podem manter o segredo seguro. Consequentemente, a abordagem preferida envolve a utilização de criptografia de chave pública (ou seja, criptografia assimétrica) para assinar o JWT. Vamos começar com o algoritmo mais popular: RSA .

RSA

RSA, um algoritmo assimétrico, usa um par de chaves: uma chave pública e uma chave privada. A chave pública é usada para verificar a assinatura, enquanto a chave privada é usada para assinar.

O header JSON para RSA se parece com isso:

{
  "alg": "RS256",
  "typ": "JWT"
}

RS256 significa RSA-SHA256, o que significa que a assinatura é criada com o algoritmo RSA e a função hash SHA256. Você também pode usar RS384 e RS512 para criar assinaturas com as funções hash SHA384 e SHA512, respectivamente.

A assinatura é criada com a chave privada:

RSA-SHA256(base64Url(header) + "." + base64Url(payload), privateKey)

Novamente, podemos montar essas partes para criar um JWT, e o JWT final se parece com isso:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ.{{signature}}

Agora, o cliente pode verificar a assinatura sem conhecer a chave privada.

ECDSA

Embora o RSA seja amplamente adotado, ele sofre com tamanhos de assinatura maiores, às vezes ultrapassando o tamanho combinado do header e do payload. O Algoritmo de Assinatura Digital de Curva Elíptica (ECDSA) é outro algoritmo assimétrico que pode criar assinaturas mais compactas e é mais eficiente.

Para gerar uma chave privada para ECDSA, precisamos escolher uma curva. Isso está fora do escopo deste artigo, mas você pode encontrar mais informações aqui .

O header JSON para ECDSA se parece com isso:

{
  "alg": "ES256",
  "typ": "JWT"
}

ES256 significa ECDSA-SHA256, o que significa que a assinatura é criada com o algoritmo ECDSA e a função hash SHA256. Você também pode usar ES384 e ES512 para criar assinaturas com as funções hash SHA384 e SHA512, respectivamente.

A assinatura é criada com a chave privada:

ECDSA-SHA256(base64Url(header) + "." + base64Url(payload), privateKey)

O JWT final mantém a mesma estrutura do RSA, mas com uma assinatura significativamente mais curta:

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ.{{signature}}

Verificar o JWT

Verificar um JWT é simples, como o processo inverso de criar um JWT:

  1. Divida o JWT em três partes (header, payload e assinatura) usando o delimitador ..
  2. Decodifique o header e o payload com Base64URL.
  3. Verifique a assinatura com o algoritmo especificado no header e a chave pública (para algoritmos assimétricos).

Existem muitas bibliotecas disponíveis para auxiliar na verificação de JWT, como jose para Node.js e navegadores web.

Veja também