← casi-studio /

wp-auth-ai-gate

// caso-studio

Auth Gate per AI

Registrazione e login frontend su WordPress con double opt-in, usati come cancello per un assistente AI (Voiceflow) - solo gli utenti verificati parlano col bot, che li accoglie per nome.

WordPressPHPVoiceflowreCAPTCHA v3WPML
Auth Gate per AI

Progetto che ho sviluppato in agenzia, partendo da spec e piano scritti prima del codice. Niente nomi e niente codice reale: gli snippet sono riscritti e semplificati per illustrare l'approccio.

Cos'è

Un cliente voleva offrire un assistente AI (Voiceflow) solo ai propri clienti registrati. WordPress però non ha un flusso di registrazione frontend decente: wp-login.php è brutto, non fa double opt-in e non c'entra nulla col brand. Questo plugin costruisce l'intera esperienza — registrazione, verifica email, login, recupero password — e usa lo stato di autenticazione come interruttore dell'assistente: loggato e verificato → widget di chat che ti saluta per nome; anonimo → un badge che ti invita a registrarti.

Il problema

Tre vincoli: gli account dovevano essere utenti WordPress veri (per non inventare un secondo concetto di sessione), la verifica email doveva essere obbligatoria prima del primo accesso, e nulla di tutto questo doveva avvicinarsi a wp-admin — un cliente registrato non deve mai vedere la dashboard.

Come funziona

  • Ruolo dedicato con la sola capability read; wp-admin viene bloccato a priorità 1 con redirect, e l'admin bar nascosta — con via di fuga per gli account promossi a editor in seguito
  • Double opt-in: il token di verifica (40 caratteri) è salvato hashato con TTL di 24 ore e confrontato con hash_equals(); al click l'utente viene attivato e loggato in automatico
  • Una pagina, cinque viste: registrazione, login, recupero, reset e "conferma la tua email" sono sibling nello stesso template; un JS vanilla da ~100 righe mostra la vista che il server indica nella risposta — anche negli errori
  • Igiene automatica: un cron mensile elimina gli account mai verificati dopo 30 giorni
  • Recupero password su primitive core (get_password_reset_key / reset_password), sessioni invalidate dopo ogni reset, copy admin-editabile e registrato in WPML

Dettagli di cui vado fiero

La difesa dall'enumeration, fatta nell'ordine giusto. Il flusso di login verifica la password prima di rivelare che un account esiste ma non è verificato — nell'ordine inverso, chiunque potrebbe scoprire quali email sono registrate. Stessa filosofia su recupero e reinvio: risposta generica identica sia che l'email esista sia che no, con un rate limit che resta invisibile proprio grazie alla risposta uniforme.

// Prima la password, poi lo stato: l'ordine inverso rivelerebbe
// a chiunque quali email hanno un account.
if ( ! $user || ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
  return $this->fail( __( 'Credenziali non valide.' ), 'login' );
}
if ( get_user_meta( $user->ID, 'account_status', true ) === 'pending' ) {
  return $this->ok( __( 'Conferma la tua email per accedere.' ), 'pending' );
}

Il contesto utente arriva all'AI senza backend in mezzo. Quando un utente verificato apre una pagina, il plugin scrive un cookie first-party di un'ora con id, email e nome; il widget lo legge client-side e personalizza il saluto. Niente API custom, niente sincronizzazione di stato: il cookie è il contratto.

Hardening contro lo script-breakout. L'ID del progetto Voiceflow configurato dall'admin finisce dentro un tag <script>: viene serializzato con wp_json_encode(..., JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT), così un eventuale </script> nel valore resta inerte anche se la sanitizzazione a monte dovesse regredire un domani.

Il server guida la UI. Ogni risposta JSON — successo o errore — può indicare la prossima vista da mostrare. "Credenziali giuste ma email non confermata" porta alla vista pending senza reload e senza che il client debba conoscere la logica: il frontend è stupido apposta.

Cosa ho imparato

  • L'autenticazione è fatta di ordinamenti: cosa verifichi prima di cosa riveli, cosa hashi prima di cosa salvi
  • Riusare le primitive core di WordPress (auth cookie, reset key, ruoli) batte reinventarle: meno codice mio da difendere
  • Una state machine guidata dal server rende il client banale e i flussi testabili
_casi-studio
Apri la palette per cercare file e navigare