Introducción: ¿por qué son necesarios OAuth 2.0 y JWT en Go?
\nLas aplicaciones web y API modernas rara vez prescinden de un sistema de autorización. Si está escribiendo en Go (Golang) y desea proteger sus endpoints, necesita familiarizarse con dos tecnologías clave: OAuth 2.0 (protocolo de delegación de acceso) y JWT (JSON Web Token — formato compacto de token).
\nEn este artículo, analizaremos cómo implementar una autorización segura en Go desde cero. Aprenderá:
\n- \n
- En qué se diferencia OAuth 2.0 de JWT y cómo funcionan juntos. \n
- Cómo generar y verificar tokens JWT en Go. \n
- Cómo construir una autorización OAuth 2.0 mínima (flujo de credenciales de cliente). \n
- Cómo proteger una API REST con middleware. \n
El artículo está dirigido a desarrolladores principiantes que ya están familiarizados con los conceptos básicos de Go y los servidores HTTP.
\n\nFundamentos: OAuth 2.0 y JWT no son lo mismo
\nMuchos principiantes confunden estos conceptos. Aclaremos las cosas de inmediato.
\n\n¿Qué es OAuth 2.0?
\nOAuth 2.0 es un protocolo de autorización que permite a un servicio (cliente) obtener acceso limitado a los recursos de otro servicio (servidor) en nombre del usuario. Imagine que desea iniciar sesión en un sitio web a través de Google. El sitio no obtiene su contraseña; obtiene de Google un token temporal que solo da acceso a su correo electrónico (y eso con su consentimiento).
\nRoles principales en OAuth 2.0:
\n- \n
- Resource Owner — propietario de los datos (generalmente el usuario). \n
- Client — aplicación que desea obtener acceso. \n
- Authorization Server — servidor que emite tokens después de la verificación. \n
- Resource Server — servidor que almacena datos protegidos y verifica tokens. \n
¿Qué es JWT?
\nJWT (JSON Web Token) es el formato del token en sí. Es una cadena de tres partes separadas por puntos: header.payload.signature. JWT puede contener cualquier dato (por ejemplo, ID de usuario, rol, fecha de vencimiento) y está firmado con una clave secreta para que no pueda ser falsificado.
OAuth 2.0 no está vinculado a JWT: el token puede ser cualquier cadena. Sin embargo, en la práctica, JWT se usa con mayor frecuencia porque es autosuficiente: el servidor no necesita almacenar sesiones en la base de datos, toda la información se puede verificar sobre la marcha.
\n\nImplementación de JWT en Go: generación y verificación de tokens
\nComencemos con la práctica. Para trabajar con JWT en Go, usaremos la biblioteca golang-jwt/jwt/v5. Instálela:
go get github.com/golang-jwt/jwt/v5\n\nGeneración de Access Token
\nCreemos una función que tome el ID del usuario y devuelva un token JWT firmado con un tiempo de vida de 1 hora.
\npackage main\n\nimport (\n "time"\n "github.com/golang-jwt/jwt/v5"\n)\n\nvar jwtSecret = []byte("your-secret-key") // ¡En producción, guárdelo en .env!\n\ntype Claims struct {\n UserID uint `json:"user_id"`\n jwt.RegisteredClaims\n}\n\nfunc GenerateAccessToken(userID uint) (string, error) {\n claims := Claims{\n UserID: userID,\n RegisteredClaims: jwt.RegisteredClaims{\n ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),\n IssuedAt: jwt.NewNumericDate(time.Now()),\n Issuer: "my-app",\n },\n }\n token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\n return token.SignedString(jwtSecret)\n}\n\nVerificación y análisis de JWT
\nAhora escribamos un middleware que verifique el token del encabezado Authorization: Bearer <token>.
func ValidateToken(tokenString string) (*Claims, error) {\n token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {\n // Verificamos que se esté utilizando el método de firma correcto\n