A estrutura dele é formada por 3 partes: Header, Payload e Signature. Vamos entender melhor elas:
Header
O Header consiste em duas partes encodados em Base64 sendo:
- O Tipo (JWT)
- E o algoritmo de Hash que pode ser (HMAC SHA256 ou RSA).
{
"alg": "HS256",
"typ": "JWT"
}
Payload (Claims)
Os payloads são objetos JSON que contem os claims, nessa parte que nós trabalhamos com os “pedidos”, carga de dados ou dados enviados. Existem 3 tipos de claims em Payloads: reserved, public, e private claims.
Reserved claims: Atributos não obrigatórios (mas recomendados) que podem ser um conjunto de informações uteis e interoperáveis normalmente utilizados por protocolos de segurança em API’s:
- “iss” (Issuer) Origem do token
- “iat” (issueAt) Timestamp de quando o token foi gerado
- “exp” (Expiration) Timestamp de quando o token expira
- “sub” (Subject) Entidade a quem o token pertence, normalmente o ID do usuário
- Public claims: São atributos que definem o uso do JWT e informações úteis para a aplicação.
- Private claims: São atributos definidos especialmente para compartilhar informações entre aplicações.
Exemplo:
{
"iss": "127.0.0.13",
"exp": 1300819380,
"user": "programadriano",
"admin": true
}
Signature
Essa é a terceira e última parte do JWT, para que possamos ter um token, nós precisamos de um Header, Payload, o algoritmo definido na header, um secret definido pela nossa aplicação. Vamos ver um exemplo com a utilização do HMAC SHA256:
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); + "." +
HMACSHA256(encodedString, 'secret');
O seu retorno seria o token a baixo:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IlRoaWFnbyIsInN1YiI6IjEzIiwianRpIjoiZDBlMGFkZDItOTlkMC00NWY1LThlYzEtY2FiYzIwZjkxMGYyIiwiaWF0IjoxNTAwMDMzMjE0LCJKd3RWYWxpZGF0aW9uIjoiVXN1YXJpbyIsIm5iZiI6MTUwMDAzMzIxMywiZXhwIjoxNTAwMDMzMjczLCJpc3MiOiJJc3N1ZXIiLCJhdWQiOiJBdWRpZW5jZSJ9.SmjuyXgloA2RUhIlAEetrQwfC0EhBmhu-xOMzyY3Y_Q
Podemos perceber que o nosso token está dividido em três partes separadas por “.”, conforme nós utilizamos no momento da criação.
Primeira parte: Header .
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
Segunda parte: Payload.
eyJ1bmlxdWVfbmFtZSI6IlRoaWFnbyIsInN1YiI6IjEzIiwianRpIjoiZDBlMGFkZDItOTlkMC00NWY1LThlYzEtY2FiYzIwZjkxMGYyIiwiaWF0IjoxNTAwMDMzMjE0LCJKd3RWYWxpZGF0aW9uIjoiVXN1YXJpbyIsIm5iZiI6MTUwMDAzMzIxMywiZXhwIjoxNTAwMDMzMjczLCJpc3MiOiJJc3N1ZXIiLCJhdWQiOiJBdWRpZW5jZSJ9.
Terceira parte: Secret.
SmjuyXgloA2RUhIlAEetrQwfC0EhBmhu-xOMzyY3Y_Q
Quando um usuário faz uma requisição ao servidor passando os seus dados de login, o servidor analisa e retorna um token com uma validade, para que o usuário possa navegar pelo sistema.
Para que possamos validar se o nosso token está correto podemos utilizar o próprio site do JWT. Para isso, basta copiar o token acima que criamos para esse exemplo e colar na parte Encoded do site. Podemos ver o seu retorno dessa validação na imagem a baixo:
Agora lembra que acima comentamos sobre a palavra chave? Podemos adicionar ela na parte VERIFY SIGNATURE do site, para esse exemplo nós utilizamos a frase: batman batman batman, notem que após colocarmos ela irá mudar o status da nossa assinatura conforme a baixo de Invalid Signature para Signature Verified.
Nessa primeira parte nós conseguimos criar o nosso token e validar ele pelo próprio site do JWT, mas como funcionária em um projeto real? Vamos criar uma API em Node.js e utilizar o postman para que possamos validar as nossas requisições.
Exemplo prático
Nosso primeiro passo será a criação de um novo projeto Node.js, para que esse artigo não fique muito longo, vamos resumir essa etapa em:
1º Crie um diretório para o nosso projeto;
2º Execute o comando npm init -y;
3º Abrir uma IDE de nossa preferencia e criar uma estrutura básica como na imagem a baixo, para esse exemplo nós iremos utilizar o Visual Studio Code, ele é uma ferramente muito completa e grátis desenvolvida pela Microsoft. Caso queria instalar ele, basta baixar o seu executável no link Download.
Vamos agora adicionar os pacotes necessários para esse artigo, no seu arquivo package.json adicione as seguintes dependências:
},"dependencies": {
"body-parser": "^1.15.0",
"express": "^4.13.4",
"jsonwebtoken": "^5.7.0",
"mongoose": "^4.4.5",
"morgan": "^1.7.0"
}
Para que possamos baixar esse pacotes para o nosso projeto, execute o comando npm install, a execução dele irá criar uma pasta chamada node_modules e dentro dela os nossos pacotes.
Nosso próximo passo será a implementação da nossa classe user. Para isso, copie e cole o código a baixo dentro do seu arquivo user.js, que está dentro do diretório models.
class User {
constructor(name, admin) {
this.name = name;
this.admin = admin;
}};
module.exports = User;
Agora nós iremos implementar o nosso server.js, esse será o arquivo principal do nosso projeto.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var jwt = require('jsonwebtoken');
var user = require('./models/user');
Nessa primeira parte estamos importando os nossos pacotes, até aqui nenhuma novidade, vamos agora adicionar o código que será responsável para realizar a conversão dos nossos dados para JSON:
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
Vamos agora referenciar o código que será responsável por gerenciar os logs das nossas requisições e apresentar eles na nossa console:
app.use(morgan(‘dev’));
Para que possamos testar o pacote Morgan e validar o nosso código, vamos criar a nossa primeira rota:
var apiRoutes = express.Router();
apiRoutes.get('/', function (req, res) {
res.json({ message: 'Node.js com JWT' });
});
app.use('/', apiRoutes);
var port = process.env.PORT || 8000;
app.listen(port);
console.log('Aplicação rodando na porta:' + port);
Vamos entender o código acima, na primeira linha nós estamos chamando o Router do pacote Express, em seguida nós criamos o nosso primeiro método Get retornando uma mensagem, por fim estamos passando a porta que o nosso projeto irá rodar e adicionando um listen nela. Para executar o código, dentro da console digite o comando node server.js, em seguida vamos abrir no nosso navegador o endereço: http://localhost:8000/ ele deve retornar a mensagem: “Node.js com JWT” e o senguinte log na nossa console:
Com isso nos conseguimos validar o pacote morgan e a nossa requisição HTTP com o express, vamos agora implementar o JWT. Para isso, vamos criar um novo método POST no nosso arquivo server.js.
apiRoutes.post('/', function (req, res) {
if (req.body.UserName != "tadriano" || req.body.PassWord != "102030") {
res.json({ success: false, message: 'Usuário ou senha incorreto(s)!' });
} else {
let usuario = new user()
{
name : "tadriano";
admin: true
};
var token = jwt.sign(usuario, 'batman batman batman', {
expiresInMinutes: 1440
});
res.json({
success: true,
message: 'Token criado!!!',
toke: token
});
}
});
Para que esse artigo não fique muito longo, nós criamos uma validação conhecida como Hard Code, em seguida como não estamos buscando o nosso usuário no banco nós criamos um novo, para que possamos implementar os dados da nossa assinatura, em seguida nós retornamos uma mensagem de sucesso e o nosso token. Para validar essa etapa nós iremos utilizar o Postman, uma ferramenta do google chrome que auxilia nos testes a requisições HTTP. Com ele aberto adicione a URL do projeto com a porta e o usuário e senha na Body. A imagem a baixo demonstra esse implementação:
Feito isso podemos enviar a nossa requisição que irá retornar o nosso token. Podemos ver esse retorno na imagem a baixo:
Agora para finalizar esse artigo vamos criar um middler para verificar se a requisição está com o token ou se ele é um token é valido. Para isso, vamos colar o código a baixo depois do nosso método POST.
apiRoutes.use(function(req, res, next) {
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if(token) {
jwt.verify(token, 'batman batman batman', function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Falha ao tentar autenticar o token!' });
} else {
//se tudo correr bem, salver a requisição para o uso em outras rotas
req.decoded = decoded;
next();
}
});
} else {
// se não tiver o token, retornar o erro 403
return res.status(403).send({
success: false,
message: '403 - Forbidden'
});
}
});
Nessa etapa nós estamos verificando se a requisição está com o token, caso não esteja enviando ele ou caso ele seja um token invalido nós retornamos o status 403, que é utilizado para passar que o usuário não tem permissão para realizar aquela requisição. Caso o token seja valido, nós retornamos o status 200 e uma mensagem no navegador.
Por fim, para que possamos validar um requisição com o token, nós precisamos realizar o mesmo procedimento acima para gerar um token e em seguida preencher o Postman conforme a imagem a baixo, assim conseguiremos ter acesso aos nossos métodos.
Com isso nós conseguimos abordar a teoria do JWT e entender o seu funcionamento através de um exemplo criado em uma linguagem de programação que vem sendo adotada por muitos programadores a cada dia que se passa.
link do projeto
Gostou deste artigo? Comente abaixo!
Referência: https://programadriano.medium.com/json-web-token-jwt-c469834849a8