Skip to content

Auth (Identidad y Acceso)

El módulo de Auth es el guardián de la seguridad en Yastubo. No solo gestiona quién puede entrar al sistema, sino qué acciones puede realizar según su rol y pertenencia a un espacio de trabajo (Company).

  • Durable Sessions: Implementación de tokens de acceso (JWT) y de refresco (Redis) para sesiones seguras y persistentes.
  • Audit-First Design: Cada registro y asignación de rol se audita automáticamente mediante decoradores de sistema.
  • RBAC Nativo: Soporte para roles como ADMIN, VENDEDOR y CLIENTE desde el núcleo.
  • Cifrado Robusto: Uso de algoritmos de hash modernos para la protección de credenciales.

El sistema utiliza una arquitectura de doble token:

  1. Access Token (JWT): Contiene los roles y el user_id. Se envía en el header Authorization: Bearer.
  2. Refresh Token: Un identificador único almacenado en Redis vinculado al usuario. Se utiliza exclusivamente para obtener un nuevo par de tokens sin requerir las credenciales nuevamente.

Al registrar un nuevo usuario, el sistema:

  • Verifica la unicidad del email.
  • Genera un hash de la contraseña usando bcrypt (o similar).
  • Asigna automáticamente el rol CLIENTE.
  • Crea una entrada en el log de auditoría (USER_REGISTERED).

Los roles no son simples strings; están vinculados a capacidades dentro del sistema. La asignación de roles requiere privilegios de ADMIN y se rastrea quién realizó la asignación.

A continuación, un ejemplo de cómo se implementa el registro de un usuario en el servicio de backend:

@audited(action="USER_REGISTERED", entity="User")
async def register_user(db: AsyncSession, data: UserRegister) -> User:
"""
Registra un nuevo usuario y le asigna el rol CLIENTE por defecto.
"""
# 1. Verificar si el correo ya existe para evitar duplicados
existing_user = await get_user_by_email(db, data.email)
if existing_user:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="El correo ya está registrado"
)
# 2. Cifrar la contraseña antes de guardarla
hashed_password = get_password_hash(data.password)
user = User(
email=data.email,
hashed_password=hashed_password,
full_name=data.full_name,
phone=data.phone,
is_active=True, # El usuario se activa inmediatamente
)
db.add(user)
await db.flush() # Obtenemos el ID generado
# 3. Asignación automática de rol inicial
role_result = await db.execute(select(Role).where(Role.name == "CLIENTE"))
cliente_role = role_result.scalar_one_or_none()
if cliente_role:
user_role = UserRole(user_id=user.id, role_id=cliente_role.id)
db.add(user_role)
await db.commit()
await db.refresh(user, ["roles"])
return user

Auth Flow

MétodoRutaDescripción
POST/api/v1/auth/registerRegistro de nuevos usuarios.
POST/api/v1/auth/loginIntercambio de credenciales por tokens.
POST/api/v1/auth/refreshRenovación de sesión usando Refresh Token.
GET/api/v1/auth/meObtención del perfil del usuario actual.