JSON Object Signing and Encryption é um conjunto para padronizar algumas representações utilizando o formato JSON:
JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.RFC 7519
Geralmente, é utilizado como um access token, que garante acesso a um determinado recurso (ou conjunto de recursos)
The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.RFC 7519
Exemplo de um JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ2aW5pY2l1c2NhbXBpdGVsbGkuY29tIiwiYXVkIjoicGFsZXN0cmFzIiwic3ViIjoiYXV0ZW50aWNhY2FvLWp3dCIsImlhdCI6MTY4NzQyNzQwMH0.wgF5eAdmH3lUpnjYvm2yhbF6RYtr1uiQUCtf-s62W9M
JSON Web Signature (JWS) represents content secured with digital signatures or Message Authentication Codes (MACs) using JSON-based data structures.RFC 7515
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ2aW5pY2l1c2NhbXBpdGVsbGkuY29tIiwiYXVkIjoicGFsZXN0cmFzIiwic3ViIjoiYXV0ZW50aWNhY2FvLWp3dCIsImlhdCI6MTY4NzQyNzQwMH0.wgF5eAdmH3lUpnjYvm2yhbF6RYtr1uiQUCtf-s62W9M
base64url({"alg": "HS256", "typ": "JWT"})
Corpo
base64url({
"iss": "viniciuscampitelli.com",
"aud": "palestras",
"sub": "autenticacao-jwt",
"iat": 1687427400
})
Assinatura
base64url(hmac(header . payload))
JSON Web Encryption (JWE) represents encrypted content using JSON-based data structures.RFC 7516
Em alguns casos, utiliza-se uma abordagem híbrida de criptografia: Criptografia simétrica para criptografar o payload e Criptografia assimétrica para cripotgrafar a Chave simétrica
RFC 7516
eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkEyNTZHQ00iLCJlcGsiOnsieCI6IlRubVZ5d2JLNjFNNktPU2gzbFlpZmpGdmoxajdLTTFTYjBsMUZ4VGVoQVUiLCJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieSI6Ik5TSWJFc0FCQmpwRGtpdXFjaUF0Z0tXQ1J5bEctSV9aOHZLemhXZ1pSY2sifX0.AshQJDAEbptscEvc3VuHzX_Ae3PsH3WFaGzKmA-QjcoJsziILktqKw.W8n4sxRmfroCN65Z.Ieg4R4SHVUoVHqHkQWccfsyRed8VT_-NtqxC0Io1dFHH8L-I3Bk-UdOPvwmO1hkBH3KCrcYgrFU-2hqb1E7fD3_DyPJ9uqBYhDrn1kpTxsTYnhX0z3DV1zPZAcHy9p6urytFMUV18k8huON0XA.P6rEnI71xYgqhdxDDuj8jA
base64url({"alg":"ECDH-ES+A256KW","enc":"A256GCM","epk":{"x":"TnmVywbK61M6KOSh3lYifjFvj1j7KM1Sb0l1FxTehAU","crv":"P-256","kty":"EC","y":"NSIbEsABBjpDkiuqciAtgKWCRylG-I_Z8vKzhWgZRck"}})
Chave
base64url(key)
IV
base64url(iv)
Corpo
base64url(encrypt({
"iat": 1687136586,
"sub": "autenticacao-jwt",
"iss": "viniciuscampitelli.com",
"aud": "palestras",
"exp": 1687140186
}, key))
Tag
base64url(tag)
This specification registers cryptographic algorithms and identifiers to be used with the JSON Web Signature (JWS), JSON Web Encryption (JWE), and JSON Web Key (JWK) specifications.RFC 7518
Alguns algoritmos para JWS:
HS256 ,
HS384 ,
HS512
|
HMAC usando SHA-256, SHA-384 ou SHA-512 |
RS256 ,
RS384 ,
RS512
|
RSASSA-PKCS1-v1_5 usando SHA-256, SHA-384 ou SHA-512 |
ES256 ,
ES384 ,
ES512
|
ECDSA usando P-256+SHA-256, P-384+SHA-384 ou P-521+SHA-512 |
none |
Sem assinatura digital ou MAC ⚠️ |
* Algoritmo
recomendado
Alguns algoritmos para JWE:
RSA-OAEP ,
RSA-OAEP-256
|
RSAES-OAEP e RSAES-OAEP com SHA-256 e MGF1 |
A128KW ,
A192KW ,
A256KW
|
AES Key Wrap usando chaves de 128, 192 ou 256 bits |
ECDH-ES
|
Curvas Elípticas com Troca de Chaves de Diffie-Hellman usando Concat KDF |
dir
|
Uso direto de uma chave simétrica |
* Algoritmos
recomendados
A JSON Web Key (JWK) is a JavaScript Object Notation (JSON) data structure that represents a cryptographic key. This specification also defines a JWK Set JSON data structure that represents a set of JWKs.RFC 7517
Hospede-o em um endereço público para que os Serviços de Negócio o consultem, como em facebook.com/.well-known/oauth/openid/jwks:
{
"keys": [
{
"kid": "852b4c741351eedc6ec8ae783b98eeabe2157daa",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "u0XiI326DxaxrD4eO9kt2B80M7NfPKcIx5AuwBj7gxVow3u8TSUr8xdycxcp_KNlKu5_MBpYOjY0CbnHM5GCiTAFI54xCRNlVTOE16f3FrSuE0ipMBw-njXO39q-BcTKGkF1Ey0hQ15AZYpaUXzFJTVC42nmnqP_TYSRBCtSTX1C2WGOuX8wOhJzzEmwcCS9VWpuSDVwtmz87c3eyn_XXtZKE8Gi2_Ibx_3K9p-RoXUhHwJrtvWqA_kz5s-zSTOU8-0hPhNwKI2Ep9juVvs_wnrvE8E0aJogNHcBodR6GvxWIkklz5yQwxe5RwrxtX71PAAynm4Kpp0KobH3A98avQ",
"e": "AQAB"
},
{
"kid": "370fa58a78d23043256a2cc580f1cf9ed3b9bbe7",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "ylVSkbdJm-Q76nrrPpv7RaGlQVjRfxw5z9OwkM7qzFdUW15QJFrN8nozL21VnOs-2rAfsoctoA8aQVMmtuWsyeGIpdLrupMVsKqC9bS5_7CQFXRGhQbxsZN1WDU9PcyzQamqFMfOEl3Blj3gZr13TMHxaOB0IH6OeMDlzUGWIsbrX4_QyYXr2Wj8xNNdZ7NwmRrik0dFTBg_-TjTvBzV10WkhbnHT7Lukri1XSEKhjGqAeD0zfGaixhunx3PcFtuB5HNB9qdpkxMeDUG0oUZ3MX-WY5ppfYMBs8euR1OPG26BAcBM5j4OFuCy8zEv5ornodoa71Af-JbEdyr8smCyw",
"e": "AQAB"
}
]
}
São os elementos que compõe o corpo do JWT, e você é livre para criá-lo do jeito que preferir
Entretanto, existem algumas Registradas para padronização na Seção 10.1. JSON Web Token Claims Registry da RFC 7519
RFC 7519: Seção 4. JWT ClaimsClaims registradas na Seção 10.1. JSON Web Token Claims Registry:
Claim | Significado | Descrição |
---|---|---|
iss |
Issuer | Serviço que emitiu o token |
aud |
Audience | Recipiente do JWT |
sub |
Subject | Indivíduo para o JWT (autor) |
iat |
Issued At | Timestamp da geração do token |
exp |
Expiration Time | Timestamp da expiração |
nbf |
Not Before | Timestamp em que o token passa a ser válido |
jti |
JWT ID | Identificador único do token |
Para JWS:
HS256
ES256
se disponível ou finalmente opte por
RS256
none
Para JWE:
ECDH-ES
RSAES-OAEP
Recomendações mínimas para cada algoritmo:
Em todos os casos, crie uma política de Rotação de chaves!
JWT signature algorithm HS256, RS256 and ES256 and key generationOutro tipo de token enviado junto com o access token que possui a principal funcionalidade de diminuir a superfície de ataque
Deve ser utilizado para receber um novo access token após sua expiração e ser usado somente uma única vez
Com isso, é possível ter JWTs com um tempo de expiração curto para aumentar a segurança
Auth0: What Are Refresh Tokens and How to Use Them SecurelyPara Comunicação entre Serviços:
Utilize um tempo de expiração bastante curto (por exemplo, 15 minutos), fazendo com que o serviço cliente deva frequentemente reautenticar-se
Para Usuários:
Crie um JWT com expiração de uma semana* e envie um refresh token com expiração maior (um mês*)
A cada acesso do usuário à aplicação ou a cada intervalo de tempo (uma hora*), utilize o refresh token para conseguir outros novos access token e refresh token
Se o usuário não acessar a aplicação nesse tempo, faça-o logar novamente
* Defina esses tempos com sua equipe de Produto/UX
Em aplicações Web:
Estratégia 1: guardar o token somente em memória em seu código JavaScript, podendo também utilizar Web Workers para salvá-lo
The New Stack: Leveraging Web Workers to Safely Store Access TokensEm aplicações Web:
Estratégia 2: utilizar Cookie
(e não LocalStorage
)
com as flags:
Secure
para apenas trafegar em HTTPSHttpOnly
para impedir acesso via JavaScriptSameSite
como Strict
para permiti-lo apenas em seu domínio
Em aplicações Mobile:
Guarde o token no armazenamento seguro específico da plataforma ou biblioteca, por exemplo:
SharedPreferences
Keychain
SecureStore
flutter_secure_storage
Um dos maiores desafios ao se utilizar JWT, pois geralmente é bastante custoso computacionalmente, inclusive sendo um ponto decisivo se você deve usar JWTs ou não
Estratégia 1:
Guarde o jti
do token em algum armazenamento como denylist e
garanta que os Serviços de Negócio o consultem ao validar o JWT
Para revogar todos os tokens de um usuário, faça o mesmo para o sub
Estratégia 1:
Estratégia 1:
Prós: expiração quase instantânea
Contras:
Estratégia 2:
Usar Eventos ou Webhooks para informar os Serviços de Negócio que o
token com aquele jti
ou sub
não pode mais ser aceito
Estratégia 2:
Estratégia 2:
Prós: mantém o JWT totalmente stateless
Contras:
Estratégia 3:
Criar o JWT com um tempo de expiração muito curto (alguns minutos, por exemplo) e o refresh token com um tempo maior (uma semana ou mais)
Prós: toda a estratégia fica centralizada no Serviço de autenticação
Contras: o usuário poderá acessar recursos até a expiração do token
Ao receber um token, certifique-se de validar...
none
)
iss
, aud
,
sub
e outros campos)
nbf
e exp
)
413 Entity Too
Large
em alguns servidores, isso poderá consumir muita CPU e inclusive ser um
vetor de ataques DoS
id
) em JWS