Gestione delle password
Configura in Potato l'hashing delle password PBKDF2-SHA256, il reset da CLI o API di amministrazione, i link di reset self-service con token e l'archiviazione delle credenziali su SQLite o PostgreSQL.
Novità della v2.4.0
Il sistema di autenticazione di Potato usa PBKDF2-SHA256 con 100.000 iterazioni e un salt per ogni utente, l'approccio raccomandato dal NIST per l'archiviazione sicura delle password. Questa pagina spiega come vengono conservate le password, come reimpostarle e come far sopravvivere le credenziali ai riavvii del server.
Riguarda i metodi in_memory e database. Con OAuth è il provider di identità a gestire la password, quindi nulla di tutto questo si applica, se non agli account locali in modalità mista.
Implementazione della sicurezza
Le password sono conservate nel formato salt$hash:
- salt esadecimale di 32 caratteri, diverso per ogni utente
- digest esadecimale di 64 caratteri, derivato con PBKDF2-HMAC-SHA256 dalla password con quel salt e 100.000 iterazioni
- confronto a tempo costante tramite
hmac.compare_digestper prevenire gli attacchi temporali
Un singolo passaggio di SHA-256 su una password con salt è abbastanza veloce da consentire un attacco a forza bruta su larga scala. Sono le 100.000 iterazioni a rendere costoso ogni tentativo.
Le password in chiaro già presenti nei file user_config.json vengono ricalcolate in automatico come hash con salt univoci quando Potato le carica, senza alcuna migrazione manuale.
Configurazione predefinita
Per impostazione predefinita Potato usa l'autenticazione in memoria. require_password è una chiave di primo livello e non fa parte del blocco 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"Credenziali persistenti
Gli account creati tramite il modulo di registrazione vengono scritti in un file JSONL e riletti all'avvio successivo. Con in_memory quel file è user_config.json, accanto alla directory di output, a meno che non ne indichi un altro.
Persistenza su file
authentication:
method: in_memory
user_config_path: /shared/path/to/user_config.jsonlIndica un percorso quando più istanze del server condividono lo stesso elenco di utenti, oppure quando vuoi tenere l'elenco altrove rispetto alle annotazioni. Le nuove registrazioni e i cambi di password vengono scritti nel momento in cui avvengono.
Conserva l'elenco degli utenti insieme all'output delle annotazioni. La directory di un annotatore prende il nome dal suo nome utente. Se l'elenco degli utenti va perso mentre la directory di output resta, la prossima persona che digita quel nome utente erediterebbe il lavoro di qualcun altro. Per questo Potato rifiuta la registrazione, e l'annotatore non può rientrare finché non ripristini il file.
Prima della v2.8.3, in_memory non scriveva nulla se user_config_path non era impostato esplicitamente, quindi gli account non sopravvivevano a un riavvio. Se hai condotto uno studio con una build precedente, quegli account sono persi; le annotazioni no.
Backend su database
SQLite (nessuna dipendenza aggiuntiva):
authentication:
method: database
database_url: "sqlite:///auth/users.db"PostgreSQL (richiede psycopg2-binary):
authentication:
method: database
database_url: "postgresql://user:password@localhost:5432/potato_auth"Potato crea la tabella users al primo avvio ed esegue SQLite in modalità WAL per migliorare le letture concorrenti. database_url deve iniziare con sqlite:/// o postgresql://. Puoi anche impostare POTATO_DB_CONNECTION nell'ambiente; se sono presenti entrambi, prevale database_url.
Nota: method: database e user_config_path si escludono a vicenda, quindi scegli una sola strategia di persistenza. Potato genera un errore se sono configurati entrambi.
Reimpostare le password
CLI di amministrazione
Reimposta una password dalla riga di comando:
# Prompts for username and password
potato reset-password config.yaml
# Prompts for the password only
potato reset-password config.yaml --username annotator1API di amministrazione
Reimposta la password via codice con la chiave API di amministrazione:
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 chiave proviene, in quest'ordine, dall'impostazione di primo livello admin_api_key, dalla variabile d'ambiente POTATO_ADMIN_API_KEY o da un file admin_api_key.txt generato nella directory del task.
Reset self-service con token
Gli annotatori che dimenticano la password possono reimpostarla da soli. Vanno su /forgot-password e inseriscono il proprio nome utente, e Potato genera un token monouso valido 24 ore. Il link di reset compare sullo schermo perché un amministratore lo inoltri; Potato non invia email. L'annotatore apre /reset/<token> e imposta una nuova password, consumando così il token.
Il flusso non richiede alcuna configurazione. Quando è impostato require_password: true, nella pagina di accesso compare un link "Forgot Password?".
Gli amministratori possono anche generare direttamente un token:
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}Passa "ttl_hours": 48 nel corpo della richiesta per una scadenza diversa.
Modalità senza password
Per le dimostrazioni in aula, gli studi rapidi o i compiti che usano un'autenticazione esterna (MTurk, Prolific), puoi disattivare del tutto le password:
require_password: false
authentication:
method: in_memoryGli annotatori entrano indicando un nome utente qualsiasi, senza che compaia la richiesta della password. Sconsigliato per dati sensibili o per compiti in cui l'identità va verificata.
Vedi Accesso Senza Password per i dettagli.
Riferimento completo
# 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 | Metodo | Autenticazione | Descrizione |
|---|---|---|---|
/forgot-password | GET, POST | nessuna | Richiede un token di reset |
/reset/<token> | GET, POST | nessuna | Imposta una nuova password |
/admin/reset_password | POST | chiave API | Reset della password da parte dell'amministratore |
/admin/create_reset_token | POST | chiave API | Genera un token di reset |
Ulteriori letture
- Autenticazione SSO e OAuth: accesso con Google, GitHub o SSO istituzionale
- Accesso Senza Password: accesso con il solo nome utente per i compiti aperti
- Configurazione di produzione: HTTPS e configurazione del reverse proxy
- Dashboard di Amministrazione: gestione degli account degli annotatori
Per i dettagli implementativi, vedi la documentazione sorgente.