gologin

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2025 License: MIT Imports: 12 Imported by: 0

README

gologin 🔐

Librería de autenticación JWT embeddable para Go

Sistema de autenticación completo con JWT tokens, rate limiting, token blacklist y arquitectura embeddable. Production-ready.

🚀 Instalación

go get github.com/ElDavosJar/[email protected]

📋 ¿Qué incluye?

Funcionalidades Completas
  • Registro de usuarios con validación robusta
  • Login seguro con JWT tokens
  • Refresh tokens con rotación automática
  • Logout completo (individual y masivo)
  • Rate limiting anti-brute force
  • Token blacklist para revocación
Seguridad Production-Ready
  • Bcrypt hashing con cost configurable
  • JWT HS256 con secrets de 32+ caracteres
  • Validación de passwords (longitud, mayúsculas, números, especiales)
  • Username sanitización y validación
  • Protección contra timing attacks
Arquitectura Embeddable
  • Agnóstico de BD: PostgreSQL, MySQL, MongoDB, DynamoDB, etc.
  • Embeddable: Struct User para embeber en tus entidades de dominio
  • Configurable: Rate limiting, expiración de tokens, etc.
  • Test-friendly: Interfaces y mocks incluidos

🎯 Inicio Rápido (3 minutos)

1. Implementa tu repositorio de usuarios

Crea una implementación de UserRepository para tu base de datos.

2. Crea el servicio de autenticación
authService := gologin.NewAuthService(tuRepo, "tu-jwt-secret-32-chars-minimo")
3. ¡Usa la autenticación!
  • RegisterUser() - Registrar usuarios
  • Login() - Autenticar usuarios
  • ValidateToken() - Verificar tokens JWT
  • RefreshAccessToken() - Renovar tokens
  • Logout() - Invalidar tokens

📖 Guía de Uso

Configuraciones Disponibles
  • Básica: Solo autenticación JWT
  • Con Mapeo: Para bases de datos legacy
  • Completa: Con rate limiting y token blacklist
  • Embeddable: User struct para embeber en tus entidades
Interfaces a Implementar

Para usar gologin necesitas implementar UserRepository para tu base de datos. Las interfaces TokenBlacklist y RateLimiter son opcionales.

🔧 API Reference

Métodos Principales
  • RegisterUser(ownerType, ownerID, username, password) - Registrar usuarios
  • Login(LoginRequest) - Autenticar usuarios
  • ValidateToken(token) - Verificar tokens JWT
  • RefreshAccessToken(refreshToken) - Renovar access tokens
  • Logout(token) - Invalidar tokens específicos
  • LogoutAll(userID) - Invalidar todos los tokens de un usuario
Interfaces Requeridas
  • UserRepository - Para persistencia de usuarios (requerida)
  • TokenBlacklist - Para revocación de tokens (opcional)
  • RateLimiter - Para protección anti-brute force (opcional)

📚 Infraestructura Soportada

Componente Interfaz Implementaciones
Base de Datos UserRepository PostgreSQL, MySQL, MongoDB, DynamoDB, In-Memory
Rate Limiting RateLimiter Redis, Memcached, In-Memory
Token Blacklist TokenBlacklist Redis, PostgreSQL, In-Memory

🧪 Testing

# Tests unitarios
go test -v ./...

# Tests de integración
cd examples && go test -v integration_test.go

# Aplicación de ejemplo
cd examples && go run full_app_example.go

📖 Más Información

  • examples/ - Aplicaciones completas funcionando
  • BETA_TESTING_GUIDE.md - Guía detallada de testing
  • BETA_RELEASE_NOTES.md - Notas de la versión

🏗️ Arquitectura

Componentes Principales
  • User: Struct embeddable con credenciales básicas
  • AuthService: API principal de autenticación
  • UserRepository: Interfaz para persistencia (requerida)
  • JWTService: Manejo interno de tokens JWT
Diseño Embeddable

La struct User está diseñada para ser embebida en tus entidades de dominio:

type BusinessUser struct {
    gologin.User  // Embed the User struct
    Email         string
    Role          string
    CompanyID     string
}

🔒 Seguridad

  • Bcrypt hashing con cost configurable
  • JWT HS256 con secrets de 32+ caracteres
  • Rate limiting configurable
  • Token rotation automática
  • Input validation completa

🧪 Calidad

  • Tests unitarios completos
  • Tests de integración incluidos
  • Cobertura 100% en funcionalidades críticas
  • Documentación completa
  • Ejemplos funcionando

📄 Licencia

MIT License - Uso gratuito para proyectos personales y comerciales.


🎯 ¿Listo para usar gologin?

  1. Instala: go get github.com/ElDavosJar/[email protected]
  2. Implementa: UserRepository para tu base de datos
  3. Configura: Elige tu nivel de seguridad
  4. ¡Usa!: Autenticación completa en minutos

¿Necesitas ayuda? Revisa los ejemplos en examples/ o abre un issue en GitHub.

Documentation

Overview

Package gologin provides a flexible authentication system for Go applications. It allows creating user credentials that belong to any domain entity (business profiles, customers, admins, etc.) without assuming specific domain models.

The package assumes standard database field names (id, username, password_hash, created_at) but allows customization for legacy systems.

The package is designed to be cohesive and idiomatic Go, with structs that have methods and interfaces for dependency injection.

Index

Constants

View Source
const (
	DefaultIDField           = "id"
	DefaultUsernameField     = "username"
	DefaultPasswordHashField = "password_hash"
	DefaultCreatedAtField    = "created_at"
)

Standard field names assumed by the library

Variables

View Source
var DefaultPasswordStrength = PasswordStrength{
	MinLength:      8,
	RequireUpper:   true,
	RequireLower:   true,
	RequireNumber:  true,
	RequireSpecial: false,
}

DefaultPasswordStrength provides secure default password requirements

View Source
var ErrRateLimitExceeded = fmt.Errorf("rate limit exceeded: too many attempts, please try again later")

ErrRateLimitExceeded is returned when rate limit is exceeded

Functions

func HashPassword

func HashPassword(password string) (string, error)

HashPassword creates a bcrypt hash of the given password. It uses the default cost for bcrypt which provides good security.

func HashPasswordWithStrength

func HashPasswordWithStrength(password string, strength *PasswordStrength) (string, error)

HashPasswordWithStrength creates a bcrypt hash with custom password policy

func SanitizeUsername

func SanitizeUsername(username string) string

SanitizeUsername removes or replaces invalid characters from a username This can be used to suggest valid usernames to users

func ValidatePasswordStrength

func ValidatePasswordStrength(password string, strength PasswordStrength) error

ValidatePasswordStrength checks if a password meets strength requirements

func ValidateUsername

func ValidateUsername(username string) error

ValidateUsername checks if a username meets security and format requirements

func VerifyPassword

func VerifyPassword(password, hash string) error

VerifyPassword compares a password with its hash. Returns nil if the password matches, error otherwise.

Types

type AuthConfig

type AuthConfig struct {
	// JWT Configuration
	JWTSecret          string        // OBLIGATORIO: Secreto para firmar tokens (mínimo 32 caracteres)
	AccessTokenExpiry  time.Duration // Por defecto: 15 minutos
	RefreshTokenExpiry time.Duration // Por defecto: 7 días

	// Optional Features
	Blacklist       TokenBlacklist // OPCIONAL: Para revocar tokens (nil = desactivado)
	LoginLimiter    RateLimiter    // OPCIONAL: Para proteger login (nil = desactivado)
	RegisterLimiter RateLimiter    // OPCIONAL: Para proteger registro (nil = desactivado)

	// Field Mapping (para sistemas legacy)
	FieldMapping *FieldMapping // OPCIONAL: Por defecto usa campos estándar

	// Password Policy
	PasswordStrength *PasswordStrength // OPCIONAL: Por defecto usa DefaultPasswordStrength
}

AuthConfig contiene toda la configuración del sistema de autenticación Todos los campos son opcionales y tienen valores por defecto seguros

func DefaultAuthConfig

func DefaultAuthConfig(jwtSecret string) *AuthConfig

DefaultAuthConfig retorna una configuración por defecto segura

func (*AuthConfig) Validate

func (c *AuthConfig) Validate() error

Validate verifica que la configuración sea válida

type AuthResponse

type AuthResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	User         *User  `json:"user"`
}

AuthResponse contains the tokens returned after successful authentication

type AuthService

type AuthService interface {
	RegisterUser(ownerType, ownerID, username, password string) (*User, error)
	Login(req LoginRequest) (*AuthResponse, error)
	ValidateToken(tokenString string) (*Claims, error)
	RefreshAccessToken(refreshToken string) (*AuthResponse, error)
	Logout(tokenString string) error // Revoke token
	LogoutAll(userID string) error   // Revoke all tokens for a user
}

AuthService provides authentication operations. It depends on a UserRepository for persistence.

func NewAuthService

func NewAuthService(repo UserRepository, jwtSecret string) AuthService

NewAuthService creates a minimal authentication service (sin rate limiting ni blacklist) Ideal para desarrollo, testing, o sistemas simples

func NewAuthServiceWithConfig

func NewAuthServiceWithConfig(repo UserRepository, config *AuthConfig) AuthService

NewAuthServiceWithConfig crea un servicio con configuración completa

func NewAuthServiceWithMapping

func NewAuthServiceWithMapping(repo UserRepository, jwtSecret string, fieldMapping *FieldMapping) AuthService

NewAuthServiceWithMapping creates a new authentication service with custom field mapping

func NewAuthServiceWithOptions

func NewAuthServiceWithOptions(repo UserRepository, jwtSecret string, blacklist TokenBlacklist, loginLimiter, registerLimiter RateLimiter) AuthService

NewAuthServiceWithOptions crea un servicio con características avanzadas opcionales Usa esto si necesitas: rate limiting, blacklist, o configuración personalizada

func NewAuthServiceWithOptionsAndMapping

func NewAuthServiceWithOptionsAndMapping(repo UserRepository, jwtSecret string, blacklist TokenBlacklist, loginLimiter, registerLimiter RateLimiter, fieldMapping *FieldMapping) AuthService

NewAuthServiceWithOptionsAndMapping creates a new authentication service with custom options and field mapping

type Claims

type Claims struct {
	UserID    string `json:"user_id"`
	Username  string `json:"username"`
	TokenType string `json:"token_type"` // "access" or "refresh"
	TokenID   string `json:"jti"`        // JWT ID for blacklisting
	ExpiresAt int64  `json:"exp"`
	IssuedAt  int64  `json:"iat"`
}

Claims represents the JWT payload

func (*Claims) GetAudience

func (c *Claims) GetAudience() (jwt.ClaimStrings, error)

GetAudience implements jwt.Claims interface

func (*Claims) GetExpirationTime

func (c *Claims) GetExpirationTime() (*jwt.NumericDate, error)

GetExpirationTime implements jwt.Claims interface

func (*Claims) GetIssuedAt

func (c *Claims) GetIssuedAt() (*jwt.NumericDate, error)

GetIssuedAt implements jwt.Claims interface

func (*Claims) GetIssuer

func (c *Claims) GetIssuer() (string, error)

GetIssuer implements jwt.Claims interface

func (*Claims) GetNotBefore

func (c *Claims) GetNotBefore() (*jwt.NumericDate, error)

GetNotBefore implements jwt.Claims interface

func (*Claims) GetSubject

func (c *Claims) GetSubject() (string, error)

GetSubject implements jwt.Claims interface

type DefaultAuthService

type DefaultAuthService struct {
	// contains filtered or unexported fields
}

DefaultAuthService provides the main authentication implementation

func (*DefaultAuthService) Login

Login authenticates a user and returns tokens

func (*DefaultAuthService) Logout

func (a *DefaultAuthService) Logout(tokenString string) error

Logout revokes a specific token by adding it to the blacklist

func (*DefaultAuthService) LogoutAll

func (a *DefaultAuthService) LogoutAll(userID string) error

LogoutAll revokes all tokens for a specific user

func (*DefaultAuthService) RefreshAccessToken

func (a *DefaultAuthService) RefreshAccessToken(refreshToken string) (*AuthResponse, error)

RefreshAccessToken generates a new access token using a refresh token CRITICAL SECURITY: Implements token rotation to prevent replay attacks

func (*DefaultAuthService) RegisterUser

func (a *DefaultAuthService) RegisterUser(ownerType, ownerID, username, password string) (*User, error)

RegisterUser creates a new user with credentials

func (*DefaultAuthService) ValidateToken

func (a *DefaultAuthService) ValidateToken(tokenString string) (*Claims, error)

ValidateToken validates a JWT token and returns its claims

type FieldMapping

type FieldMapping struct {
	ID           string
	Username     string
	PasswordHash string
	CreatedAt    string
}

FieldMapping allows customization of database field names for legacy systems

func DefaultFieldMapping

func DefaultFieldMapping() *FieldMapping

DefaultFieldMapping returns the standard field mapping

type InMemoryRateLimiter

type InMemoryRateLimiter struct {
	// contains filtered or unexported fields
}

InMemoryRateLimiter is a simple in-memory implementation of RateLimiter For production use, consider a distributed solution (Redis, etc.)

func NewInMemoryRateLimiter

func NewInMemoryRateLimiter(maxAttempts int, windowPeriod time.Duration) *InMemoryRateLimiter

NewInMemoryRateLimiter creates a new in-memory rate limiter maxAttempts: maximum number of attempts allowed within the window period windowPeriod: time window for counting attempts (e.g., 15 minutes)

func (*InMemoryRateLimiter) Allow

func (rl *InMemoryRateLimiter) Allow(identifier string) bool

Allow checks if an attempt is allowed for the given identifier

func (*InMemoryRateLimiter) GetRemainingAttempts

func (rl *InMemoryRateLimiter) GetRemainingAttempts(identifier string) int

GetRemainingAttempts returns how many attempts are left for an identifier

func (*InMemoryRateLimiter) Reset

func (rl *InMemoryRateLimiter) Reset(identifier string)

Reset clears the attempt count for an identifier

type InMemoryTokenBlacklist

type InMemoryTokenBlacklist struct {
	// contains filtered or unexported fields
}

InMemoryTokenBlacklist is a simple in-memory implementation For production, use Redis or a database with TTL support

func NewInMemoryTokenBlacklist

func NewInMemoryTokenBlacklist() *InMemoryTokenBlacklist

NewInMemoryTokenBlacklist creates a new in-memory token blacklist

func (*InMemoryTokenBlacklist) Add

func (bl *InMemoryTokenBlacklist) Add(tokenID string, expiresAt time.Time) error

Add adds a token to the blacklist

func (*InMemoryTokenBlacklist) Count

func (bl *InMemoryTokenBlacklist) Count() int

Count returns the number of blacklisted tokens

func (*InMemoryTokenBlacklist) IsBlacklisted

func (bl *InMemoryTokenBlacklist) IsBlacklisted(tokenID string) bool

IsBlacklisted checks if a token is blacklisted

func (*InMemoryTokenBlacklist) Remove

func (bl *InMemoryTokenBlacklist) Remove(tokenID string) error

Remove removes a token from the blacklist

type JWTService

type JWTService struct {
	// contains filtered or unexported fields
}

JWTService handles JWT token operations

func NewJWTService

func NewJWTService(secretKey string, accessExpiry, refreshExpiry time.Duration) *JWTService

NewJWTService creates a new JWT service with the given secret key SECURITY: secretKey MUST be at least 32 bytes for production use

func (*JWTService) GenerateTokenPair

func (j *JWTService) GenerateTokenPair(user *User) (*AuthResponse, error)

GenerateTokenPair creates both access and refresh tokens for a user

func (*JWTService) RefreshAccessToken

func (j *JWTService) RefreshAccessToken(refreshToken string) (*AuthResponse, error)

RefreshAccessToken generates a new access token using a valid refresh token

func (*JWTService) ValidateToken

func (j *JWTService) ValidateToken(tokenString string) (*Claims, error)

ValidateToken parses and validates a JWT token

type LoginRequest

type LoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

LoginRequest contains the credentials for authentication

type PasswordStrength

type PasswordStrength struct {
	MinLength      int
	RequireUpper   bool
	RequireLower   bool
	RequireNumber  bool
	RequireSpecial bool
}

PasswordStrength represents the strength requirements for passwords

type RateLimiter

type RateLimiter interface {
	// Allow checks if an action is allowed for the given identifier
	// Returns true if allowed, false if rate limit exceeded
	Allow(identifier string) bool

	// Reset clears the attempt count for an identifier
	Reset(identifier string)
}

RateLimiter provides protection against brute force attacks by limiting the number of attempts from a specific identifier (IP, username, etc.)

type RedisRateLimiter

type RedisRateLimiter struct {
	// contains filtered or unexported fields
}

RedisRateLimiter implements RateLimiter using Redis for distributed environments It is production-ready and works across multiple instances

Usage:

limiter := NewRedisRateLimiter(redisClient, 5, 15*time.Minute)
allowed := limiter.Allow("login:username")

func NewRedisRateLimiter

func NewRedisRateLimiter(client *redis.Client, maxAttempts int, window time.Duration) *RedisRateLimiter

func (*RedisRateLimiter) Allow

func (r *RedisRateLimiter) Allow(identifier string) bool

func (*RedisRateLimiter) Reset

func (r *RedisRateLimiter) Reset(identifier string)

type RedisTokenBlacklist

type RedisTokenBlacklist struct {
	// contains filtered or unexported fields
}

RedisTokenBlacklist implements TokenBlacklist using Redis for distributed revocation Usage:

blacklist := NewRedisTokenBlacklist(redisClient)
blacklist.Add(tokenID, expiresAt)

func NewRedisTokenBlacklist

func NewRedisTokenBlacklist(client *redis.Client) *RedisTokenBlacklist

func (*RedisTokenBlacklist) Add

func (r *RedisTokenBlacklist) Add(tokenID string, expiresAt time.Time) error

func (*RedisTokenBlacklist) IsBlacklisted

func (r *RedisTokenBlacklist) IsBlacklisted(tokenID string) bool

func (*RedisTokenBlacklist) Remove

func (r *RedisTokenBlacklist) Remove(tokenID string) error

type TokenBlacklist

type TokenBlacklist interface {
	// Add adds a token to the blacklist until its expiration time
	Add(tokenID string, expiresAt time.Time) error

	// IsBlacklisted checks if a token is blacklisted
	IsBlacklisted(tokenID string) bool

	// Remove removes a token from the blacklist (cleanup after expiration)
	Remove(tokenID string) error
}

TokenBlacklist provides a mechanism to revoke tokens before they expire This is essential for logout functionality and security incidents

type User

type User struct {
	ID           *string   // nil until saved to storage
	Username     string    // Unique username for login
	PasswordHash string    // bcrypt hash of the password
	CreatedAt    time.Time // When the user was created
}

User represents authentication credentials. Embed this struct in your domain entities to add authentication capabilities.

func (*User) IsValid

func (u *User) IsValid() bool

IsValid checks if the user has valid data according to business rules

type UserRepository

type UserRepository interface {
	Save(user *User) error
	FindByUsername(username string) (*User, error)
	FindByID(id string) (*User, error)
	IsUsernameTaken(username string) (bool, error)
	// GetActiveTokenIDs returns all active token IDs for a user (for LogoutAll)
	GetActiveTokenIDs(userID string) ([]string, error)
}

UserRepository defines the interface for user persistence. Implement this interface to integrate with your storage system.

Directories

Path Synopsis
Package main demonstrates a complete application using gologin This example shows how to integrate gologin into a real web application
Package main demonstrates a complete application using gologin This example shows how to integrate gologin into a real web application

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL