Autorización y autenticación en Go (Golang): resumen de herramientas clave
La autenticación (verificación de la identidad del usuario) y la autorización (verificación de los permisos de acceso) son componentes fundamentales de cualquier aplicación web. En el ecosistema de Go (Golang), existen varias bibliotecas probadas que permiten implementar estos mecanismos de forma rápida, segura y con una cantidad mínima de código. En este artículo, analizaremos cuatro enfoques principales: hash de contraseñas, tokens JWT, gestión de sesiones y OAuth2.
1. Hash de contraseñas: golang.org/x/crypto/bcrypt
El primer paso de cualquier autenticación es el almacenamiento seguro de contraseñas. ¡Nunca almacene contraseñas en texto plano! El paquete bcrypt de la colección estándar de Go proporciona un algoritmo de hash probado con costo adaptativo (cost factor).
Instalación:
go get golang.org/x/crypto/bcryptEjemplo de registro e inicio de sesión:
package main
import ( "fmt" "golang.org/x/crypto/bcrypt")
func hashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) return string(bytes), err}
func checkPasswordHash(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil}
func main() { password := "mySecretP@ssw0rd" hash, _ := hashPassword(password)
fmt.Println("Hash:", hash)
// Verificación de contraseña correcta match := checkPasswordHash(password, hash) fmt.Println("Password match:", match) // true
// Verificación de contraseña incorrecta match = checkPasswordHash("wrong", hash) fmt.Println("Wrong password match:", match) // false}Importante: bcrypt.DefaultCost es igual a 10. Para un nivel de seguridad más alto (pero más lento), use un valor de 12-14. Nunca use un cost menor a 10.
2. JWT (JSON Web Tokens) — github.com/golang-jwt/jwt/v5
JWT es una forma compacta de transferir datos entre partes como un objeto JSON. Es ideal para API REST y microservicios. El paquete golang-jwt/jwt es el más popular y con mantenimiento activo.
Instalación:
go get github.com/golang-jwt/jwt/v5Ejemplo de creación y verificación de JWT:
package main
import ( "fmt" "time" "github.com/golang-jwt/jwt/v5")
var jwtSecret = []byte("your-secret-key-keep-it-safe")
func createToken(userID string) (string, error) { claims := jwt.MapClaims{ "user_id": userID, "exp": time.Now().Add(24 * time.Hour).Unix(), } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(jwtSecret)}
func verifyToken(tokenString string) (string, error) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return jwtSecret, nil }) if err != nil { return "", err } if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { return claims["user_id"].(string), nil } return "", fmt.Errorf("invalid token")}
func main() { token, _ := createToken("user123") fmt.Println("JWT:", token)
userID, err := verifyToken(token) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Authenticated user:", userID) }}Consejo: Almacene la clave secreta en variables de entorno, no en el código. Para producción, use cifrado asimétrico (RS256).
3. Gestión de sesiones — gorilla/sessions
Para aplicaciones web clásicas con plantillas HTML, a