https://a.storyblok.com/f/270183/1368x665/d60d9f5a60/jwt-token_network-apis.png

Como gerar tokens JSON da Web (JWTs) para autenticação em APIs de rede

Publicado em November 26, 2024

Tempo de leitura: 3 minutos

O que é um JSON Web Token (JWT)?

A JWT (JSON Web Token) é um padrão aberto (RFC 7519) para a transmissão segura de informações entre partes na forma de um objeto JSON. O objeto pode ser criptografado e assinado com uma chave privada/pública, sendo comumente utilizado para autenticação e autorização em aplicativos da web. 

Você pode pensar no JWT como um cartão de identificação digital usado em aplicativos da web para confirmar sua identidade sem precisar fazer login toda vez que interagir com esse aplicativo.

É importante saber como gerar um token JWT, já que as APIs de rede as utilizam para realizar a autorização. Existem várias maneiras de gerar um novo token JWT ao utilizar as APIs da Vonage:

  • Usando o gerador online de JWT. Você precisará do ID do seu aplicativo e da chave privada gerada pelo aplicativo no seu painel de controle. As APIs de rede não exigem nenhuma propriedade ACL adicional.

  • Usando a ferramenta CLI da Vonage. Assim como no gerador online, é necessário fornecer uma chave privada e um ID de aplicativo: vonage jwt --key_file=caminho/para/private.key --app_id=<application_id>

  • Se você estiver usando um de nossos SDKs, não precisa se preocupar com o JWT, pois todos os SDKs oferecem suporte à geração de tokens JWT.

E se eu quiser gerar os tokens JWT sem depender de nenhuma ferramenta ou biblioteca externa? Se for esse o caso, continue lendo! 

Estrutura do JWT

Antes de implementar o JWT, é importante compreender sua estrutura. 

Um JWT é composto pelo cabeçalho, payload, e assinatura. Essas partes são codificadas separadamente usando o algoritmo de codificação e concatenadas por meio de pontos:

jwt = base64url(header) + '.' + base64url(payload) + '.' + base64url(signature)

Vamos começar!

Cabeçalho

Especifica qual algoritmo é usado para gerar a assinatura. Para as APIs da Vonage, o cabeçalho terá a seguinte aparência:

{ 
  alg: "RS256",
  typ: "JWT"
};

Carga útil

Ele inclui informações sobre o usuário e suas solicitações, como o ID da solicitação, a hora de emissão, a hora de validade, etc. A lista a seguir contém as chaves necessárias para usar as APIs da Vonage:

  • application_id. Corresponde ao ID do aplicativo com recursos do Registro de Rede, criado no painel do usuário.

  • iat. A hora em que o token foi emitido.

  • nbf. O horário em que o token deve se tornar válido.

  • exp. O horário em que o token deve expirar.

  • acl. Uma lista das permissões que esse token terá. Para APIs de rede, usaremos um valor vazio, pois as APIs não precisam de nenhuma permissão adicional.

  • jti. Um identificador exclusivo para o JWT.

Assinatura

Funciona como um selo para validar o token. É calculado por meio da codificação do cabeçalho e da carga útil usando o algoritmo de codificação Base64url e assinado com uma chave secreta. A chave privada do aplicativo é usada para assinar o token. A chave pública correspondente é usada para Verify-lo. As chaves podem ser encontradas nas configurações do aplicativo, no painel do usuário.

Como gerar um JWT em JavaScript

O primeiro passo seria criar o cabeçalho:

const header = {
  alg: "RS256",
  typ: "JWT",
};

Em seguida, crie a carga útil. Neste exemplo, definimos um prazo de validade de uma hora:

const currentTime = Math.floor(Date.now() / 1000);

const payload = {
  application_id: "123-456-789",
  iat: currentTime,
  nbf: currentTime,
  exp: currentTime + (60 * 60),
  acl: {},                 
  jti: crypto.randomUUID()
};

O JavaScript não inclui uma implementação do algoritmo Base64URL; portanto, precisamos implementar nossa própria versão:

function base64url(str) {
  let encodedSource = Buffer.from(str).toString('base64');

  // remove padding and replace characters
  return encodedSource
       .replace(/\+/g, '-')
       .replace(/\//g, '_')
       .replace(/=+$/, '');
}

A seguir, vamos criar a assinatura:

const crypto = require("crypto");
const fs = require("fs");

// Load your private key generated for the Vonage Application
const privateKey = fs.readFileSync("path/to/private.key", "utf8");

const encodedHeader = base64url(JSON.stringify(header));
const encodedPayload = base64url(JSON.stringify(payload));

const signingInput = `${encodedHeader}.${encodedPayload}`;

// Create RS256 signature (RSA-SHA256)
const signature = crypto.sign("RSA-SHA256", Buffer.from(signingInput), {
  key: privateKey,
});

const encodedSignature = base64url(signature);

Por fim, nosso JWT está pronto para ser usado:

const jwt = `${encodedHeader}.${encodedPayload}.${encodedSignature}`;
console.log(jwt);

Como gerar um JWT em Python

O código para implementar um JWT é muito semelhante à versão em JavaScript. Vamos começar implementando o algoritmo Base64URL:

import base64
import json
import time
import uuid

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

def base64url(data: bytes) -> str:
    return base64.urlsafe_b64encode(data).rstrip(b"=").decode("utf-8")

Em seguida, vamos definir nosso cabeçalho e nossa carga útil:

current_time = int(time.time())

header = {"alg": "RS256", "typ": "JWT"}

payload = {
    "application_id": "123-456-789",
    "iat": current_time,
    "nbf": current_time,
    "exp": current_time + 3600,
    "acl": {},
    "jti": str(uuid.uuid4()),
}

O próximo passo é codificar tanto o cabeçalho quanto a carga útil:

encoded_header = base64url(json.dumps(header, separators=(",", ":")).encode("utf-8"))
encoded_payload = base64url(json.dumps(payload, separators=(",", ":")).encode("utf-8"))

Estamos prontos para criar a assinatura:

app_id = "1234-4567-8901-abcd"
private_key = "/path/to/your/private/key"

with open(private_key, "rb") as f:
    private_key = serialization.load_pem_private_key(f.read(), password=None)

signature = private_key.sign(
    signing_input,
    padding.PKCS1v15(),
    hashes.SHA256(),
)

encoded_signature = base64url(signature)

Nosso JWT está pronto para ser usado:

jwt_token = f"{encoded_header}.{encoded_payload}.{encoded_signature}"
print(jwt_token)

Como usar o JWT com APIs de rede

As APIs de rede utilizam JWT durante a etapa de autorização, antes de realizar qualquer chamada à API. Como os tokens são credenciais, devemos levar em consideração algumas medidas de segurança para evitar problemas de segurança:

  • A geração do JWT deve ser feita no back-end.

  • Não mantenha o prazo de validade dos tokens por mais tempo do que o necessário. 

Uma vez gerado, os usuários devem poder utilizar o token para acessar endpoints protegidos. Isso geralmente é feito por meio do cabeçalho Authorization, utilizando o esquema Bearer:

Authorization: Bearer <token>

A documentação sobre autorização das APIs de rede contém uma descrição detalhada de como usar tokens JWT no front-end e back-end .

Entre em contato

Você já implementou o JWT na sua linguagem de programação favorita? Adoraríamos ver o seu código! Junte-se a nós no Slack da Comunidade de Desenvolvedores da Vonage ou envie uma mensagem para a gente no X, e entraremos em contato com você. 

Obrigado pela leitura!

Compartilhar:

https://a.storyblok.com/f/270183/405x400/2b811a162d/alvaro-navarro.jpg
Alvaro NavarroEx-funcionários da Vonage

Álvaro é um ex-membro da equipe da Vonage. Ele atuou como defensor dos desenvolvedores na Vonage, com foco em APIs de rede. É apaixonado por experiência do desenvolvedor, APIs e código aberto. Fora do trabalho, é comum encontrá-lo explorando lojas de quadrinhos, participando de festivais de ficção científica e terror ou montando coisas com aqueles famosos blocinhos de plástico.