Executando verificação de segurança...
10

Json Web Tokens - Como funcionam, como criar e validar.

Bom dia pessoal, hoje irei demonstrar como o processo de criação e validação de um Json Web Token funciona, e nós não vamos usar módulos como o jwt ou o jose pra isso. Vamos começar do zero!

O tutorial a seguir é pra node.js

Além disso para ficar mais organizado eu dividi esse post em 3 categorias:

  • O que é?
  • Como criar
  • Como validar
O que é um Json Web Token (Clique para expandir)

O que é um Json Web Token?

Um json web token, em palavras simples é um token de autenticação, que é divido em 3 partes:

Parte 1O header do token, ele contém o algoritmo usado pelo hash, e o tipo de token
Parte 2O payload do token, ele contém informações personalizadas que você pode decidir!
Parte 3O hash do token, ele é criptografado com uma chave privada

Para não ter que ficar repetindo Json Web Token toda hora, vamos chamar ele de JWT por enquanto

Como o processo da criação do token funciona (Clique para expandir)

Como o processo da criação do token funciona

Antes de escrever o código que vai gerar o token, precisamos antes entender como o processo que gera ele funciona.

O que temos que gerar?

Temos que gerar um header, um payload, E um hash que garante a integridade dos header e do payload.

O header, assim como o payload será um Json encriptado em Base64
E o hash, será um Hash-sha256 que terá como valor o header e o payload, e o hash será assinado com uma chave privada para garantir que quem emitiu o token foi nós, e não outra pessoa.


Como gerar?

Primeiramente precisamos ter um meio de codificar um json em base64 e vice-versa.
Para isso utilizaremos o Buffer do node.js, que irá fazer o trabalho de codificar o base64 para nós

let JSONbase64 = {
	encode: (json) => Buffer.from(JSON.stringify(json)).toString("base64url"),
	decode: (base64) => JSON.parse(Buffer.from(base64, "base64url").toString("ascii"))
}

Com isso feito nós podemos passar pra nossa próxima tarefa: Gerar o hash do token

Para isso nós usaremos o módulo crypto que já vem instalado com o node.js
A linha de código que vai gerar o hash é está:

crypto.createHmac("sha256", secret_key).update(`${header}.${payload}`).digest("base64url") //secret_key = a chave privada que eu falei antes!

Se você quiser saber mais do crypto a docs dele está aqui

Maravilha! agora que fizemos tudo nós vamos criar a função que vai gerar o token:

Primeiramente, tenha em mente que essa função vai gerar uma Promise, pois demora alguns milissegundos pra gerar um hash.(Pode parecer pouco millisegundos, mas computadores são muitos mais rapidos que isso. então somente pra nós, Humanos que esse tempo é curto)
Essa função vai gerar um header, um payload com a data de quando o token foi emitido e o nome do usuário(que vai ser passado por um pârametro), e o hash que corresponde a isso. E depois vai juntar tudo com o separador .

const crypto = require("crypto")

function createToken(nome){
	return new Promise((resolve, reject) => {
		let header = JSONbase64.encode({typ: "JWT", "alg": "HS256"})
		let payload = JSONbase64.encode({nome: nome, createdAt: Date.now()})
		let hash = crypto.createHmac("sha256", secret_key).update(`${header}.${payload}`).digest("base64url")
		let result_token = `${header}.${payload}.${hash}`
		resolve(result_token)
	})
}

E pronto! Você aprendeu como gerar um token!

Como o processo da validação do token funciona (Clique para expandir)

Como o processo da validação do token funciona

Ok, você aprendeu a como gerar um token JWT, mas como validar ele?
Alguns processos que você pode pensar são:

  • Gerar o token novamente e verificar se os tokens são iguais: Não funciona! lembra do atributo createdAt do payload? o tempo que você vai validar é diferente do tempo que o token foi criado, então os tokens vão ser diferentes!
  • Gerar o hash novamente e verificar se os hash são iguais: Funciona!

Então vamos lá:

function validateToken(token){
	return new Promise((resolve, reject) => {
		let [header_in_base64, payload_in_base64, hash] = token.split(".")
		let valid_hash = crypto.createHmac("sha256", secret_key).update(`${header_in_base64}.${payload_in_base64}`).digest("base64url")
		resolve(hash == valid_hash)
	})
}

E pronto! agora você sabe como validar e criar tokens JWT

Repositorio no github para quem quiser ver o código completo: https://github.com/33gustavo33/jwt-exemplo

Carregando publicação patrocinada...
3

Parabéns!!! ✨, pra mim o mais legal desse artigo é o fato de você ter seguido uma abordagem sem libs prontas. Eu gosto muito quando vejo algo desse tipo pois na minha opnião, acrescenta e muito no aprendizado.

1

Concordo, um

const jwt = require("jsonwebtoken")
jwt.sign(payload, secret_key)

pode até ser mais simples, mas ver o que esse comando faz pro trás é muito melhor pro aprendizado!

1