Tokens JWT en Go (Golang): Guía completa con la biblioteca golang-jwt
JSON Web Token (JWT) es un estándar abierto (RFC 7519) para la creación de tokens de acceso basados en JSON. JWT se utiliza ampliamente para la autenticación y el intercambio de información entre partes. En Go (Golang), la biblioteca más popular y activamente mantenida para trabajar con JWT es golang-jwt/jwt/v5. En este artículo, analizaremos en detalle cómo instalar, configurar y utilizar esta biblioteca para crear aplicaciones web seguras.
Instalación de la biblioteca golang-jwt
Para comenzar, agregue la biblioteca a su proyecto usando go get:
go get github.com/golang-jwt/jwt/v5Después de la instalación, importe el paquete en su código:
import ( "github.com/golang-jwt/jwt/v5")Componentes principales de JWT
JWT consta de tres partes separadas por puntos: Header (encabezado), Payload (carga útil) y Signature (firma). La biblioteca golang-jwt proporciona estructuras convenientes para trabajar con cada una de ellas:
- Header — contiene metadatos sobre el tipo de token y el algoritmo de firma (por ejemplo, HS256, RS256).
- Payload — contiene claims (declaraciones), como el identificador de usuario, tiempo de expiración, roles y otros datos.
- Signature — se crea utilizando una clave secreta o un par de claves (privada/pública).
Creación de un token JWT de acceso (Access Token)
Consideremos un ejemplo de creación de un token de acceso con el algoritmo HS256 (cifrado simétrico). Primero, definamos una estructura con claims personalizados:
type CustomClaims struct { UserID int `json:"user_id"` Username string `json:"username"` jwt.RegisteredClaims}Ahora, creemos una función para generar el 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)}Aquí establecemos un tiempo de vida del token de 15 minutos, que es una práctica estándar para los access tokens. Utilice jwt.NewNumericDate() para un formato de tiempo correcto.
Verificación y análisis del token
Para verificar la autenticidad del token, es necesario extraer los claims y verificar la firma:
func ValidateToken(tokenString string, secretKey []byte) (*CustomClaims, error) { token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { // Verificamos que se use el algoritmo de firma esperado if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("método de firma 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")}Es importante verificar el algoritmo de firma en la función de callback para evitar ataques relacionados con la suplantación del algoritmo.
Creación y renovación del Refresh Token
Para mejorar la seguridad, a menudo se utiliza un par de tokens: un access token de corta duración y un refresh token de larga duración. El refresh token permite obtener un nuevo access token sin necesidad de volver a introducir el nombre de usuario/contraseña.
func GenerateRefreshToken(userID int, secretKey []byte) (string, error) { También en la biblioteca
Envío de correo electrónico en Rust: bibliotecas lettre y mailparse para trabajar con correo
Trabajo con CSV en TypeScript: bibliotecas y ejemplos de código
Programación reactiva en Swift: Combine y RxSwift para iOS/macOS