🔐 Autenticación
Esta guía cubre todos los métodos de autenticación con el SDK toDus.
Métodos de Autenticación
El SDK soporta dos formas principales de autenticación:
1. Autenticación con Contraseña
La forma más simple y recomendada para bots y aplicaciones estables.
from todus import ToDusClient2
client = ToDusClient2(
phone_number="5312345678",
password="tu_contraseña"
)
# Iniciar sesión
token = client.login()
print(f"Sesión iniciada. Token: {token[:20]}...")
Ventajas: - ✅ Simple y rápido - ✅ Seguro si usas HTTPS - ✅ Ideal para bots permanentes
Desventajas: - ❌ Requiere almacenar la contraseña - ❌ Si se compromete, acceso total a la cuenta
2. Autenticación con Código SMS
Útil para aplicaciones móviles o cuando no tienes la contraseña disponible.
from todus import ToDusClient
# Paso 1: Solicitar código
client = ToDusClient()
result = client.request_code(phone_number="5312345678")
print(f"Código enviado a: {result.get('phone_number')}")
# Paso 2: Validar el código recibido vía SMS
code = input("Ingresa el código SMS: ")
token = client.validate_code(phone_number="5312345678", code=code)
print(f"Autenticado. Token: {token[:20]}...")
Flujo completo:
from todus import ToDusClient
from todus.errors import AuthenticationError
client = ToDusClient()
phone = "5312345678"
try:
# Solicitar código
print("Solicitando código SMS...")
client.request_code(phone)
# Esperar entrada del usuario
code = input(f"Ingresa el código SMS enviado a +{phone}: ")
# Validar código
token = client.validate_code(phone, code)
print("✅ Autenticación exitosa")
# Ahora puedes usar el token para enviar mensajes
msg_id = client.send_message(token, "5387654321@im.todus.cu", "Hola!")
print(f"Mensaje enviado: {msg_id}")
except AuthenticationError as e:
print(f"❌ Error de autenticación: {e}")
Ventajas: - ✅ No requiere almacenar contraseña - ✅ Más seguro para aplicaciones públicas - ✅ Permite cambio de contraseña sin afectar
Desventajas: - ❌ Requiere acceso a SMS - ❌ Token tiene duración limitada - ❌ Más pasos en el flujo
Manejo de Tokens
El token es un JWT que expira después de cierto tiempo.
Obtener el Token
client = ToDusClient2("5312345678", "password")
token = client.login() # Obtiene y almacena el token
# El token se guarda automáticamente
print(client.token) # Acceder al token actual
Token Expirado
Si el token expira, obtendrás un error:
from todus.errors import TokenExpiredError
try:
client.send_message("5387654321", "Hola")
except TokenExpiredError:
print("Token expirado, reauthenticando...")
client.login() # Vuelve a autenticarse
client.send_message("5387654321", "Hola")
Decodificar Token
Para obtener información del token sin contactar el servidor:
from todus.util import jwt_decode_payload
payload = jwt_decode_payload(token)
print(f"Usuario: {payload.get('username')}")
print(f"Expira en: {payload.get('exp')}")
Buenas Prácticas de Seguridad
✅ Usa Variables de Entorno
Nunca hardcodees credenciales:
import os
from dotenv import load_dotenv
from todus import ToDusClient2
load_dotenv()
phone = os.getenv("TODUS_PHONE")
password = os.getenv("TODUS_PASSWORD")
client = ToDusClient2(phone, password)
client.login()
Archivo .env:
✅ Guarda Credenciales de Forma Segura
Para aplicaciones que necesitan múltiples cuentas:
import json
from cryptography.fernet import Fernet
# Generar clave (hazlo una sola vez)
# key = Fernet.generate_key()
cipher = Fernet(key)
credentials = {
"phone": "5312345678",
"password": "password123"
}
# Encriptar
encrypted = cipher.encrypt(json.dumps(credentials).encode())
with open("creds.enc", "wb") as f:
f.write(encrypted)
# Desencriptar
with open("creds.enc", "rb") as f:
encrypted = f.read()
decrypted = json.loads(cipher.decrypt(encrypted).decode())
print(decrypted)
✅ Manejo de Errores
from todus.errors import AuthenticationError, TokenExpiredError
try:
client.login()
except AuthenticationError as e:
print(f"Credenciales inválidas: {e}")
# No reintentar inmediatamente
except TokenExpiredError:
print("Token expirado, reauthenticando...")
client.login()
except Exception as e:
print(f"Error inesperado: {e}")
Estados de Autenticación
# Verificar si está autenticado
if client.logged:
print("Cliente autenticado")
print(f"Usuario: {client.phone_number}")
print(f"Token: {client.token[:20]}...")
else:
print("Cliente no autenticado")
client.login()
Ejemplo: Bot con Reauthenticación Automática
from todus import ToDusClientWithQueue
from todus.errors import TokenExpiredError
import time
class RobotPersistente:
def __init__(self, phone, password):
self.client = ToDusClientWithQueue(phone, password)
self.client.login()
def send_with_retry(self, to_phone, message, max_retries=3):
for attempt in range(max_retries):
try:
return self.client.send_message_queued(to_phone, message)
except TokenExpiredError:
print(f"Token expirado, reauthenticando (intento {attempt+1}/{max_retries})")
self.client.login()
if attempt == max_retries - 1:
raise
time.sleep(1)
def listen_with_reconnect(self, callback):
while True:
try:
self.client.listen_messages(self.client.token, callback)
except Exception as e:
print(f"Conexión perdida: {e}")
print("Reauthenticando en 10 segundos...")
time.sleep(10)
self.client.login()
# Uso
bot = RobotPersistente("5312345678", "password")
bot.send_with_retry("5387654321", "Hola desde mi bot")
Preguntas Frecuentes
P: ¿Cuánto dura un token? R: Los tokens típicamente duran 24-48 horas. El SDK maneja automáticamente la reauthenticación.
P: ¿Puedo usar el mismo token en múltiples dispositivos? R: Técnicamente sí, pero no es recomendado. Cada dispositivo debería autenticarse por separado.
P: ¿Qué sucede si uso credenciales incorrectas? R: Se lanzará una AuthenticationError. No será posible recuperarse sin credenciales válidas.
P: ¿Es seguro guardar el token en disco? R: No. Siempre encripta tokens almacenados. Es mejor volver a autenticarse cada vez.
P: ¿Puedo revocar un token? R: Cambiando la contraseña se revocan todos los tokens activos.