token

package
v0.0.7-2 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 7 Imported by: 0

README

GoKit Token — JWT & Sesiones

Módulo de autenticación para el ecosistema GoKit: emisión/validación de JSON Web Tokens (access + refresh) y gestión completa del ciclo de vida de sesiones de usuario, con soporte para revocación, expiración por inactividad y límite de sesiones concurrentes.

🌟 Características

JWT (JSON Web Tokens)
  • ✅ Access tokens y refresh tokens con claims personalizados (UserID, Role, SessionID, Email, etc.)
  • ✅ Firma HMAC-SHA256 con verificación estricta del método (previene ataques de confusión de algoritmos)
  • ✅ Distinción explícita entre access token y refresh token (TokenType)
  • ✅ Duraciones configurables manualmente o derivadas automáticamente de security.Level
  • ✅ API dual: Manager configurable + funciones globales de uso rápido
  • ✅ Helpers para prototipado rápido (GenerateQuickToken, ValidateQuickToken, etc.)
Sesiones
  • ✅ Ciclo de vida completo: creación, validación, revocación individual/masiva, limpieza
  • ✅ Expiración absoluta (ExpiresAt) e inactividad (IdleTimeout, "sliding expiration")
  • ✅ Límite de sesiones concurrentes por usuario con revocación automática de las más antiguas
  • ✅ Abstracción SessionStore para usar cualquier backend (Redis, BD, etc.)
  • ✅ MemorySessionStore incluido para desarrollo/testing
  • ✅ API dual: Manager configurable + funciones globales de uso rápido

📦 Instalación

go get github.com/AndresGT/GoKit/security/token

Dependencias:

  • github.com/AndresGT/GoKit/security (niveles de seguridad, errores)
  • github.com/AndresGT/GoKit/security/crypto (generación de UUIDs y strings seguros)
  • github.com/golang-jwt/jwt/v5 (librería JWT)

🚀 Inicio Rápido

Opción 1: Uso Rápido (Prototipado)

Ideal para empezar rápido sin configuración:

package main

import (
    "fmt"
    "github.com/AndresGT/GoKit/security/token"
)

func main() {
    // Generar token rápido
    tokenStr, err := token.GenerateQuickToken("user-123", "admin")
    if err != nil {
        panic(err)
    }
    
    // Validar token
    if token.ValidateQuickToken(tokenStr) {
        userID := token.ExtractUserID(tokenStr)
        fmt.Printf("Token válido, UserID: %s\n", userID)
    }
    
    // Crear sesión rápida
    sessionID, err := token.CreateQuickSession(token.SessionInfo{
        UserID:    "user-123",
        Username:  "john_doe",
        IPAddress: "192.168.1.100",
    })
    if err != nil {
        panic(err)
    }
    
    // Validar sesión
    if token.QuickSessionExists(sessionID) {
        fmt.Println("Sesión activa")
    }
}
Opción 2: Configuración Completa (Producción)

Para producción, configura managers personalizados:

package main

import (
    "fmt"
    "time"
    "github.com/AndresGT/GoKit/security"
    "github.com/AndresGT/GoKit/security/token"
)

func main() {
    // === JWT Manager ===
    jwtManager, err := token.NewJWTManager(token.JWTConfig{
        SecretKey:            []byte("clave-secreta-de-al-menos-32-bytes!!"),
        Issuer:               "mi-api",
        AccessTokenDuration:  15 * time.Minute,
        RefreshTokenDuration: 7 * 24 * time.Hour,
    })
    if err != nil {
        panic(err)
    }
    
    // O usar nivel de seguridad (usa valores predeterminados)
    jwtManagerHigh, _ := token.NewJWTManager(token.JWTConfig{
        SecretKey:     []byte("otra-clave-secreta-de-32-bytes-min!!"),
        Issuer:        "mi-api",
        SecurityLevel: security.LevelHigh,
    })
    
    // === Session Manager ===
    sessionManager, err := token.NewSessionManager(token.SessionConfig{
        SecurityLevel:         security.LevelHigh,
        MaxConcurrentSessions: 3,
        // Store: redisStore, // En producción, usa un backend persistente
    })
    if err != nil {
        panic(err)
    }
    
    // === Ejemplo de flujo completo ===
    // 1. Login → Generar tokens
    claims := token.Claims{
        UserID:    "user-123",
        Username:  "john_doe",
        Role:      "admin",
        Email:     "john@example.com",
    }
    
    accessToken, _ := jwtManager.GenerateAccessToken(claims)
    refreshToken, _ := jwtManager.GenerateRefreshToken(claims)
    
    // 2. Crear sesión
    sessionID, _ := sessionManager.CreateSession(token.SessionInfo{
        UserID:    "user-123",
        Username:  "john_doe",
        IPAddress: "192.168.1.100",
        UserAgent: "Mozilla/5.0...",
    })
    
    // 3. Validar token en cada request
    validatedClaims, err := jwtManager.ValidateToken(accessToken)
    if err != nil {
        // Token inválido o expirado
        return
    }
    fmt.Printf("Usuario: %s, Rol: %s\n", validatedClaims.UserID, validatedClaims.Role)
    
    // 4. Validar sesión en cada request
    session, err := sessionManager.ValidateSession(sessionID)
    if err != nil {
        // Sesión inválida o expirada
        return
    }
    fmt.Printf("Sesión activa desde: %s\n", session.IPAddress)
    
    // 5. Refresh token cuando expire el access token
    newAccessToken, err := jwtManager.RefreshAccessToken(refreshToken)
    if err != nil {
        // Refresh token expirado → requerir re-login
        return
    }
    _ = newAccessToken
    
    // 6. Logout → Revocar sesión
    _ = sessionManager.RevokeSession(sessionID, "user_logout")
    
    // 7. Logout global (ej. tras cambio de contraseña)
    _ = sessionManager.RevokeAllUserSessions("user-123", "password_changed")
}

📚 API Reference

JWT Manager
Configuración
type JWTConfig struct {
    SecretKey            []byte        // Mínimo 32 bytes para HMAC-SHA256
    Issuer               string        // Emisor del token (ej. "api.example.com")
    AccessTokenDuration  time.Duration // Duración del access token
    RefreshTokenDuration time.Duration // Duración del refresh token
    SecurityLevel        security.Level // Nivel de seguridad para valores por defecto
}
Métodos del Manager
Método Descripción Retorna
NewJWTManager(config) Crea un manager de JWT (*JWTManager, error)
GenerateAccessToken(claims) Genera access token (string, error)
GenerateRefreshToken(claims) Genera refresh token (string, error)
ValidateToken(tokenString) Valida token y extrae claims (*Claims, error)
RefreshAccessToken(refreshToken) Renueva access token (string, error)
GetConfig() Obtiene configuración actual JWTConfig
Claims Personalizados
type Claims struct {
    jwt.RegisteredClaims
    UserID     string `json:"user_id"`
    Username   string `json:"username,omitempty"`
    Role       string `json:"role,omitempty"`
    Email      string `json:"email,omitempty"`
    SessionID  string `json:"session_id,omitempty"`
    DeviceInfo string `json:"device_info,omitempty"`
    IPAddress  string `json:"ip_address,omitempty"`
    TokenType  string `json:"token_type,omitempty"` // "access" o "refresh"
}
Funciones Globales (Uso Rápido)
Función Descripción Ejemplo
Init(config) Inicializa manager global token.Init(JWTConfig{...})
GetDefault() Obtiene manager global manager := token.GetDefault()
GenerateAccessToken(claims) Genera access token global t, _ := token.GenerateAccessToken(c)
GenerateRefreshToken(claims) Genera refresh token global t, _ := token.GenerateRefreshToken(c)
ValidateToken(token) Valida token global c, _ := token.ValidateToken(t)
RefreshAccessToken(token) Renueva access token nt, _ := token.RefreshAccessToken(rt)
Funciones Helper (Prototipado)
Función Descripción Ejemplo
GenerateQuickToken(userID, role) Token rápido sin config t, _ := token.GenerateQuickToken("u1", "admin")
GenerateQuickTokenWithEmail(userID, email, role) Token rápido con email t, _ := token.GenerateQuickTokenWithEmail("u1", "a@b.com", "user")
ValidateQuickToken(token) Valida y retorna bool if token.ValidateQuickToken(t) {...}
ExtractUserID(token) Extrae UserID id := token.ExtractUserID(t)
ExtractClaims(token) Extrae todos los claims c := token.ExtractClaims(t)

Session Manager
Configuración
type SessionConfig struct {
    SessionTimeout        time.Duration // Tiempo máximo de vida absoluto
    IdleTimeout           time.Duration // Tiempo máximo de inactividad
    MaxConcurrentSessions int           // Máximo sesiones por usuario
    SecurityLevel         security.Level // Nivel de seguridad para defaults
    Store                 SessionStore   // Backend de almacenamiento
}
SessionStore Interface
type SessionStore interface {
    Save(session *Session) error
    Get(sessionID string) (*Session, error)
    GetByUserID(userID string) ([]*Session, error)
    Delete(sessionID string) error
    DeleteByUserID(userID string) error
    CleanExpired() (int, error)
}

Implementaciones disponibles:

  • MemorySessionStore: Para desarrollo/testing (no persistente)
  • Producción: Implementa tu propio store con Redis, PostgreSQL, MongoDB, etc.
Estructura Session
type Session struct {
    ID             string
    UserID         string
    Username       string
    IPAddress      string
    UserAgent      string
    DeviceInfo     string
    CreatedAt      time.Time
    LastActivityAt time.Time
    ExpiresAt      time.Time
    IdleTimeout    time.Duration
    IsValid        bool
    RevokedAt      time.Time
    RevokeReason   string
}
Métodos del Manager
Método Descripción Retorna
NewSessionManager(config) Crea manager de sesiones (*SessionManager, error)
CreateSession(info) Crea nueva sesión (sessionID, error)
GetSession(id) Obtiene sesión sin validar (*Session, error)
ValidateSession(id) Valida y actualiza actividad (*Session, error)
RevokeSession(id, reason) Revoca sesión específica error
RevokeAllUserSessions(uid, reason) Revoca todas las sesiones de un usuario error
GetUserSessions(uid) Obtiene sesiones activas de usuario ([]*Session, error)
CleanExpiredSessions() Limpia sesiones expiradas (count, error)
GetConfig() Obtiene configuración SessionConfig
Funciones Globales (Uso Rápido)
Función Descripción Ejemplo
InitSession(config) Inicializa manager global token.InitSession(SessionConfig{...})
GetDefaultSession() Obtiene manager global m := token.GetDefaultSession()
CreateQuickSession(info) Crea sesión rápida id, _ := token.CreateQuickSession(info)
ValidateQuickSession(id) Valida sesión rápida s, _ := token.ValidateQuickSession(id)
RevokeQuickSession(id, reason) Revoca sesión rápida token.RevokeQuickSession(id, "logout")
RevokeAllQuickSessions(uid, reason) Revoca todas las sesiones token.RevokeAllQuickSessions("u1", "pwd")
GetQuickUserSessions(uid) Obtiene sesiones de usuario sessions, _ := token.GetQuickUserSessions("u1")
QuickSessionExists(id) Verifica si existe sesión if token.QuickSessionExists(id) {...}
GetSessionUserID(id) Extrae UserID de sesión uid := token.GetSessionUserID(id)

🔐 Seguridad

JWT Best Practices
  1. Secret Key Segura: Mínimo 32 bytes, usa crypto.GenerateRandomBytes(32) en producción
  2. Rotación de Refresh Tokens: Invalida y reemplaza después de cada uso
  3. Validación Estricta: Verifica firma, expiración, emisor y método de firma
  4. TokenType Claim: Previene que access tokens se usen como refresh tokens
  5. No almacenes datos sensibles en los claims (los tokens son codificados en base64, no cifrados)
Sesiones Best Practices
  1. Backend Persistente: Usa Redis o BD en producción, nunca MemorySessionStore
  2. Límite de Sesiones: Configura MaxConcurrentSessions según tus necesidades (3-5 típico)
  3. Idle Timeout: Configura según el tipo de aplicación (15-30 min para apps bancarias, 2-8 horas para otras)
  4. Revocación Sincrónica: Al cambiar contraseña, revoca TODAS las sesiones
  5. Limpieza Periódica: Ejecuta CleanExpiredSessions() cada hora con un cron job
Niveles de Seguridad

El módulo integra con security.Level para configuración automática:

Nivel Access Token Refresh Token Sesión Idle Max Sesiones
Low 1h 24h 8h 1h 10
Medium 15m 7d 8h 30m 5
High 5m 1d 2h 15m 3
Critical 1m 1h 30m 5m 1

⚠️ Errores del Paquete

JWT Errors
var (
    ErrJWTInvalid              = errors.New("token JWT inválido")
    ErrJWTExpired              = errors.New("token JWT expirado")
    ErrJWTSigningMethodInvalid = errors.New("método de firma JWT inválido")
)
Session Errors
var (
    ErrSessionNotFound    = errors.New("sesión no encontrada")
    ErrSessionStoreFailed = errors.New("fallo en el almacenamiento de sesiones")
)

También puede retornar security.ErrSessionExpired cuando una sesión expira o es revocada.


🧪 Testing

El módulo incluye tests unitarios exhaustivos que cubren:

  • ✅ Generación y validación de JWT
  • ✅ Refresh token y rotación
  • ✅ Claims personalizados y extracción
  • ✅ Creación y validación de sesiones
  • ✅ Revocación de sesiones (individual y masiva)
  • ✅ Límite de sesiones concurrentes
  • ✅ Expiración por tiempo absoluto e inactividad
  • ✅ MemorySessionStore thread-safe
  • ✅ Funciones helper de uso rápido

Ejecutar tests:

cd security/token
go test -v -cover

📌 Production Checklist

  • Usar secret key generada criptográficamente (crypto.GenerateRandomBytes(32))
  • Configurar Issuer apropiado para tu dominio
  • Implementar SessionStore persistente (Redis/BD)
  • Configurar límites de sesiones según necesidades
  • Habilitar HTTPS para transmitir tokens de forma segura
  • Implementar rotación de refresh tokens
  • Agregar logging de eventos de seguridad (login, logout, revocación)
  • Configurar CORS apropiadamente si es API web
  • Establecer cookies HttpOnly + Secure + SameSite si usas cookies
No Hacer
  • ❌ No uses MemorySessionStore en producción
  • ❌ No almacenes contraseñas o datos ultrasensibles en JWT claims
  • ❌ No extiendas excesivamente la duración de access tokens (>1h)
  • ❌ No compartas la misma secret key entre diferentes entornos
  • ❌ No ignores la validación del TokenType en refresh tokens
  • ❌ No olvides revocar sesiones al cerrar sesión o cambiar contraseña

📜 Licencia

MIT License

Documentation

Index

Constants

View Source
const (
	TokenTypeAccess    = "access"
	TokenTypeRefresh   = "refresh"
	TokenTypeTemporary = "temporary"
)

Variables

View Source
var (
	ErrJWTInvalid              = errors.New("token JWT inválido")
	ErrJWTExpired              = errors.New("token JWT expirado")
	ErrJWTSigningMethodInvalid = errors.New("método de firma JWT inválido")
)
View Source
var (
	// ErrSessionNotFound se retorna cuando no se encuentra la sesión solicitada.
	// Es un error genérico que no revela si la sesión existió o fue revocada.
	ErrSessionNotFound = errors.New("sesión no encontrada")

	// ErrSessionStoreFailed se retorna cuando el almacenamiento de sesiones
	// no puede completar la operación (fallo de BD, Redis, etc.).
	ErrSessionStoreFailed = errors.New("fallo en el almacenamiento de sesiones")
)

Functions

func CreateQuickSession

func CreateQuickSession(info SessionInfo) (string, error)

CreateQuickSession crea una sesión rápida usando el manager global.

func ExtractUserID

func ExtractUserID(tokenString string) string

func GenerateAccessToken

func GenerateAccessToken(claims Claims) (string, error)

func GenerateQuickToken

func GenerateQuickToken(userID, role string) (string, error)

func GenerateQuickTokenWithEmail

func GenerateQuickTokenWithEmail(userID, email, role string) (string, error)

func GenerateRefreshToken

func GenerateRefreshToken(claims Claims) (string, error)

func GetSessionUserID

func GetSessionUserID(sessionID string) string

GetSessionUserID extrae el UserID de una sesión válida. Retorna string vacío si la sesión es inválida.

func Init

func Init(config JWTConfig) error

func InitSession

func InitSession(config SessionConfig) error

InitSession permite reconfigurar el manager global de sesiones.

Ejemplo:

token.InitSession(token.SessionConfig{
    SecurityLevel:         security.LevelHigh,
    MaxConcurrentSessions: 3,
})

func QuickSessionExists

func QuickSessionExists(sessionID string) bool

QuickSessionExists verifica si una sesión existe y está activa. Retorna true si la sesión es válida, false en caso contrario.

func RefreshAccessToken

func RefreshAccessToken(refreshTokenString string) (string, error)

func RevokeAllQuickSessions

func RevokeAllQuickSessions(userID, reason string) error

RevokeAllQuickSessions revoca todas las sesiones de un usuario.

func RevokeQuickSession

func RevokeQuickSession(sessionID, reason string) error

RevokeQuickSession revoca una sesión usando el manager global.

func ValidateQuickToken

func ValidateQuickToken(tokenString string) bool

Types

type Claims

type Claims struct {
	jwt.RegisteredClaims

	UserID     string                 `json:"user_id"`
	Username   string                 `json:"username,omitempty"`
	Role       string                 `json:"role,omitempty"`
	Email      string                 `json:"email,omitempty"`
	SessionID  string                 `json:"session_id,omitempty"`
	DeviceInfo string                 `json:"device_info,omitempty"`
	IPAddress  string                 `json:"ip_address,omitempty"`
	TokenType  string                 `json:"token_type,omitempty"`
	CustomData map[string]interface{} `json:"custom_data,omitempty"`
}

func ExtractClaims

func ExtractClaims(tokenString string) *Claims

func ValidateToken

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

type JWTConfig

type JWTConfig struct {
	SecretKey            []byte
	Issuer               string
	AccessTokenDuration  time.Duration
	RefreshTokenDuration time.Duration
	SecurityLevel        security.Level
}

type JWTManager

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

func GetDefault

func GetDefault() *JWTManager

func NewJWTManager

func NewJWTManager(config JWTConfig) (*JWTManager, error)

func (*JWTManager) GenerateAccessToken

func (m *JWTManager) GenerateAccessToken(claims Claims) (string, error)

func (*JWTManager) GenerateRefreshToken

func (m *JWTManager) GenerateRefreshToken(claims Claims) (string, error)

func (*JWTManager) GenerateTemporaryToken

func (m *JWTManager) GenerateTemporaryToken(claims Claims, duration time.Duration) (string, error)

func (*JWTManager) GetConfig

func (m *JWTManager) GetConfig() JWTConfig

func (*JWTManager) RefreshAccessToken

func (m *JWTManager) RefreshAccessToken(refreshTokenString string) (string, error)

func (*JWTManager) ValidateTemporaryToken

func (m *JWTManager) ValidateTemporaryToken(tokenString string) (*Claims, error)

func (*JWTManager) ValidateToken

func (m *JWTManager) ValidateToken(tokenString string) (*Claims, error)

type MemorySessionStore

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

MemorySessionStore es una implementación en memoria de SessionStore. NO es adecuada para producción (no persiste, no es distribuida). Úsala solo para desarrollo, testing o aplicaciones de un solo proceso.

func NewMemorySessionStore

func NewMemorySessionStore() *MemorySessionStore

NewMemorySessionStore crea un nuevo almacenamiento en memoria.

func (*MemorySessionStore) CleanExpired

func (s *MemorySessionStore) CleanExpired() (int, error)

CleanExpired elimina todas las sesiones expiradas.

func (*MemorySessionStore) Delete

func (s *MemorySessionStore) Delete(sessionID string) error

Delete elimina una sesión.

func (*MemorySessionStore) DeleteByUserID

func (s *MemorySessionStore) DeleteByUserID(userID string) error

DeleteByUserID elimina todas las sesiones de un usuario.

func (*MemorySessionStore) Get

func (s *MemorySessionStore) Get(sessionID string) (*Session, error)

Get recupera una sesión por su ID. Devuelve una copia para que las modificaciones del llamador (p. ej. actualizar LastActivityAt antes de llamar a Save) no muten el estado interno del store fuera de su mutex.

func (*MemorySessionStore) GetByUserID

func (s *MemorySessionStore) GetByUserID(userID string) ([]*Session, error)

GetByUserID recupera todas las sesiones de un usuario. Devuelve copias por la misma razón que Get.

func (*MemorySessionStore) Save

func (s *MemorySessionStore) Save(session *Session) error

Save guarda una sesión en memoria.

type Session

type Session struct {
	// ID es el identificador único de la sesión (generado criptográficamente).
	ID string

	// UserID es el identificador del usuario propietario de la sesión.
	UserID string

	// Username es el nombre de usuario (opcional, para logging/auditoría).
	Username string

	// IPAddress es la IP desde donde se creó la sesión.
	IPAddress string

	// UserAgent es el User-Agent del navegador/cliente.
	UserAgent string

	// DeviceInfo contiene información adicional del dispositivo (opcional).
	DeviceInfo string

	// CreatedAt es el momento en que se creó la sesión.
	CreatedAt time.Time

	// LastActivityAt es el momento de la última actividad del usuario.
	// Se actualiza en cada validación exitosa para implementar idle timeout.
	LastActivityAt time.Time

	// ExpiresAt es el momento de expiración absoluta de la sesión.
	// Después de este tiempo, la sesión es inválida sin importar la actividad.
	ExpiresAt time.Time

	// IdleTimeout es el tiempo máximo de inactividad permitido.
	// Si pasa más tiempo que esto desde LastActivityAt, la sesión expira.
	IdleTimeout time.Duration

	// IsValid indica si la sesión está activa (no ha sido revocada).
	IsValid bool

	// RevokedAt es el momento en que la sesión fue revocada (si aplica).
	// Si es zero, la sesión no ha sido revocada.
	RevokedAt time.Time

	// RevokeReason indica la razón de la revocación (opcional, para auditoría).
	RevokeReason string
}

Session representa una sesión de usuario autenticada. Contiene toda la información necesaria para validar y auditar la sesión a lo largo de su ciclo de vida.

func GetQuickUserSessions

func GetQuickUserSessions(userID string) ([]*Session, error)

GetQuickUserSessions obtiene las sesiones activas de un usuario.

func ValidateQuickSession

func ValidateQuickSession(sessionID string) (*Session, error)

ValidateQuickSession valida una sesión usando el manager global.

func (*Session) IsActive

func (s *Session) IsActive() bool

IsActive verifica si la sesión está activa (válida y no expirada).

func (*Session) IsExpired

func (s *Session) IsExpired() bool

IsExpired verifica si la sesión ha expirado por tiempo absoluto o inactividad.

type SessionConfig

type SessionConfig struct {
	// SessionTimeout es el tiempo máximo absoluto de vida de una sesión.
	// Si es 0, se usa el valor predeterminado del nivel de seguridad.
	SessionTimeout time.Duration

	// IdleTimeout es el tiempo máximo de inactividad permitido.
	// Si es 0, se usa el valor predeterminado del nivel de seguridad.
	IdleTimeout time.Duration

	// MaxConcurrentSessions es el número máximo de sesiones activas por usuario.
	// Si es 0, se usa el valor predeterminado del nivel de seguridad.
	// Cuando se supera este límite, las sesiones más antiguas se revocan.
	MaxConcurrentSessions int

	// SecurityLevel define el nivel de seguridad para usar valores predeterminados.
	// Si no se especifica, se usa LevelMedium.
	SecurityLevel security.Level

	// Store es el almacenamiento de sesiones a utilizar.
	// Si es nil, se usa MemorySessionStore (solo para desarrollo/testing).
	Store SessionStore
}

SessionConfig define la configuración para el manager de sesiones.

type SessionInfo

type SessionInfo struct {
	UserID     string
	Username   string
	IPAddress  string
	UserAgent  string
	DeviceInfo string
}

CreateSession crea una nueva sesión para el usuario especificado. Si el usuario ya tiene el máximo de sesiones concurrentes permitidas, las sesiones más antiguas se revocan automáticamente.

Retorna el ID de la nueva sesión, que debe ser enviado al cliente (típicamente en una cookie HttpOnly o en el cuerpo de la respuesta).

Ejemplo de uso:

sessionID, err := sessionManager.CreateSession(token.SessionInfo{
    UserID:    "user-123",
    Username:  "john_doe",
    IPAddress: "192.168.1.100",
    UserAgent: "Mozilla/5.0...",
})
if err != nil {
    // Manejar error
}
// Enviar sessionID al cliente (cookie o respuesta)

type SessionManager

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

SessionManager maneja el ciclo de vida completo de las sesiones de usuario.

func GetDefaultSession

func GetDefaultSession() *SessionManager

GetDefaultSession devuelve la instancia global actual del SessionManager.

func NewSessionManager

func NewSessionManager(config SessionConfig) *SessionManager

NewSessionManager crea un nuevo manager de sesiones con la configuración proporcionada. Si no se especifica un Store, se usa MemorySessionStore (solo para desarrollo).

IMPORTANTE: Para producción, DEBES proporcionar un SessionStore persistente (Redis, base de datos, etc.). MemorySessionStore pierde datos al reiniciar.

Ejemplo de uso:

// Con valores predeterminados del nivel de seguridad
manager := token.NewSessionManager(token.SessionConfig{
    SecurityLevel: security.LevelHigh,
})

// Con configuración personalizada y Redis (ejemplo conceptual)
manager := token.NewSessionManager(token.SessionConfig{
    SessionTimeout:        8 * time.Hour,
    IdleTimeout:           15 * time.Minute,
    MaxConcurrentSessions: 2,
    Store:                 redisStore, // Implementación personalizada
})

func (*SessionManager) CleanExpiredSessions

func (m *SessionManager) CleanExpiredSessions() (int, error)

CleanExpiredSessions elimina todas las sesiones expiradas del almacenamiento. Debe llamarse periódicamente (ej. cada hora con un cron job) para evitar que el almacenamiento crezca indefinidamente.

Ejemplo de uso:

// En un goroutine de mantenimiento
go func() {
    ticker := time.NewTicker(1 * time.Hour)
    for range ticker.C {
        cleaned, _ := sessionManager.CleanExpiredSessions()
        log.Info("Sesiones expiradas limpiadas: %d", cleaned)
    }
}()

func (*SessionManager) CreateSession

func (m *SessionManager) CreateSession(info SessionInfo) (string, error)

func (*SessionManager) GetConfig

func (m *SessionManager) GetConfig() SessionConfig

GetConfig retorna la configuración actual del manager.

func (*SessionManager) GetSession

func (m *SessionManager) GetSession(sessionID string) (*Session, error)

GetSession recupera una sesión por su ID. Retorna ErrSessionNotFound si la sesión no existe.

func (*SessionManager) GetUserSessions

func (m *SessionManager) GetUserSessions(userID string) ([]*Session, error)

GetUserSessions recupera todas las sesiones activas de un usuario. Útil para mostrar al usuario "Dónde estás conectado" en su perfil.

Ejemplo de uso:

sessions, err := sessionManager.GetUserSessions("user-123")
for _, s := range sessions {
    fmt.Printf("Sesión desde %s, creada en %s\n", s.IPAddress, s.CreatedAt)
}

func (*SessionManager) RevokeAllUserSessions

func (m *SessionManager) RevokeAllUserSessions(userID, reason string) error

RevokeAllUserSessions revoca todas las sesiones de un usuario. Útil para:

  • Cambio de contraseña (invalidar todas las sesiones anteriores)
  • Sospecha de compromiso de cuenta
  • Logout global ("cerrar sesión en todos los dispositivos")

Ejemplo de uso:

err := sessionManager.RevokeAllUserSessions("user-123", "password_changed")

func (*SessionManager) RevokeSession

func (m *SessionManager) RevokeSession(sessionID, reason string) error

RevokeSession revoca una sesión específica (logout).

Ejemplo de uso:

err := sessionManager.RevokeSession(sessionID, "user_logout")

func (*SessionManager) ValidateSession

func (m *SessionManager) ValidateSession(sessionID string) (*Session, error)

ValidateSession valida una sesión y actualiza su tiempo de última actividad. Retorna la sesión si es válida, o un error si está expirada, revocada o no existe.

Este método debe llamarse en CADA request autenticado para:

  • Verificar que la sesión sigue activa
  • Actualizar el LastActivityAt (para idle timeout)
  • Detectar sesiones revocadas (logout en otro dispositivo)

Ejemplo de uso:

session, err := sessionManager.ValidateSession(sessionID)
if err != nil {
    // Sesión inválida, requerir re-login
    return security.ErrSessionExpired
}
// Sesión válida, continuar con el request
userID := session.UserID

type SessionStore

type SessionStore interface {
	// Save guarda una sesión en el almacenamiento.
	Save(session *Session) error

	// Get recupera una sesión por su ID.
	// Retorna ErrSessionNotFound si no existe.
	Get(sessionID string) (*Session, error)

	// GetByUserID recupera todas las sesiones activas de un usuario.
	GetByUserID(userID string) ([]*Session, error)

	// Delete elimina una sesión del almacenamiento.
	Delete(sessionID string) error

	// DeleteByUserID elimina todas las sesiones de un usuario.
	DeleteByUserID(userID string) error

	// CleanExpired elimina todas las sesiones expiradas del almacenamiento.
	// Útil para tareas de mantenimiento periódico.
	CleanExpired() (int, error)
}

SessionStore define el contrato para los backends de almacenamiento de sesiones. Esta abstracción permite usar diferentes backends (memoria, Redis, base de datos) sin modificar el código del manager.

Jump to

Keyboard shortcuts

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