README
¶
Security
Paquete de seguridad con funciones de hashing y JWT para Go.
📦 Instalación
go get github.com/AndresGT/gokit/security
🔐 Hash
Uso Básico (bcrypt - Recomendado)
import "github.com/AndresGT/gokit/security/hash"
// Hashear contraseña
hashed, err := hash.HashPassword("mi-password")
// Verificar contraseña
valid := hash.CheckPassword("mi-password", hashed) // true
Argon2 (Más Seguro)
// Hashear con Argon2id
hashed, err := hash.HashPasswordArgon2("mi-password")
// Verificar
valid, err := hash.CheckPasswordArgon2("mi-password", hashed)
Tokens Aleatorios
// Token seguro de 32 bytes
token, err := hash.GenerateSecureToken()
// Token personalizado
token, err := hash.GenerateRandomToken(64)
// Bytes aleatorios
bytes, err := hash.GenerateRandomBytes(32)
Configuración Personalizada
// bcrypt con cost específico
hashed, err := hash.HashPasswordWithCost("password", 12)
// Argon2 con parámetros personalizados
hashed, err := hash.HashPasswordArgon2WithParams("password", hash.Argon2Params{
Memory: 128 * 1024,
Iterations: 4,
Parallelism: 4,
SaltLength: 32,
KeyLength: 64,
})
// Verificar si un hash necesita regenerarse
if hash.NeedsRehash(oldHash, 12) {
newHash, _ := hash.HashPasswordWithCost(password, 12)
// Actualizar en DB
}
🎫 JWT
Configuración
import "github.com/AndresGT/gokit/security/jwt"
// Configurar JWT (hacer una vez al inicio)
jwt.Configure(jwt.Config{
Secret: "tu-secreto-seguro",
RefreshSecret: "otro-secreto", // Opcional
AccessTokenDuration: 24 * time.Hour, // 24 horas
RefreshTokenDuration: 7 * 24 * time.Hour, // 7 días
Issuer: "mi-aplicacion",
})
Generar Tokens
import "github.com/google/uuid"
userID := uuid.New()
// Token simple
token, err := jwt.Generate(userID, "admin")
// Token con claims extra
token, err := jwt.GenerateWithExtra(userID, "user", map[string]interface{}{
"email": "user@example.com",
"permissions": []string{"read", "write"},
})
// Par de tokens (access + refresh)
pair, err := jwt.GeneratePair(userID, "user")
// pair.AccessToken
// pair.RefreshToken
// pair.ExpiresAt
Validar Tokens
// Validar access token
claims, err := jwt.Validate(token)
if err != nil {
// Token inválido
}
// Usar claims
userID, _ := uuid.Parse(claims.UserID)
role := claims.Role
extra := claims.Extra
// Validar refresh token
claims, err := jwt.ValidateRefreshToken(refreshToken)
Refresh Tokens
// Generar nuevo par de tokens con refresh token
newPair, err := jwt.Refresh(oldRefreshToken)
Helpers
// Verificar si está expirado
if jwt.IsExpired(token) {
// Token expirado
}
// Obtener user_id sin validar completamente
userID, err := jwt.GetUserID(token)
// Obtener claims sin validar (para debugging)
claims, err := jwt.GetClaims(token)
🎯 Tipos
Claims
type Claims struct {
UserID string `json:"user_id"`
Role string `json:"role"`
Extra map[string]interface{} `json:"extra,omitempty"`
jwt.RegisteredClaims
}
TokenPair
type TokenPair struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresAt time.Time `json:"expires_at"`
}
⚙️ Configuración Avanzada
jwt.Configure(jwt.Config{
Secret: os.Getenv("JWT_SECRET"),
RefreshSecret: os.Getenv("JWT_REFRESH_SECRET"),
AccessTokenDuration: 15 * time.Minute, // Tokens cortos
RefreshTokenDuration: 30 * 24 * time.Hour, // 30 días
Issuer: "my-app-v2",
SigningMethod: jwt.SigningMethodHS512, // Algoritmo personalizado
})
💡 Mejores Prácticas
Hash
- Usa bcrypt por defecto - balance perfecto entre seguridad y performance
- Usa Argon2 para datos muy sensibles - más seguro pero más lento
- Aumenta el cost gradualmente - según mejora el hardware
- Regenera hashes antiguos - usa
NeedsRehash()para actualizar
// Al login, verificar si necesita rehash
if hash.CheckPassword(password, storedHash) {
if hash.NeedsRehash(storedHash, 12) {
newHash, _ := hash.HashPasswordWithCost(password, 12)
// Actualizar en DB
}
// Login exitoso
}
JWT
- Tokens de vida corta - access tokens de 15min a 1h
- Refresh tokens de vida larga - 7 a 30 días
- Secretos diferentes - access y refresh con secretos distintos
- Rota secretos - cambia secretos periódicamente en producción
- Valida siempre - nunca confíes en tokens sin validar
// Flujo recomendado
func login(email, password string) (*jwt.TokenPair, error) {
// 1. Validar credenciales
user, err := validateCredentials(email, password)
if err != nil {
return nil, err
}
// 2. Generar tokens
return jwt.GeneratePair(user.ID, user.Role)
}
func refresh(refreshToken string) (*jwt.TokenPair, error) {
// 1. Validar refresh token
// 2. Generar nuevo par
return jwt.Refresh(refreshToken)
}
🔗 Links
Parte de gokit - Tu toolkit de Go para desarrollo rápido
Click to show internal directories.
Click to hide internal directories.