Você sabia que o formato JWT pode ser tanto um JWS quanto um JWE? E que o algoritmo mais recomendado para assinar um JWT é o ECDsa P-256 SHA-256 (ES256)? Veja neste artigo detalhes do JWT e como proteger melhor suas API's.

Formulas on an old blackboard

Json Web Token (JWT)

O JWT é o acronimo de JSON Web Token. É uma estrutura de dados no formato JSON. Ele é compacto e seguro. URL safe, ou esja, pode trafegar na URL sem prejudicar seu conteúdo.
O JWT pode ser comparado a uma classe abstrata. JWS e JWE são as implementações do JWT.

Seu conteúdo é composto por claims. As Claims são um conjunto de chave/valor. Fornecem ao client ou API informações sobre o usuário que está consumindo seus serviços.

Ele é amplamente utilizado para transferir dados através do protocolo HTTP. Entre clients frontends (SPA) e API's. Pode ser também utilizado para transferência de dados entre API's.

O JWT é uma estrutura JSON. As especificações sobre como criptografar ou assinar digitalmente um JWT é conhecido como Javascript Object Signing & Encription (JOSE). Ele é composto pelos seguintes componentes. E suas respectivas RFC's.

Acronimo Nomenclatura Detalhes
JWS Json Web Signature (RFC7515) Processo sobre como assinar digitalmente um JWT
JWE Json Web Encryption (RFC7516) Processo sobre como criptografar um JWT
JWK Json Web Key (RFC7517) Define uma estrutura JSON para representar uma chave de criptografia.
JWA Json Web Algorithm (RFC7518) Define os algoritmos válidos para assinar digitalmente ou criptografar um JWT

JOSE é um framework. Seu objetivo é fornecer um método seguro para transferir as claims com segurança. Garantindo que seu conteúdo não seja adulterado durante o transporte das informações.

Json Web Signature (JWS)

O JWS é o mais popular. Facilmente confundido como o própio JWT. Após assinar digitalmente o JWT, ele torna-se um JWS. O JWS é o conteúdo JWT com uma assinatura digital.

O que garante segurança ao JWS é sua assinatura digital. A assinatura é o resultado da criptografia da composição do Header & Paylooad.

Encrypt(header + '.' + payload, secret);

Meramente ilustrativo. O formato como deve ser feito está detalhado abaixo.

Dessa forma o conteúdo do JWT (Payload) é legivel, porém, qualquer alteração no conteúdo resultaria numa assinatura diferente.

A chave pública só permite acesso de leitura, por isso sua API ou Client frontend (SPA) consegue validar se o payload do JWT foi alterado. Garantindo confiabilidade e segurança ao consumidores.

Somente quem possui a chave privada consegue gerar uma assinatura válida para o JWT.

O JWS é composto por três seções.

  • Header
  • Payload
  • Digital Signature

Nesse caso, ECDSA-P256-S256 é a representação extensa do algoritimo utilizado no header (ES256).

O formato final do JWS é muito simples:

É a transformação para base64url dos componentes, separados por . (ponto).

jws

Json Web Encryption (JWE)

O JWE representa o conteúdo criptografado de um JWT. Assim como o JWS, possui uma estrutura de dados JSON própria:

  • Header
  • Chave Criptografada
  • Initialization Vector
  • Additional Authenticated Data (AAD)
  • Ciphertext
  • Authentication Tag

O Header é composto por:

  • Per-Recipient Unprotected Header
  • Protected Header
  • Shared Unprotected Header

Alguns dos valores podem não ser utilizados, isso depende do algoritmo de assinatura utilizado.

Também a exemplo do JWS o resultado final do JWE é a concatenação de seus componentes.

jwe

Json Web Algorithms (JWA)

Não é qualquer algoritmo que pode ser utilizado para Assinar Digitalmente ou Criptografar um JWT. Existe uma RFC que espeficifica quais algoritmos devem ser utilizados. Apesar de todos algoritmos estar em conformidade com a RFC. Ela recomenda a utilização do ECDSA using P-256 and SHA-256 (ES256) ou RSASSA-PSS (PS256) para assinar digitalmente o JWT.

JWS

Abaixo uma tabela de quais algoritmos utilizar para assinar um JWS.

algoritmo Descrição
HS256 HMAC using SHA-256
HS384 HMAC using SHA-384
HS512 HMAC using SHA-512
RS256 RSASSA-PKCS1-v1_5 using SHA-256
RS384 RSASSA-PKCS1-v1_5 using SHA-384
RS512 RSASSA-PKCS1-v1_5 using SHA-512
ES256 ECDSA using P-256 and SHA-256
ES384 ECDSA using P-384 and SHA-384
ES512 ECDSA using P-521 and SHA-512
PS256 RSASSA-PSS using SHA-256 and MGF1 with SHA-256
PS384 RSASSA-PSS using SHA-384 and MGF1 with SHA-384
PS512 RSASSA-PSS using SHA-512 and MGF1 with SHA-512
none No digital signature or MAC performed

Repare que a RFC preve a opção "Nenhum". Isso pressupõe que uma outra camada de proteção foi utilizada para garantir que o JWT não foi adulterado no seu transporte.

Json Web Key (JWK)

JWK é uma estrutura JSON que representa uma chave de criptografia. Na sua estrutura contém as informações para criptografar um JWT (JWE) ou Assinar Digitalmente (JWS).

Dentro de um ambiente OAuth 2.0, o responsável por criar e gerenciar o JWK é o Authorization Server. Como no OAuth 2.0 todos os JWT's são emitidos por um unico servidor ele é quem gerencia o JWK. Assim somente o Authorization Server pode emitir um JWT.

Certos parâmetros do JWK podem ser públicos, dessa forma os consumidores do JWT podem validar se o JWT não foi adulterado.

Exemplo de um JWK público (Google):

Exemplo de um JWK privado:

Json Web Key Set (JWKS)

JWKS é um array de JWK.

Os algoritmos de criptografia se tornam mais fracos com o tempo. Seja por que as técnicas de análise de criptografia melhoram ou por causa do desempenho dos computadores que melhoram dia após dias. Ambos contribuem para diminuir o tempo necessário para quebrar um algoritmo específico. Portanto, o objetivo do JWK e JWKS é permitir que um servidor OAuth 2.0 seja modular em relação a criptografia. Permitindo que novos algoritmos sejam facilmente inseridos.

Por esse motivo as boas práticas dizem que o JWK deve mudar a cada 90 dias. E com o auxilio do JWKS, ao efetuar a troca do algoritmo, não irá inválidar os tokens que foram gerados com o algoritmo anterior. Permitindo uma troca gradual, sem afetar os sistemas.

Atualmente o OAuth 2.0 utiliza o mesmo JWK para assinar o access_token e o identity_token. Há uma discussão no OAuth Working Group sobre separar a responsabilidade. Em breve teremos novidades.

Todo servidor OAuth 2.0 mantém um link público de seus JWKS.

Exemplo de um JWKS público Google:

Repare que apesar de público, não possui os dados privados. Utilizado para assinar o JWT.

Referências