O Básico: JWT - JSON Web Token
Tags: beginners, webdev, javascript, braziliandevs
Published: 2022-04-05 23:12:37

## JWT

### O que é?
É um token gerado a partir de dados _"pessoais"_, esse que pode ser trafegado entre aplicações ao se realizar requisições a APIs. As informações contidas no token são públicas e podem ser lidas por qual quer um que o possua, porém há um mecanismo de segurança que faz com que somente quem tenha a senha, possa modificá-lo.

### O que faz?
De forma geral os tokens podem ser usados para diversas finalidades, afinal eles são somente uma estrutura segura para o trafego de informações, porém seu uso mais comum é para autorização de usuários em diversos serviços.

### Estrutura

#### Header
O Header do token irá conter duas propriedades, `alg` para definir o algoritmo de hash e `typ` para definir o tipo de token, no nosso caso será `JWT`.

``` json
{
  "alg": /*algoritmo de hash*/,
  "typ": "JWT",
}
```
``` json
{
  "alg": "HS256",
  "typ": "JWT",
}
```

#### Payload
O payload irá conter os dados do usuário, esses que não devem ser dados sensíveis _(CPF, cartão, endereço, etc)_, apenas o essencial para dar ao usuário a autorização necessária para navegar e interagir com a aplicação.

``` json
{
  "username": "Big John",
  "name": "John Doe",
  "admin": false,
  "isPrime": true
}
```

### Signature
É a assinatura utilizada para validar o token, dessa forma conseguimos verificar se o token recebido do cliente é igual ao que enviamos anteriormente, caso não sejam iguais, o token é considerado inválido.

``` js
// essa parte é a concatenação, criptografada, do Header + Payload e será gerada para nós pelo JWT.
```

___

## Usando o JWT

### Instalando
Antes de começarmos a implementar o JWT, precisamos instalar a biblioteca que irá gerar e validar os tokens, para isso usamos o comando:

``` bash
npm i jsonwebtoken

npm i -D @types/jsonwebtoken  # caso usar TypeScript será necessário instalar os pacotes a parte
```

### Configurando
Tendo instalado e importado o JWT para nosso arquivo, iremos configurá-lo. Nas configurações podemos definir o algoritmo de hash, o período de validade, entre outas opções.

As configurações consistem em um Objeto JS com algumas chaves pré existentes. Consultar a [documentação](https://www.npmjs.com/package/jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback) para as chaves.

``` js
const jwtConfig = {
  expiresIn: '4d',  // <- Faz com que o token expire depois de 4 dias
  algorithm: 'HS256',  // <- Indica o algoritmo de hash HS256 para criptografia
};
```

### Criando
Após termos definido nossas configurações iremos chamar o método `.sign()` para realmente criarmos nosso token, esse método irá receber os dados, o _secret_ e as configurações como argumentos.

``` js
const jwt = require('jsonwebtoken');  // <- importação do jwt
const secret = 'meuSuperSegredo';  // Considerações logo abaixo*
const user = { email: 'gabriel@gabriel.com', username: 'Roxo' };  // <- usuário fake para demonstração

jwt.sign({ data: user }, secret, jwtConfig);  // <- data é a chave padrão do JWT para passarmos os dados
```

<small>_*O secret deve ser armazenado em variáveis de ambiente para maior segurança da aplicação, caso o declaremos hardcoded, estaremos deixando nossa aplicação vulnerável e nossos tokens/usuários em risco._</small>

### Validando
Para validarmos um token basta chamarmos o método `.verify()`, passando o token em questão e o _secret_ utilizado como argumentos. Não se preocupe em referenciar o token criado anteriormente, pois a biblioteca do JWT faz isso para nós.

Caso o token seja inválido, ou tenha expirado, o próprio método irá nos retornar um erro, logo precisamos trabalhar essa validação dentro de um bloco `try/catch`, ou algo equivalente.

``` js
/*
Assim como na criação, na validação do token precisamos importar o jwt e o secret.

E a variável secret deve ser EXATAMENTE a mesma utilizada no jwt.sign (criação) para gerar o token, caso contrário a verificação falhará.

*No caso desse exemplo seria necessário criar uma outra constante para definir o secret (NÃO RECOMENDADO)
*/

jwt.verify(token, secret);
```