Tokens JWT en Go (Golang): guía completa
\n\nJSON Web Tokens (JWT) es un estándar abierto (RFC 7519) para crear tokens de acceso basados en JSON. JWT se utiliza ampliamente para la autenticación y el intercambio de información entre el cliente y el servidor. En el lenguaje Go (Golang), trabajar con tokens JWT se implementa de manera simple y eficiente gracias a la biblioteca golang-jwt/jwt.
En este artículo, analizaremos en detalle la creación, firma, verificación y uso de tokens JWT en Go. El material será útil tanto para principiantes como para desarrolladores experimentados que deseen implementar autenticación segura en sus proyectos en Golang.
\n\nInstalación de la biblioteca golang-jwt
\n\nPara trabajar con JWT en Go, se utiliza el paquete github.com/golang-jwt/jwt/v5. Instálelo con el comando:
go get github.com/golang-jwt/jwt/v5\n\nDespués de la instalación, puede importar el paquete en su código:
\n\nimport (\n "github.com/golang-jwt/jwt/v5"\n)\n\nEstructura del token JWT
\n\nUn token JWT consta de tres partes, separadas por puntos:
\n\n- \n
- Header (encabezado) — contiene el tipo de token (JWT) y el algoritmo de firma (por ejemplo, HS256 o RS256). \n
- Payload (carga útil) — contiene los datos (claims), como el identificador de usuario, rol, fecha de expiración, etc. \n
- Signature (firma) — se crea a partir del header y payload utilizando una clave secreta o un par de claves RSA/ECDSA. \n
Creación de un token JWT en Go
\n\nVeamos un ejemplo de creación de un token JWT con el algoritmo HMAC-SHA256 (HS256). Para esto, se necesita una clave secreta.
\n\npackage main\n\nimport (\n "fmt"\n "time"\n "github.com/golang-jwt/jwt/v5"\n)\n\nfunc main() {\n // Clave secreta (debe almacenarse en un lugar seguro)\n secretKey := []byte("my_secret_key_12345")\n\n // Creamos los claims (afirmaciones)\n claims := jwt.MapClaims{\n "user_id": 123,\n "role": "admin",\n "exp": time.Now().Add(time.Hour * 24).Unix(), // token válido por 24 horas\n "iat": time.Now().Unix(),\n }\n\n // Creamos el token\n token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\n\n // Firmamos el token con la clave secreta\n tokenString, err := token.SignedString(secretKey)\n if err != nil {\n fmt.Println("Error al crear el token:", err)\n return\n }\n\n fmt.Println("Token JWT creado:")\n fmt.Println(tokenString)\n}\n\nVerificación y análisis de un token JWT
\n\nPara verificar la autenticidad del token, se utiliza la misma clave secreta. Es importante verificar la fecha de expiración y la firma.
\n\npackage main\n\nimport (\n "fmt"\n "github.com/golang-jwt/jwt/v5"\n)\n\nfunc main() {\n tokenString := "su_token_aqui"\n secretKey := []byte("my_secret_key_12345")\n\n // Analizamos y verificamos el token\n token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {\n // Verificamos el algoritmo de firma\n if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {\n return nil, fmt.Errorf("método de firma inesperado: %v", token.Header["alg"])\n }\n return secretKey, nil\n })\n\n if err != nil {\n fmt.Println("Error al verificar el token:", err)\n return\n }\n\n // Extraemos los claims\n if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {\n fmt.Println("¡Token válido!")\n fmt.Printf("User ID: %v\\n", claims["user_id"])\n fmt.Printf("Role: %v\\n", claims["role"])\n } else {\n fmt.Println("Token no válido")\n }\n}\n\nUso de claims estructurados
\n\nPara mayor comodidad, puede definir su propia estructura de claims que implemente la interfaz jwt.Claims:
type CustomClaims struct {\n UserID int `json:"user_id"`\n Role string `json:"role"`\n jwt.RegisteredCl