Servicio de Generación y Verificación de Tokens Firmados (JWT/HS256) en Go

Servicio REST en Go para generar y verificar tokens JWT firmados con HS256, ideal para autenticación y autorización segura en aplicaciones.

Breve Introducción

Servicio de Generación y Verificación de Tokens Firmados (JWT/HS256) en Go (go)
DESCRIPCIÓN:
Implementación de un servicio REST en Go para generar y verificar JSON Web Tokens (JWT) firmados con el algoritmo HS256. El servicio expone dos endpoints: uno para crear un token a partir de una carga útil JSON y otro para validar un token JWT recibido. El código utiliza la biblioteca github.com/golang-jwt/jwt/v5 para la gestión de tokens.

NOTAS ADICIONALES:
Este ejemplo está listo para usar: solo necesitas tener Go instalado, ejecutar 'go mod tidy' para descargar la dependencia y luego 'go run main.go' para iniciar el servidor. El servicio expone APIs REST simples para generar y verificar JWT firmados con HS256. Es un ejemplo robusto y modular, adecuado para integraciones en sistemas de autenticación o autorización.

EXPLICACIONES:
- La biblioteca github.com/golang-jwt/jwt/v5 es una de las más usadas en Go para la gestión de JWT, soporta varios algoritmos de firma incluyendo HS256.
- El token JWT está firmado con una clave secreta definida en el código (en una aplicación real debería gestionarse de forma segura).
- El endpoint /generate-token acepta un JSON con campos personalizados y devuelve un token JWT firmado.
- El endpoint /verify-token acepta un token JWT y verifica la firma y validez, devolviendo la carga útil decodificada si es válido.
- El código maneja errores comunes como carga útil malformada, token no válido o firma incorrecta, devolviendo mensajes JSON claros.
- El servidor HTTP está implementado con el paquete estándar net/http de Go, sin dependencias externas para el servidor web.
- El código está comentado en italiano para facilitar la comprensión y el mantenimiento.

Código de Ejemplo: go

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// Clave secreta usada para firmar los tokens JWT (en producción debe gestionarse de forma segura)
const jwtSecret = "questa_e_una_chiave_segreta_molto_lunga_e_sicura"

// Payload representa los datos personalizados contenidos en el token JWT
// Puedes agregar otros campos a tu gusto
type Payload struct {
	Username string `json:"username"`
	Role     string `json:"role"`
	// Puedes agregar otros campos como Email, Exp, Issuer, etc.
}

// ResponseToken representa la respuesta JSON con el token JWT generado
type ResponseToken struct {
	Token string `json:"token"`
}

// ResponseVerify representa la respuesta JSON para la verificación del token
// Indica si el token es válido y devuelve la carga decodificada
type ResponseVerify struct {
	Valid   bool    `json:"valid"`
	Payload Payload `json:"payload,omitempty"`
	Error   string  `json:"error,omitempty"`
}

// generaToken crea un token JWT firmado con HS256 a partir del payload proporcionado
func generaToken(payload Payload) (string, error) {
	// Creamos un nuevo token JWT
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"username": payload.Username,
		"role":     payload.Role,
		"iat":      time.Now().Unix(), // Emitido en
		"exp":      time.Now().Add(time.Hour * 1).Unix(), // Expira en 1 hora
	})

	// Firmamos el token con la clave secreta
	tokenString, err := token.SignedString([]byte(jwtSecret))
	if err != nil {
		return "", err
	}
	return tokenString, nil
}

// verificaToken decodifica y verifica la validez del token JWT
func verificaToken(tokenString string) (Payload, error) {
	// ParseWithClaims permite especificar el tipo de claims esperados
	claims := jwt.MapClaims{}
	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		// Verificamos que el algoritmo de firma sea HS256
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("algoritmo de firma no válido")
		}
		return []byte(jwtSecret), nil
	})

	if err != nil {
		return Payload{}, err
	}

	if !token.Valid {
		return Payload{}, fmt.Errorf("token no válido")
	}

	// Extraemos los datos del payload
	username, ok1 := claims["username"].(string)
	role, ok2 := claims["role"].(string)
	if !ok1 || !ok2 {
		return Payload{}, fmt.Errorf("payload del token malformado")
	}

	return Payload{Username: username, Role: role}, nil
}

// handler para generar un token JWT a partir de un payload JSON
func handleGenerateToken(w http.ResponseWriter, r *http.Request) {
	// Establecemos header para respuesta JSON
	w.Header().Set("Content-Type", "application/json")

	// Decodificamos el payload JSON de la solicitud
	var payload Payload
	err := json.NewDecoder(r.Body).Decode(&payload)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{"error": "payload JSON no válido"})
		return
	}

	// Generamos el token JWT
	token, err := generaToken(payload)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{"error": "error al generar el token"})
		return
	}

	// Respondemos con el token generado
	json.NewEncoder(w).Encode(ResponseToken{Token: token})
}

// handler para verificar un token JWT
func handleVerifyToken(w http.ResponseWriter, r *http.Request) {
	// Establecemos header para respuesta JSON
	w.Header().Set("Content-Type", "application/json")

	// Estructura para recibir el token de la solicitud
	type RequestToken struct {
		Token string `json:"token"`
	}

	var reqToken RequestToken
	err := json.NewDecoder(r.Body).Decode(&reqToken)
	if err != nil || reqToken.Token == "" {
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(ResponseVerify{Valid: false, Error: "token faltante o JSON no válido"})
		return
	}

	// Verificamos el token
	payload, err := verificaToken(reqToken.Token)
	if err != nil {
		w.WriteHeader(http.StatusUnauthorized)
		json.NewEncoder(w).Encode(ResponseVerify{Valid: false, Error: err.Error()})
		return
	}

	// Token válido, respondemos con el payload
	json.NewEncoder(w).Encode(ResponseVerify{Valid: true, Payload: payload})
}

func main() {
	// Registramos los endpoints HTTP
	http.HandleFunc("/generate-token", handleGenerateToken)
	http.HandleFunc("/verify-token", handleVerifyToken)

	// Iniciamos el servidor HTTP en el puerto 8080
	fmt.Println("Servidor iniciado en el puerto 8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

// Para probar:
// 1) POST /generate-token con body JSON {"username":"mario", "role":"admin"}
//    recibirás un token JWT
// 2) POST /verify-token con body JSON {"token":"<token recibido>"}
//    recibirás validez y payload decodificado
×
×
×
¿Quieres regenerar la respuesta?
×
Exportar chat
Elige el formato de exportación
⏳ Generazione PDF in corso…
Allegati
×
⚠️ Estás a punto de cerrar el chat y pasar al generador de imágenes. Si no has iniciado sesión, perderás nuestro chat. ¿Confirmas?
👁 Estás viendo un chat compartido en modo temporal. No se guardará.
💬
×
Prompts guardados
×
Nota privada
×
Etiqueta
×
Buscar en todos los chats
×
Tus insights
Analizando…
×
Preferencias de IA
Nombre del asistente 30
Longitud de las respuestas
Modelo de IA
Respuestas estructuradas
Incluir ejemplos
Usar emojis
Guíame, no resuelvas Pistas y preguntas en vez de la solución hecha
Más ajustes →
×
Compartir este chat
Quien abra este enlace podrá ver el chat o añadirlo a su perfil como chat propio.
⚠️ Atención: también se compartirán los archivos adjuntos del chat. Quien lo añada recibirá una copia en su propia carpeta.
Chat compartido
Alguien ha compartido un chat contigo. ¿Solo quieres verlo o añadirlo a tus chats?
⚠️ Atención: también se compartirán los archivos adjuntos del chat. Quien lo añada recibirá una copia en su propia carpeta.
×

📌 Mensajes guardados

Cargando...

×

Historial de Chat

programas-ejemplo · HISTORIAL DE CHAT

Cargando...

Preferencias de IA

×
  • 🟢 BásicoRespuestas rápidas y esenciales para estudiar
  • 🔵 MedioMayor calidad para estudio y programación
  • 🟣 AvanzadoRazonamiento complejo y análisis detallado
Explicar Pasos

¿Qué se necesita?

Go 1.20+ como lenguaje de programación

Biblioteca github.com/golang-jwt/jwt/v5 para creación y verificación de JWT

Módulo Go con gestión de módulos (go.mod) para dependencias

Servidor HTTP nativo de Go (net/http) para exponer APIs REST

Configuración: clave secreta para firma HS256 definida como constante

Endpoint POST /generate-token: recibe carga JSON, devuelve token JWT

Endpoint POST /verify-token: recibe token JWT, devuelve validez y carga decodificada

Estructura de datos Payload personalizada para contener datos de usuario (ej. username, rol)

Manejo robusto de errores con respuestas HTTP apropiadas y mensajes JSON

Archivo README.md (no incluido en el código) con instrucciones de ejecución y prueba

Ningún hardware Arduino involucrado en este proyecto de software