Tokens JWT em Go (Golang): Guia completo com a biblioteca golang-jwt
JSON Web Token (JWT) é um padrão aberto (RFC 7519) para criação de tokens de acesso baseados em JSON. JWT é amplamente utilizado para autenticação e troca de informações entre partes. Em Go (Golang), a biblioteca mais popular e ativamente mantida para trabalhar com JWT é a golang-jwt/jwt/v5. Neste artigo, abordaremos detalhadamente como instalar, configurar e usar esta biblioteca para criar aplicações web seguras.
Instalação da biblioteca golang-jwt
Para começar, adicione a biblioteca ao seu projeto usando go get:
go get github.com/golang-jwt/jwt/v5Após a instalação, importe o pacote no seu código:
import ( "github.com/golang-jwt/jwt/v5")Componentes principais do JWT
O JWT consiste em três partes separadas por pontos: Header (cabeçalho), Payload (carga útil) e Signature (assinatura). A biblioteca golang-jwt fornece estruturas convenientes para trabalhar com cada uma delas:
- Header — contém metadados sobre o tipo de token e o algoritmo de assinatura (por exemplo, HS256, RS256).
- Payload — contém as claims (declarações), como identificador do usuário, tempo de expiração, papéis e outros dados.
- Signature — é criada usando uma chave secreta ou um par de chaves (privada/pública).
Criação de um token JWT de acesso (Access Token)
Vamos considerar um exemplo de criação de um token de acesso com o algoritmo HS256 (criptografia simétrica). Primeiro, definimos uma estrutura com claims personalizadas:
type CustomClaims struct { UserID int `json:"user_id"` Username string `json:"username"` jwt.RegisteredClaims}Agora, criamos uma função para gerar o token:
func GenerateAccessToken(userID int, username string, secretKey []byte) (string, error) { claims := CustomClaims{ UserID: userID, Username: username, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)), IssuedAt: jwt.NewNumericDate(time.Now()), Subject: "access", }, }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(secretKey)}Aqui, definimos o tempo de vida do token como 15 minutos, o que é uma prática padrão para access tokens. Use jwt.NewNumericDate() para formatar o tempo corretamente.
Verificação e análise do token
Para verificar a autenticidade do token, é necessário extrair as claims e verificar a assinatura:
func ValidateToken(tokenString string, secretKey []byte) (*CustomClaims, error) { token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { // Verificamos se o algoritmo de assinatura esperado está sendo usado if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("método de assinatura inesperado: %v", token.Header["alg"]) } return secretKey, nil })
if err != nil { return nil, err }
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { return claims, nil }
return nil, fmt.Errorf("token inválido")}É importante verificar o algoritmo de assinatura na função de callback para evitar ataques relacionados à substituição do algoritmo.
Criação e renovação do Refresh Token
Para aumentar a segurança, é comum usar um par de tokens: um access token de curta duração e um refresh token de longa duração. O refresh token permite obter um novo access token sem precisar inserir login/senha novamente.
func GenerateRefreshToken(userID int, secretKey []byte) (string, error) { Também na biblioteca
GraphQL Java: Guia Completo da Biblioteca para Criação de APIs em Java
Geolocalização e Mapas em JavaScript (Node.js): bibliotecas e ferramentas
Trabalho com CSV em Java: guia completo de leitura e escrita
Biblioteca Padrão C++: visão geral completa e exemplos de código
Machine Learning em Go: bibliotecas para Golang (ML, redes neurais, PLN)