Gestión de contraseñas
Configura en Potato el hash de contraseñas con PBKDF2-SHA256, el restablecimiento desde la CLI y la API de administración, los enlaces de restablecimiento con token de autoservicio y el almacenamiento de credenciales en SQLite o PostgreSQL.
Novedad en la v2.4.0
El sistema de autenticación de Potato usa PBKDF2-SHA256 con 100.000 iteraciones y una sal distinta por usuario, el mismo enfoque que recomienda el NIST para almacenar contraseñas de forma segura. Esta página explica cómo se guardan las contraseñas, cómo restablecerlas y cómo conservar las credenciales entre reinicios del servidor.
Se aplica a los métodos in_memory y database. Con OAuth, la contraseña es cosa del proveedor de identidad, así que nada de esto aplica salvo a las cuentas locales en modo mixto.
Implementación de seguridad
Las contraseñas se guardan en formato salt$hash:
- Sal hexadecimal de 32 caracteres, única para cada usuario
- Resumen hexadecimal de 64 caracteres, obtenido con PBKDF2-HMAC-SHA256 sobre la contraseña con esa sal y 100.000 iteraciones
- Comparación en tiempo constante mediante
hmac.compare_digestpara evitar ataques de temporización
Una sola pasada de SHA-256 sobre una contraseña con sal es lo bastante rápida como para atacarla por fuerza bruta a gran escala. Las 100.000 iteraciones son lo que encarece cada intento.
Las contraseñas en texto plano que ya existan en archivos user_config.json se vuelven a hashear automáticamente con sales únicas cuando Potato las carga, sin necesidad de ninguna migración manual.
Configuración predeterminada
De forma predeterminada, Potato usa autenticación en memoria. require_password es una clave de nivel superior y no forma parte del bloque authentication:
require_password: true
authentication:
method: in_memory
user_config:
users:
- username: "annotator1"
password: "initial-password" # will be hashed on first load
- username: "annotator2"
password: "initial-password"Credenciales persistentes
Las cuentas creadas mediante el formulario de registro se escriben en un archivo JSONL y se vuelven a leer en el siguiente arranque. Con in_memory, ese archivo es user_config.json, junto al directorio de salida, salvo que indiques otro.
Persistencia en archivo
authentication:
method: in_memory
user_config_path: /shared/path/to/user_config.jsonlIndica una ruta cuando varias instancias del servidor comparten una misma lista de usuarios, o cuando quieres guardar la lista en un lugar distinto al de las anotaciones. Los registros nuevos y los cambios de contraseña se escriben en el momento en que ocurren.
Guarda la lista de usuarios junto con la salida de anotación. El directorio de cada anotador lleva su nombre de usuario, así que si la lista se pierde pero el directorio de salida se conserva, la siguiente persona que escriba ese nombre de usuario heredaría el trabajo de otra. Potato rechaza el registro en ese caso, lo que significa que el anotador no puede volver a entrar hasta que restaures el archivo.
Antes de la v2.8.3, in_memory no escribía nada salvo que user_config_path estuviera definido explícitamente, así que las cuentas no sobrevivían a un reinicio. Si ejecutaste un estudio con una versión anterior, esas cuentas se han perdido; las anotaciones no.
Backend de base de datos
SQLite (sin dependencias adicionales):
authentication:
method: database
database_url: "sqlite:///auth/users.db"PostgreSQL (requiere psycopg2-binary):
authentication:
method: database
database_url: "postgresql://user:password@localhost:5432/potato_auth"Potato crea la tabla users en el primer arranque y ejecuta SQLite en modo WAL para mejorar las lecturas concurrentes. database_url debe empezar por sqlite:/// o postgresql://. También puedes definir POTATO_DB_CONNECTION en el entorno; si ambos están presentes, database_url tiene prioridad.
Nota: method: database y user_config_path son mutuamente excluyentes, así que elige una sola estrategia de persistencia. Potato genera un error si se configuran los dos.
Restablecer contraseñas
CLI de administración
Restablece una contraseña desde la línea de comandos:
# Prompts for username and password
potato reset-password config.yaml
# Prompts for the password only
potato reset-password config.yaml --username annotator1API de administración
Restablece la contraseña mediante programación con la clave de API de administración:
curl -X POST http://localhost:8000/admin/reset_password \
-H "X-API-Key: $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username": "annotator1", "new_password": "new-secure-password"}'La clave se toma, por este orden, del ajuste de nivel superior admin_api_key, de la variable de entorno POTATO_ADMIN_API_KEY o de un archivo admin_api_key.txt generado en el directorio de la tarea.
Restablecimiento de autoservicio con token
Los anotadores que olvidan su contraseña pueden restablecerla por su cuenta. Entran en /forgot-password y escriben su nombre de usuario, y Potato genera un token de un solo uso válido durante 24 horas. El enlace de restablecimiento se muestra en pantalla para que un administrador lo haga llegar; Potato no envía correos. El anotador abre /reset/<token> y define una contraseña nueva, lo que consume el token.
El flujo no necesita configuración. Cuando require_password: true está activado, aparece un enlace "Forgot Password?" en la página de inicio de sesión.
Los administradores también pueden generar un token directamente:
curl -X POST http://localhost:8000/admin/create_reset_token \
-H "X-API-Key: $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username": "annotator1"}'
# {"reset_link": "http://localhost:8000/reset/abc123...",
# "token": "abc123...", "expires_in_hours": 24}Pasa "ttl_hours": 48 en el cuerpo de la solicitud para usar otra caducidad.
Modo sin contraseña
Para demostraciones en clase, estudios rápidos o tareas que usan autenticación externa (MTurk, Prolific), puedes desactivar las contraseñas por completo:
require_password: false
authentication:
method: in_memoryLos anotadores escriben cualquier nombre de usuario para entrar y no aparece ninguna petición de contraseña. No es recomendable con datos sensibles ni en tareas que exijan identidad verificada.
Consulta Inicio de Sesión sin Contraseña para más detalles.
Referencia completa
# Top-level: require a password at login (default: true)
require_password: true
# Top-level: key for the admin endpoints
admin_api_key: ${POTATO_ADMIN_API_KEY}
authentication:
# in_memory (default) | database | clerk | oauth
method: in_memory
# in_memory only, mutually exclusive with method: database
user_config_path: users.jsonl
# database only; sqlite:/// or postgresql://
# database_url: "sqlite:///auth.db"
user_config:
users:
- username: "researcher"
password: "secure-passphrase"
- username: "annotator1"
password: "initial-pass"| Endpoint | Método | Autenticación | Descripción |
|---|---|---|---|
/forgot-password | GET, POST | ninguna | Solicitar un token de restablecimiento |
/reset/<token> | GET, POST | ninguna | Definir una contraseña nueva |
/admin/reset_password | POST | clave de API | Restablecimiento de contraseña por un administrador |
/admin/create_reset_token | POST | clave de API | Generar un token de restablecimiento |
Lecturas adicionales
- Autenticación SSO y OAuth: inicio de sesión con Google, GitHub o el SSO de tu institución
- Inicio de Sesión sin Contraseña: acceso solo con nombre de usuario para tareas abiertas
- Configuración de producción: HTTPS y configuración del proxy inverso
- Panel de Administración: gestión de las cuentas de anotador
Para detalles de implementación, consulta la documentación fuente.